diff options
author | Ian Johnson <ianj@wgrids.com> | 2013-11-11 11:49:51 +0400 |
---|---|---|
committer | Ian Johnson <ianj@wgrids.com> | 2013-11-11 11:49:51 +0400 |
commit | 203e44a3d3254a8805d92381ae26975f49da1c21 (patch) | |
tree | a0b27e5a02778e4336ddbb74b3a62b24ba3e405b | |
parent | 47e0bc7a1da52c754b156d5fddf46d8cbd24053e (diff) |
Started let command. DOES NOT WORK ON THIS COMMIT.
-rw-r--r-- | examples/let_binding/let_binding.pcl | 21 | ||||
-rw-r--r-- | extras/syntax-highlighting/vim/pcl.vim | 4 | ||||
-rw-r--r-- | src/pclc/parser/command.py | 78 | ||||
-rw-r--r-- | src/pclc/parser/pcl_lexer.py | 2 | ||||
-rw-r--r-- | src/pclc/parser/pcl_parser.py | 28 | ||||
-rw-r--r-- | src/pclc/visitors/do_executor_visitor.py | 65 | ||||
-rw-r--r-- | src/pclc/visitors/first_pass_resolver_visitor.py | 17 | ||||
-rw-r--r-- | src/pclc/visitors/second_pass_resolver_visitor.py | 10 |
8 files changed, 209 insertions, 16 deletions
diff --git a/examples/let_binding/let_binding.pcl b/examples/let_binding/let_binding.pcl new file mode 100644 index 0000000..7e68e74 --- /dev/null +++ b/examples/let_binding/let_binding.pcl @@ -0,0 +1,21 @@ +import pcl.os.path as path +import pcl.util.list as list +import pcl.util.string as string + +component let_binding + input filename + output filename.new + configuration working.directory + do + # Create the pathname of the re-encoded corpus + result <- let + basename <- path.basename(filename) + pieces <- path.splitext(basename) + base <- list.index(pieces, 0) + ext <- list.index(pieces, 1) + bits <- list.cons(base, "new", ext) + new_basename <- string.join(bits, ".") + in + path.join(@working.directory, new_basename) + + return filename.new <- result diff --git a/extras/syntax-highlighting/vim/pcl.vim b/extras/syntax-highlighting/vim/pcl.vim index aace61d..ee46bef 100644 --- a/extras/syntax-highlighting/vim/pcl.vim +++ b/extras/syntax-highlighting/vim/pcl.vim @@ -10,8 +10,8 @@ elseif exists("b:current_syntax") endif syn keyword pclKeywords and as bottom component configuration declare do -syn keyword pclKeywords else endif if input inputs or output outputs -syn keyword pclKeywords merge new return split then top wire with xor +syn keyword pclKeywords else endif if in input inputs or output outputs +syn keyword pclKeywords let merge new return split then top wire with xor syn keyword pclStatement component nextgroup=pclIdentifier skipwhite syn keyword pclImports import diff --git a/src/pclc/parser/command.py b/src/pclc/parser/command.py index 6d5add1..dc8a036 100644 --- a/src/pclc/parser/command.py +++ b/src/pclc/parser/command.py @@ -39,7 +39,7 @@ class Function(Entity): def __repr__(self): return "<Function:\n\tname = %s\n\targuments = %s\n\tentity = %s>" % \ - (self.name.__repr__(), + (repr(self.name), ", ".join(map(lambda arg: arg.__repr__(), self.arguments)), super(Function, self).__repr__()) @@ -67,8 +67,9 @@ class Command(Entity): def __repr__(self): return "<Command:\n\tidentifier = %s,\n\tfunction = %s,\n\t" \ "entity = %s>" % \ - (self.identifier.__repr__() if self.identifier else None, - self.function.__repr__(), super(Command, self).__repr__()) + (repr(self.identifier), + repr(self.function), + super(Command, self).__repr__()) class Return(Entity): def __init__(self, @@ -95,9 +96,9 @@ class Return(Entity): def __repr__(self): return "<Return:\n\tvalue = %s\n\tmappings = %s\n\tentity = %s>" % \ - (self.value, + (repr(self.value), "()" if not self.mappings \ - else ", ".join(map(lambda m: m.__repr__(), self.mappings)), \ + else ", ".join(map(lambda m: repr(m), self.mappings)), \ super(Return, self).__repr__()) class IfCommand(Entity): @@ -163,11 +164,72 @@ class IfCommand(Entity): return " ".join(l) def __repr__(self): - f = lambda cmd: cmd.__repr__() + f = lambda cmd: repr(cmd) return "<IfCommand:\n\tidentifier = %s\n\tcondition = %s,\n\tthen_commands = %s,\n\t" \ "else_commands = %s\n\tentity = %s>" % \ - (self.identifier.__repr__(), - self.condition.__repr__(), + (repr(self.identifier), + repr(self.condition), " ".join(map(f, self.then_commands)), " ".join(map(f, self.else_commands)), super(IfCommand, self).__repr__()) + +class LetCommand(Entity): + class LetBindings(Entity): + def __init__(self, + filename, + lineno, + bindings): + Entity.__init__(self, filename, lineno) + self.bindings = bindings + + def __getitem__(self, idx): + return self.bindings[idx] + + def __iter__(self): + return self.bindings.__iter__() + + def accept(self, visitor): + visitor.visit(self) + for binding in self.bindings: + binding.accept(visitor) + + class LetEnd(Entity): + def __init__(self, filename, lineno): + Entity.__init__(self, filename, lineno) + + def accept(self, visitor): + visitor.visit(self) + + def __init__(self, + filename, + lineno, + identifier, + bindings, + expression): + Entity.__init__(self, filename, lineno) + self.identifier = identifier + self.bindings = LetCommand.LetBindings(filename, bindings[0].lineno, bindings) + self.expression = expression + self.let_end = LetCommand.LetEnd(filename, expression.lineno) + + def accept(self, visitor): + visitor.visit(self) + self.bindings.accept(visitor) + self.expression.accept(visitor) + self.let_end.accept(visitor) + + def __str__(self): + l = ['let'] + l.extend([str(b) for b in self.bindings]) + l.append('in') + l.append(str(self.expression)) + return ' '.join(l) + + def __repr__(self): + f = lambda t: repr(t) + return "<LetCommand:\n\tidentifier = %s\n\tbindings = %s\n\t" \ + "expression = %s\n\tentity = %s>" % \ + (repr(self.identifier), + " ".join(map(f, self.bindings)), + repr(self.expression), + super(LetCommand, self).__repr__()) diff --git a/src/pclc/parser/pcl_lexer.py b/src/pclc/parser/pcl_lexer.py index 5a1563b..160af46 100644 --- a/src/pclc/parser/pcl_lexer.py +++ b/src/pclc/parser/pcl_lexer.py @@ -39,8 +39,10 @@ reserved = { 'first' : 'FIRST', 'import' : 'IMPORT', 'if' : 'IF', + 'in' : 'IN', 'input' : 'INPUTS', 'inputs' : 'INPUTS', + 'let' : 'LET', 'merge' : 'MERGE', 'new' : 'NEW', 'or' : 'OR', diff --git a/src/pclc/parser/pcl_parser.py b/src/pclc/parser/pcl_parser.py index a98cc2c..397a323 100644 --- a/src/pclc/parser/pcl_parser.py +++ b/src/pclc/parser/pcl_parser.py @@ -26,7 +26,7 @@ from pcl_lexer import tokens, PCLLexer from import_spec import Import from component import Component from declaration import Declaration -from command import Command, Function, Return, IfCommand +from command import Command, Function, Return, IfCommand, LetCommand from conditional_expressions import AndConditionalExpression, \ OrConditionalExpression, \ XorConditionalExpression, \ @@ -390,22 +390,46 @@ def p_do_command_list(p): def p_do_command(p): '''do_command : identifier_or_qual_identifier LEFT_ARROW function | function + | LET let_bindings IN function + | identifier_or_qual_identifier LEFT_ARROW LET let_bindings IN function | IF conditional_expression THEN opt_do_command_list return_command ELSE opt_do_command_list return_command ENDIF | identifier_or_qual_identifier LEFT_ARROW IF conditional_expression THEN opt_do_command_list return_command ELSE opt_do_command_list return_command ENDIF''' p[0] = list() if len(p) > 10: + # 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])) - elif len(p) > 4: + 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])) + elif len(p) > 6: + # len(p) == 7 + p[0].append(LetCommand(p.parser.filename, p.lineno(1), p[1], p[4], p[6])) + elif len(p) > 4: + # len(p) == 5 + p[0].append(LetCommand(p.parser.filename, p.lineno(1), None, p[2], p[4])) elif len(p) > 3: + # len(p) == 4 p[0].append(Command(p.parser.filename, p[1].lineno, p[1], p[3])) else: + # len(p) == 2 p[0].append(Command(p.parser.filename, p[1].lineno, None, p[1])) +def p_let_bindings(p): + '''let_bindings : let_binding let_bindings + | let_binding''' + if len(p) > 2: + p[0] = [p[1]] + p[2] + else: + p[0] = [p[1]] + +def p_let_binding(p): + '''let_binding : identifier_or_qual_identifier LEFT_ARROW function''' + p[0] = Command(p.parser.filename, p[1].lineno, p[1], p[3]) + def p_function(p): '''function : QUALIFIED_IDENTIFIER '(' opt_function_args ')' ''' p[0] = Function(p.parser.filename, p.lineno(1), p[1], p[3]) diff --git a/src/pclc/visitors/do_executor_visitor.py b/src/pclc/visitors/do_executor_visitor.py index c62aace..0b620ce 100644 --- a/src/pclc/visitors/do_executor_visitor.py +++ b/src/pclc/visitors/do_executor_visitor.py @@ -24,7 +24,7 @@ from executor_visitor import ExecutorVisitor 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.command import Function, Command, Return, IfCommand, LetCommand from parser.conditional_expressions import ConditionalExpression, \ AndConditionalExpression, \ OrConditionalExpression, \ @@ -80,12 +80,22 @@ class IntermediateRepresentation(object): def add_child(self, node): pass + class IRLetNode(IRNode): + def __init__(self, pt_object, parent): + IntermediateRepresentation.IRNode.__init__(self, pt_object, parent) + self.bindings = list() + + def add_child(self, node): + if isinstance(node.object, Command): + self.bindings.append(node) + __TEMP_FUNC_FMT = "____func_%d" def __init__(self): self.__root = list() self.__current_node = None self.__current_if = None + self.__current_let = None self.__func_table = dict() self.__func_no = 0 @@ -121,6 +131,19 @@ class IntermediateRepresentation(object): else: self.__current_node.add_child(node) + 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.__current_let = node + + def mark_let_end(self): + self.__current_node = self.__current_let.parent + self.__current_let = None + def generate_code(self, executor_visitor, assignment_symbol_table, is_instrumented): # Generate function call lambdas generate_func_args = lambda args: ", ".join([executor_visitor._generate_terminal(a) for a in args]) @@ -205,6 +228,34 @@ class IntermediateRepresentation(object): code.append(("return {%s}" % ", ".join(["'%s' : %s" % \ (m.to, executor_visitor._generate_terminal(m.from_)) \ for m in return_command.mappings]), "")) + elif isinstance(node, IntermediateRepresentation.IRLetNode): + # Let command + let_command = node.object + + code.append(("# LET", "")) + code.append(("def %s(a, s):" % self.__get_function_name(let_command), "+")) + + for binding in node.bindings: + more_code = self.__generate_code(binding, + generate_function_call, + executor_visitor, + is_instrumented) + code.extend(more_code) + + #more_code = self.__generate_code(node.expression, + # generate_function_call, + # executor_visitor, + # is_instrumented) + code.append(("%s = %s" % (executor_visitor._get_temp_var(let_command.expression), \ + generate_function_call(let_command.expression)), "")) + code.append(("return %s" % executor_visitor._lookup_var(let_command.expression), "")) + + code.extend([(None, "-"), (None, "-")]) + if let_command.identifier: + code.append(("%s = %s(a, s)" % (executor_visitor._get_temp_var(let_command.identifier), \ + self.__lookup_function_name(let_command)), "")) + else: + code.append(("%s(a, s)" % self.__lookup_function_name(let_command), "")) return code @@ -310,6 +361,18 @@ class DoExecutorVisitor(ExecutorVisitor): def visit(self, else_block): self.__ir.mark_else_block() + @multimethod(LetCommand) + def visit(self, let_command): + self.__ir.push_let_action(let_command) + + @multimethod(LetCommand.LetBindings) + def visit(self, let_bindings): + pass + + @multimethod(LetCommand.LetEnd) + def visit(self, let_end): + self.__ir.mark_let_end() + @multimethod(AndConditionalExpression) def visit(self, and_cond_expr): pass diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py index 0de08d3..508c7d6 100644 --- a/src/pclc/visitors/first_pass_resolver_visitor.py +++ b/src/pclc/visitors/first_pass_resolver_visitor.py @@ -25,7 +25,7 @@ import types from multimethod import multimethod, multimethodclass from parser.import_spec import Import -from parser.command import Function, Command, Return, IfCommand +from parser.command import Function, Command, Return, IfCommand, LetCommand from parser.component import Component from parser.conditional_expressions import AndConditionalExpression, \ OrConditionalExpression, \ @@ -976,9 +976,9 @@ class FirstPassResolverVisitor(ResolverVisitor): @multimethod(IfCommand) def visit(self, if_command): + self._module.resolution_symbols['assignment_table'].pop_inner_scope() if if_command.identifier: self.__resolve_assignment(if_command.identifier, if_command) - self._module.resolution_symbols['assignment_table'].pop_inner_scope() @multimethod(IfCommand.ThenBlock) def visit(self, then_block): @@ -988,3 +988,16 @@ class FirstPassResolverVisitor(ResolverVisitor): def visit(self, else_block): self._module.resolution_symbols['assignment_table'].pop_inner_scope() self._module.resolution_symbols['assignment_table'].push_inner_scope() + + @multimethod(LetCommand) + def visit(self, let_command): + if let_command.identifier: + self.__resolve_assignment(let_command.identifier, let_command) + + @multimethod(LetCommand.LetBindings) + def visit(self, let_bindings): + self._module.resolution_symbols['assignment_table'].push_inner_scope() + + @multimethod(LetCommand.LetEnd) + def visit(self, let_end): + self._module.resolution_symbols['assignment_table'].pop_inner_scope() diff --git a/src/pclc/visitors/second_pass_resolver_visitor.py b/src/pclc/visitors/second_pass_resolver_visitor.py index 5a48e12..05868f6 100644 --- a/src/pclc/visitors/second_pass_resolver_visitor.py +++ b/src/pclc/visitors/second_pass_resolver_visitor.py @@ -18,7 +18,7 @@ # from multimethod import multimethod, multimethodclass from parser.import_spec import Import -from parser.command import Function, Command, Return, IfCommand +from parser.command import Function, Command, Return, IfCommand, LetCommand from parser.component import Component from parser.conditional_expressions import ConditionalExpression, \ UnaryConditionalExpression, \ @@ -150,3 +150,11 @@ class SecondPassResolverVisitor(FirstPassResolverVisitor): @multimethod(IfCommand.ElseBlock) def visit(self, else_block): pass + + @multimethod(LetCommand) + def visit(self, let_command): + pass + + @multimethod(LetCommand.LetBindings) + def visit(self, let_bindings): + pass |