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-10-23 19:44:13 +0400
committerIan Johnson <ian.johnson@appliedlanguage.com>2013-10-23 19:44:13 +0400
commit8360af279584a22cc0d27f2e3e15968f74e46ece (patch)
treec68bdfd954813e8c65b93a5a02500de3e4341cdf
parent7675a18cc6bd760b5bea34c216185c5cec6c8212 (diff)
Do notation code generation started.
-rw-r--r--src/pclc/parser/command.py27
-rw-r--r--src/pclc/visitors/do_executor_visitor.py270
-rw-r--r--src/pclc/visitors/executor_visitor.py17
-rw-r--r--src/pclc/visitors/first_pass_resolver_visitor.py6
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))