diff options
author | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-10-23 19:44:13 +0400 |
---|---|---|
committer | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-10-23 19:44:13 +0400 |
commit | 8360af279584a22cc0d27f2e3e15968f74e46ece (patch) | |
tree | c68bdfd954813e8c65b93a5a02500de3e4341cdf | |
parent | 7675a18cc6bd760b5bea34c216185c5cec6c8212 (diff) |
Do notation code generation started.
-rw-r--r-- | src/pclc/parser/command.py | 27 | ||||
-rw-r--r-- | src/pclc/visitors/do_executor_visitor.py | 270 | ||||
-rw-r--r-- | src/pclc/visitors/executor_visitor.py | 17 | ||||
-rw-r--r-- | src/pclc/visitors/first_pass_resolver_visitor.py | 6 |
4 files changed, 300 insertions, 20 deletions
diff --git a/src/pclc/parser/command.py b/src/pclc/parser/command.py index 875a900..ce23f25 100644 --- a/src/pclc/parser/command.py +++ b/src/pclc/parser/command.py @@ -74,7 +74,7 @@ class Return(Entity): def __init__(self, filename, lineno, - mappings): + mappings = list()): Entity.__init__(self, filename, lineno) self.mappings = mappings @@ -94,25 +94,32 @@ class Return(Entity): class IfCommand(Entity): class Block(Entity): - def __init__(self, filename, lineno, commands): + def __init__(self, filename, lineno, commands, if_command): Entity.__init__(self, filename, lineno) self.commands = commands + self.if_command = if_command + + def __getitem__(self, idx): + return self.commands[idx] def __iter__(self): return self.commands.__iter__() + def append(self, cmd): + self.commands.append(cmd) + def accept(self, visitor): visitor.visit(self) for cmd in self.commands: cmd.accept(visitor) class ThenBlock(Block): - def __init__(self, filename, lineno, commands): - IfCommand.Block.__init__(self, filename, lineno, commands) + def __init__(self, filename, lineno, commands, if_command): + IfCommand.Block.__init__(self, filename, lineno, commands, if_command) class ElseBlock(Block): - def __init__(self, filename, lineno, commands): - IfCommand.Block.__init__(self, filename, lineno, commands) + def __init__(self, filename, lineno, commands, if_command): + IfCommand.Block.__init__(self, filename, lineno, commands, if_command) def __init__(self, filename, @@ -122,8 +129,8 @@ class IfCommand(Entity): else_commands): Entity.__init__(self, filename, lineno) self.condition = condition - self.then_commands = IfCommand.ThenBlock(filename, then_commands[0].lineno, then_commands) - self.else_commands = IfCommand.ElseBlock(filename, else_commands[0].lineno, else_commands) + 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) def accept(self, visitor): self.condition.accept(visitor) @@ -136,9 +143,9 @@ class IfCommand(Entity): l = ['if', str(self.condition), 'then', - " ".join(map(f, then_commands)), + " ".join(map(f, self.then_commands)), 'else', - " ".join(map(f, else_commands)), + " ".join(map(f, self.else_commands)), 'endif'] return " ".join(l) diff --git a/src/pclc/visitors/do_executor_visitor.py b/src/pclc/visitors/do_executor_visitor.py index cb7d391..d2e48a3 100644 --- a/src/pclc/visitors/do_executor_visitor.py +++ b/src/pclc/visitors/do_executor_visitor.py @@ -25,12 +25,219 @@ from parser.import_spec import Import from parser.module import Module from parser.component import Component from parser.command import Function, Command, Return, IfCommand +from parser.conditional_expressions import ConditionalExpression, \ + AndConditionalExpression, \ + OrConditionalExpression, \ + XorConditionalExpression, \ + EqualsConditionalExpression, \ + NotEqualsConditionalExpression, \ + GreaterThanConditionalExpression, \ + LessThanConditionalExpression, \ + GreaterThanEqualToConditionalExpression, \ + LessThanEqualToConditionalExpression, \ + UnaryConditionalExpression, \ + TerminalConditionalExpression +from parser.expressions import StateIdentifier, Identifier, Literal + + +class IntermediateRepresentation(object): + class IRNode(object): + def __init__(self, pt_object, parent = None): + self.object = pt_object + self.parent = parent + + def add_child(self, node): + raise NotImplementedError + + class IRCommandNode(IRNode): + def __init__(self, pt_object, parent): + IntermediateRepresentation.IRNode.__init__(self, pt_object, parent) + self.children = list() + + def add_child(self, node): + self.children.append(node) + + class IRIfNode(IRNode): + def __init__(self, pt_object, parent): + IntermediateRepresentation.IRNode.__init__(self, pt_object, parent) + self.then_block = list() + self.else_block = list() + self.is_then_block = True + + def add_child(self, node): + if self.is_then_block is True: + self.then_block.append(node) + elif self.is_then_block is False: + self.else_block.append(node) + + def switch_to_else_block(self): + self.is_then_block = False + + class IRReturnNode(IRNode): + def __init__(self, pt_object, parent): + IntermediateRepresentation.IRNode.__init__(self, pt_object, parent) + + def add_child(self, node): + pass + + __TEMP_FUNC_FMT = "____func_%d" + + def __init__(self): + self.__root = list() + self.__current_node = None + self.__current_if = None + self.__func_table = dict() + self.__func_no = 0 + + def push_command_action(self, command): + node = IntermediateRepresentation.IRCommandNode(command, self.__current_node) + 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 + self.__current_if = node + + def mark_else_block(self): + self.__current_if.switch_to_else_block() + self.__current_node = self.__current_if + + def mark_endif(self): + self.__current_node = self.__current_if.parent + self.__current_if = None + + 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) + + def generate_code(self, executor_visitor, assignment_symbol_table): + # Generate function call lambdas + generate_func_args = lambda args: ", ".join(["s['%s']" % a.identifier if isinstance(a, StateIdentifier) \ + else executor_visitor._lookup_var(a) if isinstance(a, Identifier) and \ + a in assignment_symbol_table \ + else "a['%s']" % a if isinstance(a, Identifier) \ + else str(a) for a in args]) + generate_func_call = lambda f: "____%s(%s)" % (f.name, generate_func_args(f.arguments)) + + code = list() + for node in self.__root: + code.extend(self.__generate_code(node, generate_func_call, executor_visitor)) + + top_function_name = self.__lookup_function_name(self.__root[0].object) + + return (code, top_function_name) + + def __generate_code(self, node, generate_function_call, executor_visitor): + code = list() + + if isinstance(node, IntermediateRepresentation.IRCommandNode): + # Command action code generation + command = node.object + code.append(("def %s(a, s):" % self.__get_function_name(command), "+")) + if command.identifier: + code.append(("%s = %s" % (executor_visitor._get_temp_var(command.identifier), \ + generate_function_call(command.function)), "")) + else: + code.append((generate_function_call(command.function), "")) + + for child in node.children: + more_code = self.__generate_code(child, generate_function_call, executor_visitor) + code.extend(more_code) + + code.append((None, "-")) + code.append(("%s(a, s)" % self.__lookup_function_name(command), "")) + elif isinstance(node, IntermediateRepresentation.IRIfNode): + # If command action code generation + if_command = node.object + code.append(("def %s(a, s):" % self.__get_function_name(if_command), "+")) + code.append(("if %s:" % executor_visitor._generate_condition(if_command.condition), "+")) + + for then_node in node.then_block: + more_code = self.__generate_code(then_node, generate_function_call, executor_visitor) + code.extend(more_code) + code.append(("return %s(a, s)" % self.__lookup_function_name(if_command.then_commands[0]), "-")) + code.append((None, "-")) + + code.append(("else:", "+")) + for else_node in node.then_block: + print type(else_node) + more_code = self.__generate_code(else_node, generate_function_call, executor_visitor) + code.extend(more_code) + + + code.append((None, "-")) + code.append(("%s(a, s)" % self.__lookup_function_name(if_command), "")) + + elif isinstance(node, IntermediateRepresentation.IRReturnNode): + # Return command code generation + pass + + return code + + def __get_function_name(self, function): + func_name = IntermediateRepresentation.__TEMP_FUNC_FMT % self.__func_no + self.__func_table[function] = func_name + self.__func_no += 1 + return func_name + + def __lookup_function_name(self, function): + return self.__func_table[function] + + + +## # Generate the whole code +## def generate_code(cmd_iterator, accum): +## cmd = None +## try: +## cmd = cmd_iterator.next() +## except StopIteration: +## return None + +## print cmd, type(cmd) + +## if isinstance(cmd, Command): +## accum.append() +## accum.append() +## elif isinstance(cmd, IfCommand): +## accum.append(()) +## accum.append((None, "+")) +## #accum.extend(generate_code(cmd.then_commands.__iter__(), accum)) +## accum.append((None, "-")) +## accum.append(("else:", "+")) +## #accum.extend(generate_code(cmd.else_commands.__iter__(), accum)) + +## more_code = generate_code(cmd_iterator, accum) +## if more_code: +## accum.extend(more_code) + +## if isinstance(cmd, Command): +## accum.append() +## accum.append() + +## # Generate some code +## iterator = self.__commands.__iter__() +## func_defs = list() +## generate_code(iterator, func_defs) @multimethodclass class DoExecutorVisitor(ExecutorVisitor): def __init__(self, filename_root, is_instrumented): ExecutorVisitor.__init__(self, filename_root, "", is_instrumented) + self.__ir = IntermediateRepresentation() + self.__func_no = 0 + self.__func_table = dict() @multimethod(Module) def visit(self, module): @@ -75,26 +282,81 @@ class DoExecutorVisitor(ExecutorVisitor): for i in self._module.resolution_symbols['configuration']]), ["args"]) + @multimethod(object) + def visit(self, nowt): + func_defs, top_function_name = self.__ir.generate_code(self, self._module.resolution_symbols['assignment_table']) + + # Write initialise function + self._write_function("initialise", func_defs, ["config"]) + self._reset_indent_level() + self._write_lines([("", "+")]) + self._write_line("return %s" % top_function_name) + self._object_file.close() + @multimethod(Function) def visit(self, function): pass @multimethod(Command) def visit(self, command): - pass + self.__ir.push_command_action(command) @multimethod(Return) def visit(self, ret): - pass + self.__ir.push_return_action(ret) @multimethod(IfCommand) def visit(self, if_command): - pass + self.__ir.mark_endif() @multimethod(IfCommand.ThenBlock) def visit(self, then_block): - pass + self.__ir.push_then_block(then_block) @multimethod(IfCommand.ElseBlock) def visit(self, else_block): + self.__ir.mark_else_block() + + @multimethod(AndConditionalExpression) + def visit(self, and_cond_expr): + pass + + @multimethod(OrConditionalExpression) + def visit(self, or_cond_expr): + pass + + @multimethod(XorConditionalExpression) + def visit(self, xor_cond_expr): + pass + + @multimethod(EqualsConditionalExpression) + def visit(self, eq_cond_expr): + pass + + @multimethod(NotEqualsConditionalExpression) + def visit(self, ne_cond_expr): + pass + + @multimethod(GreaterThanConditionalExpression) + def visit(self, gt_cond_expr): + pass + + @multimethod(LessThanConditionalExpression) + def visit(self, lt_cond_expr): + pass + + @multimethod(GreaterThanEqualToConditionalExpression) + def visit(self, gte_cond_expr): + pass + + @multimethod(LessThanEqualToConditionalExpression) + def visit(self, lte_cond_expr): + pass + + @multimethod(UnaryConditionalExpression) + def visit(self, unary_cond_expr): + pass + + @multimethod(TerminalConditionalExpression) + def visit(self, term_cond_expr): pass diff --git a/src/pclc/visitors/executor_visitor.py b/src/pclc/visitors/executor_visitor.py index b8e01b8..fc76256 100644 --- a/src/pclc/visitors/executor_visitor.py +++ b/src/pclc/visitors/executor_visitor.py @@ -31,6 +31,7 @@ from parser.conditional_expressions import ConditionalExpression, \ LessThanEqualToConditionalExpression, \ UnaryConditionalExpression, \ TerminalConditionalExpression +from parser.expressions import StateIdentifier, Identifier, Literal class ExecutorVisitor(object): __INDENTATION = " " @@ -77,7 +78,8 @@ class ExecutorVisitor(object): if isinstance(lines, list) or \ isinstance(lines, tuple): for line, indent_step in lines: - self._write_line(line) + if line is not None: + self._write_line(line) if indent_step == "+": self._incr_indent_level() elif indent_step == "-": @@ -91,7 +93,7 @@ class ExecutorVisitor(object): def _decr_indent_level(self): self._indent_level -= 1 if self._indent_level < 1: - self._reset_indent_level(self) + self._reset_indent_level() def _reset_indent_level(self): self._indent_level = 0 @@ -118,22 +120,25 @@ class ExecutorVisitor(object): terminal = cond_expr.terminal if isinstance(terminal, StateIdentifier): return "s['%s']" % terminal + elif isinstance(terminal, Identifier) and \ + terminal in self._module.resolution_symbols['assignment_table']: + return self._lookup_var(terminal) elif isinstance(terminal, Identifier): return "a['%s']" % terminal elif isinstance(terminal, Literal): - return str(terminal).__repr__() + return str(terminal) else: raise ValueError("Unexpected terminal in conditional: filename = %s, line no = %d" % \ (terminal.filename, terminal.lineno)) elif isinstance(cond_expr, ConditionalExpression): - left_code = self.__generate_condition(cond_expr.left) - right_code = self.__generate_condition(cond_expr.right) + left_code = self._generate_condition(cond_expr.left) + right_code = self._generate_condition(cond_expr.right) op = self.__conditional_operators[cond_expr.__class__] if isinstance(cond_expr, XorConditionalExpression): left_code = "bool(%s)" % left_code right_code = "bool(%s)" % right_code return "(%s %s %s)" % (left_code, op, right_code) - elif isinstance(cond_expr, UnaryConditionExpress): + elif isinstance(cond_expr, UnaryConditionalExpression): return "(%s)" % self._generate_condition(cond_expr.expression) else: raise ValueError("Unexpected expression in conditional: filename = %s, line no = %d" % \ diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py index d8c6573..af04a23 100644 --- a/src/pclc/visitors/first_pass_resolver_visitor.py +++ b/src/pclc/visitors/first_pass_resolver_visitor.py @@ -980,8 +980,14 @@ class FirstPassResolverVisitor(ResolverVisitor): @multimethod(IfCommand.ThenBlock) def visit(self, then_block): self._module.resolution_symbols['assignment_table'].push_inner_scope() + # Add implicit return () if no return exits + if not isinstance(then_block[-1], Return): + then_block.append(Return(None, -1)) @multimethod(IfCommand.ElseBlock) def visit(self, else_block): self._module.resolution_symbols['assignment_table'].pop_inner_scope() self._module.resolution_symbols['assignment_table'].push_inner_scope() + # Add implicit return () if no return exits + if not isinstance(else_block[-1], Return): + else_block.append(Return(None, -1)) |