Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ianj-als/pcl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Johnson <ian.johnson@appliedlanguage.com>2013-11-12 21:21:17 +0400
committerIan Johnson <ian.johnson@appliedlanguage.com>2013-11-12 21:21:17 +0400
commit4a00214cc8703307df99bb4081459729cfa581ab (patch)
tree8ba6b30378e38530e2c7f54195bd4590b8f09c6e
parent02d755c37991dc1996644cf254a950c866e434c3 (diff)
Re-factored if command execution visitor phase.
-rw-r--r--src/pclc/parser/command.py15
-rw-r--r--src/pclc/parser/pcl_parser.py4
-rw-r--r--src/pclc/visitors/do_executor_visitor.py42
-rw-r--r--src/pclc/visitors/first_pass_resolver_visitor.py18
-rw-r--r--src/pclc/visitors/second_pass_resolver_visitor.py4
-rw-r--r--src/pclc/visitors/symbol_table.py3
6 files changed, 53 insertions, 33 deletions
diff --git a/src/pclc/parser/command.py b/src/pclc/parser/command.py
index 9fc074b..ac749b4 100644
--- a/src/pclc/parser/command.py
+++ b/src/pclc/parser/command.py
@@ -143,25 +143,36 @@ class IfCommand(Entity, ResolutionSymbols):
def __init__(self, filename, lineno, commands, if_command):
IfCommand.Block.__init__(self, filename, lineno, commands, if_command)
+ class EndIf(Entity):
+ def __init__(self, filename, lineno, if_command):
+ Entity.__init__(self, filename, lineno)
+ self.if_command = if_command
+
+ def accept(self, visitor):
+ visitor.visit(self)
+
def __init__(self,
filename,
lineno,
identifier,
condition,
then_commands,
- else_commands):
+ else_commands,
+ endif_lineno):
Entity.__init__(self, filename, lineno)
ResolutionSymbols.__init__(self)
self.identifier = identifier
self.condition = condition
self.then_commands = IfCommand.ThenBlock(filename, then_commands[0].lineno, then_commands, self)
self.else_commands = IfCommand.ElseBlock(filename, else_commands[0].lineno, else_commands, self)
+ self.endif = IfCommand.EndIf(filename, endif_lineno, self)
def accept(self, visitor):
+ visitor.visit(self)
self.condition.accept(visitor)
self.then_commands.accept(visitor)
self.else_commands.accept(visitor)
- visitor.visit(self)
+ self.endif.accept(visitor)
def __str__(self):
f = lambda cmd: str(cmd)
diff --git a/src/pclc/parser/pcl_parser.py b/src/pclc/parser/pcl_parser.py
index 397a323..925b631 100644
--- a/src/pclc/parser/pcl_parser.py
+++ b/src/pclc/parser/pcl_parser.py
@@ -399,12 +399,12 @@ def p_do_command(p):
# len(p) == 12
p[6].append(p[7])
p[9].append(p[10])
- p[0].append(IfCommand(p.parser.filename, p[1].lineno, p[1], p[4], p[6], p[9]))
+ p[0].append(IfCommand(p.parser.filename, p[1].lineno, p[1], p[4], p[6], p[9], p.lineno(11)))
elif len(p) > 9:
# len(p) == 10
p[4].append(p[5])
p[7].append(p[8])
- p[0].append(IfCommand(p.parser.filename, p.lineno(1), None, p[2], p[4], p[7]))
+ p[0].append(IfCommand(p.parser.filename, p.lineno(1), None, p[2], p[4], p[7], p.lineno(9)))
elif len(p) > 6:
# len(p) == 7
p[0].append(LetCommand(p.parser.filename, p.lineno(1), p[1], p[4], p[6]))
diff --git a/src/pclc/visitors/do_executor_visitor.py b/src/pclc/visitors/do_executor_visitor.py
index 1e2d345..a198fc2 100644
--- a/src/pclc/visitors/do_executor_visitor.py
+++ b/src/pclc/visitors/do_executor_visitor.py
@@ -106,21 +106,22 @@ class IntermediateRepresentation(object):
self.__func_table = dict()
self.__func_no = 0
- def push_command_action(self, command):
- node = IntermediateRepresentation.IRCommandNode(command, self.__current_node)
+ def __add_node(self, node, update_current_node = True):
if node.parent is None:
self.__root.append(node)
else:
self.__current_node.add_child(node)
- self.__current_node = node
- def push_then_block(self, then_block):
- node = IntermediateRepresentation.IRIfNode(then_block.if_command, self.__current_node)
- if node.parent is None:
- self.__root.append(node)
- else:
- self.__current_node.add_child(node)
- self.__current_node = node
+ if update_current_node:
+ self.__current_node = node
+
+ def push_command_action(self, command):
+ node = IntermediateRepresentation.IRCommandNode(command, self.__current_node)
+ self.__add_node(node)
+
+ def push_if_action(self, if_command):
+ node = IntermediateRepresentation.IRIfNode(if_command, self.__current_node)
+ self.__add_node(node)
self.__current_if = node
def mark_else_block(self):
@@ -133,18 +134,11 @@ class IntermediateRepresentation(object):
def push_return_action(self, return_command):
node = IntermediateRepresentation.IRReturnNode(return_command, self.__current_node)
- if node.parent is None:
- self.__root.append(node)
- else:
- self.__current_node.add_child(node)
+ self.__add_node(node, False)
def push_let_action(self, let_command):
node = IntermediateRepresentation.IRLetNode(let_command, self.__current_node)
- if node.parent is None:
- self.__root.append(node)
- else:
- self.__current_node.add_child(node)
- self.__current_node = node
+ self.__add_node(node)
self.__current_let = node
def mark_let_end(self, let_expression_function):
@@ -248,7 +242,7 @@ class IntermediateRepresentation(object):
scope = return_command['scope']
if return_command.value:
- code.append(("return %s" % executor_visitor._generate_terminal(return_command.value, scope)))
+ code.append(("return %s" % executor_visitor._generate_terminal(return_command.value, scope), ""))
elif len(return_command.mappings) == 0:
code.append(("return None", ""))
else:
@@ -365,16 +359,20 @@ class DoExecutorVisitor(ExecutorVisitor):
@multimethod(IfCommand)
def visit(self, if_command):
- self.__ir.mark_endif()
+ self.__ir.push_if_action(if_command)
@multimethod(IfCommand.ThenBlock)
def visit(self, then_block):
- self.__ir.push_then_block(then_block)
+ pass
@multimethod(IfCommand.ElseBlock)
def visit(self, else_block):
self.__ir.mark_else_block()
+ @multimethod(IfCommand.EndIf)
+ def visit(self, end_if):
+ self.__ir.mark_endif()
+
@multimethod(LetCommand)
def visit(self, let_command):
self.__ir.push_let_action(let_command)
diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py
index eb4c1e4..6d26f1b 100644
--- a/src/pclc/visitors/first_pass_resolver_visitor.py
+++ b/src/pclc/visitors/first_pass_resolver_visitor.py
@@ -915,12 +915,12 @@ class FirstPassResolverVisitor(ResolverVisitor):
# Check if assignment variable has been used already. Code generation may not
# generate all code to provide the previous use!
- if identifier in self._current_scope:
- self._add_warnings("WARNING: %(filename)s at line %(lineno)d, duplicate assignment variable %(var_name)s",
- [identifier],
- lambda i: {'filename' : i.filename,
- 'lineno' : i.lineno,
- 'var_name' : i})
+ if self._current_scope.in_current_scope(identifier):
+ self._add_errors("ERROR: %(filename)s at line %(lineno)d, duplicate assignment variable %(var_name)s",
+ [identifier],
+ lambda i: {'filename' : i.filename,
+ 'lineno' : i.lineno,
+ 'var_name' : i})
else:
# Record the assignment and the command
self._current_scope[identifier] = assign_object
@@ -992,7 +992,7 @@ class FirstPassResolverVisitor(ResolverVisitor):
# Record the current scope in the entity's resolution symbols
if_command['scope'] = self._current_scope
- self._current_scope = self._current_scope.get_parent()
+ # Resolve the assignment if there is one
if if_command.identifier:
self.__resolve_assignment(if_command.identifier, if_command)
@@ -1009,6 +1009,10 @@ class FirstPassResolverVisitor(ResolverVisitor):
previous_scope.add_nested_scope(else_scope)
self._current_scope = else_scope
+ @multimethod(IfCommand.EndIf)
+ def visit(self, end_if):
+ self._current_scope = self._current_scope.get_parent()
+
@multimethod(LetCommand)
def visit(self, let_command):
# Record the current scope in the entity's resolution symbols
diff --git a/src/pclc/visitors/second_pass_resolver_visitor.py b/src/pclc/visitors/second_pass_resolver_visitor.py
index f384f94..ff682a7 100644
--- a/src/pclc/visitors/second_pass_resolver_visitor.py
+++ b/src/pclc/visitors/second_pass_resolver_visitor.py
@@ -151,6 +151,10 @@ class SecondPassResolverVisitor(FirstPassResolverVisitor):
def visit(self, else_block):
pass
+ @multimethod(IfCommand.EndIf)
+ def visit(self, end_if):
+ pass
+
@multimethod(LetCommand)
def visit(self, let_command):
pass
diff --git a/src/pclc/visitors/symbol_table.py b/src/pclc/visitors/symbol_table.py
index 98492c7..fe5cb37 100644
--- a/src/pclc/visitors/symbol_table.py
+++ b/src/pclc/visitors/symbol_table.py
@@ -29,6 +29,9 @@ class SymbolTable(object):
def get_parent(self):
return self.__parent
+ def in_current_scope(self, key):
+ return key in self.__table
+
def __getitem__(self, key):
return self.__table[key]