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-21 18:44:08 +0400
committerIan Johnson <ian.johnson@appliedlanguage.com>2013-10-21 18:44:08 +0400
commitb43d1c1ff5f0ad64552339feaee0d176156e0ed4 (patch)
tree4db70e3763529d9629a0f98d762921493e85a492
parent6451c37835ef255ec01cbe182094a11db889d6e0 (diff)
Resolution of do-notation.
-rw-r--r--src/pclc/parser/command.py39
-rw-r--r--src/pclc/visitors/first_pass_resolver_visitor.py16
-rw-r--r--src/pclc/visitors/second_pass_resolver_visitor.py8
-rw-r--r--src/pclc/visitors/symbol_table.py104
4 files changed, 155 insertions, 12 deletions
diff --git a/src/pclc/parser/command.py b/src/pclc/parser/command.py
index b9b3921..875a900 100644
--- a/src/pclc/parser/command.py
+++ b/src/pclc/parser/command.py
@@ -93,6 +93,27 @@ class Return(Entity):
super(Return, self).__repr__())
class IfCommand(Entity):
+ class Block(Entity):
+ def __init__(self, filename, lineno, commands):
+ Entity.__init__(self, filename, lineno)
+ self.commands = commands
+
+ def __iter__(self):
+ return self.commands.__iter__()
+
+ 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)
+
+ class ElseBlock(Block):
+ def __init__(self, filename, lineno, commands):
+ IfCommand.Block.__init__(self, filename, lineno, commands)
+
def __init__(self,
filename,
lineno,
@@ -101,26 +122,26 @@ class IfCommand(Entity):
else_commands):
Entity.__init__(self, filename, lineno)
self.condition = condition
- self.then_commands = then_commands
- self.else_commands = else_commands
+ self.then_commands = IfCommand.ThenBlock(filename, then_commands[0].lineno, then_commands)
+ self.else_commands = IfCommand.ElseBlock(filename, else_commands[0].lineno, else_commands)
def accept(self, visitor):
self.condition.accept(visitor)
- for then_cmd in self.then_commands:
- then_cmd.accept(visitor)
- for else_cmd in self.else_commands:
- else_cmd.accept(visitor)
+ self.then_commands.accept(visitor)
+ self.else_commands.accept(visitor)
visitor.visit(self)
def __str__(self):
f = lambda cmd: str(cmd)
l = ['if',
str(self.condition),
- 'else',
+ 'then',
" ".join(map(f, then_commands)),
- " ".join(map(f, else_commands))]
+ 'else',
+ " ".join(map(f, else_commands)),
+ 'endif']
return " ".join(l)
-
+
def __repr__(self):
f = lambda cmd: cmd.__repr__()
return "<IfCommand:\n\tcondition = %s,\n\tthen_commands = %s,\n\t" \
diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py
index 37a47e9..dc8370b 100644
--- a/src/pclc/visitors/first_pass_resolver_visitor.py
+++ b/src/pclc/visitors/first_pass_resolver_visitor.py
@@ -65,6 +65,7 @@ from parser.helpers import parse_component
from pypeline.core.types.just import Just
from pypeline.core.types.nothing import Nothing
from resolver_visitor import ResolverVisitor
+from symbol_table import SymbolTable
# Decorator to prevent resolving more than once
@@ -206,7 +207,7 @@ class FirstPassResolverVisitor(ResolverVisitor):
'configuration' : dict(),
'unused_configuration' : list(),
'command_table' : list(),
- 'assignment_table' : dict()}
+ 'assignment_table' : SymbolTable()}
if not self.__dict__.has_key("__resolve_import"):
self.__resolve_import = self.__resolve_runtime_import if self._module.definition.is_leaf \
else self.__resolve_pcl_import
@@ -875,7 +876,7 @@ class FirstPassResolverVisitor(ResolverVisitor):
elif isinstance(argument, Identifier):
if argument not in self._module.definition.inputs and \
argument not in self._module.resolution_symbols['assignment_table']:
- self._add_errors("ERROR: %(filename)s at line %(lineno)d, unknown function argument %(arg_name)s TITZ",
+ self._add_errors("ERROR: %(filename)s at line %(lineno)d, unknown function argument %(arg_name)s",
[function],
lambda f: {'filename' : f.filename,
'lineno' : f.lineno,
@@ -966,4 +967,13 @@ class FirstPassResolverVisitor(ResolverVisitor):
@multimethod(IfCommand)
def visit(self, if_command):
- pass
+ self._module.resolution_symbols['assignment_table'].pop_inner_scope()
+
+ @multimethod(IfCommand.ThenBlock)
+ def visit(self, then_block):
+ self._module.resolution_symbols['assignment_table'].push_inner_scope()
+
+ @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()
diff --git a/src/pclc/visitors/second_pass_resolver_visitor.py b/src/pclc/visitors/second_pass_resolver_visitor.py
index 3923191..5a48e12 100644
--- a/src/pclc/visitors/second_pass_resolver_visitor.py
+++ b/src/pclc/visitors/second_pass_resolver_visitor.py
@@ -142,3 +142,11 @@ class SecondPassResolverVisitor(FirstPassResolverVisitor):
@multimethod(IfCommand)
def visit(self, if_command):
pass
+
+ @multimethod(IfCommand.ThenBlock)
+ def visit(self, then_block):
+ pass
+
+ @multimethod(IfCommand.ElseBlock)
+ def visit(self, else_block):
+ pass
diff --git a/src/pclc/visitors/symbol_table.py b/src/pclc/visitors/symbol_table.py
new file mode 100644
index 0000000..1e68f80
--- /dev/null
+++ b/src/pclc/visitors/symbol_table.py
@@ -0,0 +1,104 @@
+#
+# Copyright Capita Translation and Interpreting 2013
+#
+# This file is part of Pipeline Creation Language (PCL).
+#
+# Pipeline Creation Language (PCL) is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Pipeline Creation Language (PCL) is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Pipeline Creation Language (PCL). If not, see <http://www.gnu.org/licenses/>.
+#
+class SymbolTable(object):
+ class Scope(object):
+ def __init__(self):
+ self.__table = dict()
+ self.__nested_scopes = list()
+ self.__root = None
+
+ def addNestedScope(self, scope):
+ scope.__root = self
+ return self.__nested_scopes.append(scope)
+
+ def getRoot(self):
+ return self.__root
+
+ def __getitem__(self, key):
+ return self.__table[key]
+
+ def __setitem__(self, key, value):
+ self.__table[key] = value
+
+ def __delitem__(self, key):
+ del self.__table[key]
+
+ def __contains__(self, item):
+ return item in self.__table
+
+ def __iteritems__(self):
+ return self.__table.__iteritems__()
+
+ def iterkeys(self):
+ return self.__table.iterkeys()
+
+ def keys(self):
+ return self.__table.keys()
+
+ def has_key(self, key):
+ return self.__table.has_key(key)
+
+ def _get_nested_scopes_iter(self):
+ return self.__nested_scopes.__iter__()
+
+ def __init__(self):
+ self.__tree = SymbolTable.Scope()
+ self.__current_scope = self.__tree
+
+ def __getitem__(self, key):
+ scope = self.__current_scope
+ while scope is not None:
+ if scope.has_key(key):
+ return scope[key]
+ scope.getRoot()
+
+ raise KeyError
+
+ def __setitem__(self, key, value):
+ self.__current_scope[key] = value
+
+ def __contains__(self, item):
+ scope = self.__current_scope
+ while scope is not None:
+ if item in scope:
+ return True
+ scope = scope.getRoot()
+
+ return False
+
+ def push_inner_scope(self):
+ scope = SymbolTable.Scope()
+ self.__current_scope.addNestedScope(scope)
+ self.__current_scope = scope
+
+ def pop_inner_scope(self):
+ outer_scope = self.__current_scope.getRoot()
+ if outer_scope is not None:
+ self.__current_scope = outer_scope
+
+ def __str__(self):
+ disp = lambda s, d: (" " * d) + ("%d : " % d) + ", ".join([str(sym) for sym in s.keys()]) + "\n"
+
+ def trav(s, d):
+ rep = disp(s, d)
+ for ns in s._get_nested_scopes_iter():
+ rep += trav(ns, d + 1)
+ return rep
+
+ return trav(self.__tree, 0)