diff options
author | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-11-12 21:21:17 +0400 |
---|---|---|
committer | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-11-12 21:21:17 +0400 |
commit | 4a00214cc8703307df99bb4081459729cfa581ab (patch) | |
tree | 8ba6b30378e38530e2c7f54195bd4590b8f09c6e | |
parent | 02d755c37991dc1996644cf254a950c866e434c3 (diff) |
Re-factored if command execution visitor phase.
-rw-r--r-- | src/pclc/parser/command.py | 15 | ||||
-rw-r--r-- | src/pclc/parser/pcl_parser.py | 4 | ||||
-rw-r--r-- | src/pclc/visitors/do_executor_visitor.py | 42 | ||||
-rw-r--r-- | src/pclc/visitors/first_pass_resolver_visitor.py | 18 | ||||
-rw-r--r-- | src/pclc/visitors/second_pass_resolver_visitor.py | 4 | ||||
-rw-r--r-- | src/pclc/visitors/symbol_table.py | 3 |
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] |