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 <ianj@wgrids.com>2013-11-11 11:49:51 +0400
committerIan Johnson <ianj@wgrids.com>2013-11-11 11:49:51 +0400
commit203e44a3d3254a8805d92381ae26975f49da1c21 (patch)
treea0b27e5a02778e4336ddbb74b3a62b24ba3e405b
parent47e0bc7a1da52c754b156d5fddf46d8cbd24053e (diff)
Started let command. DOES NOT WORK ON THIS COMMIT.
-rw-r--r--examples/let_binding/let_binding.pcl21
-rw-r--r--extras/syntax-highlighting/vim/pcl.vim4
-rw-r--r--src/pclc/parser/command.py78
-rw-r--r--src/pclc/parser/pcl_lexer.py2
-rw-r--r--src/pclc/parser/pcl_parser.py28
-rw-r--r--src/pclc/visitors/do_executor_visitor.py65
-rw-r--r--src/pclc/visitors/first_pass_resolver_visitor.py17
-rw-r--r--src/pclc/visitors/second_pass_resolver_visitor.py10
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