diff options
author | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-05-21 19:33:48 +0400 |
---|---|---|
committer | Ian Johnson <ian.johnson@appliedlanguage.com> | 2013-05-21 19:33:48 +0400 |
commit | a11ce00140323ef9fa1a5d26c6e4db05e461cc8d (patch) | |
tree | 8e15d8f6949d2d17c7ee7c0cc6113eda7a410b46 /src | |
parent | e6ac220310b6588102813b3bd8e2a6d769b20b7d (diff) |
The configuration of a PCL file is now propagated through the pipeline. Any state conversions needed to support a imported component are done.
Diffstat (limited to 'src')
-rwxr-xr-x | src/pcl-run/pcl-run.py | 4 | ||||
-rw-r--r-- | src/pclc/parser/pcl_lexer.py | 2 | ||||
-rw-r--r-- | src/pclc/parser/pcl_parser.py | 2 | ||||
-rwxr-xr-x | src/pclc/pclc.py | 2 | ||||
-rw-r--r-- | src/pclc/visitors/executor_visitor.py | 16 | ||||
-rw-r--r-- | src/pclc/visitors/first_pass_resolver_visitor.py | 142 | ||||
-rw-r--r-- | src/pclc/visitors/second_pass_resolver_visitor.py | 8 |
7 files changed, 97 insertions, 79 deletions
diff --git a/src/pcl-run/pcl-run.py b/src/pcl-run/pcl-run.py index 35d9056..e5e91c8 100755 --- a/src/pcl-run/pcl-run.py +++ b/src/pcl-run/pcl-run.py @@ -27,7 +27,7 @@ from pypeline.core.arrows.kleisli_arrow import KleisliArrow from pypeline.helpers.parallel_helpers import eval_pipeline, cons_function_component -__VERSION = "1.0.1" +__VERSION = "1.0.2" def get_configuration(section, config_key): @@ -153,6 +153,6 @@ if __name__ == '__main__': executor = ThreadPoolExecutor(max_workers = options.no_workers) print >> sys.stderr, "Evaluating pipeline..." try: - print eval_pipeline(executor, pipeline, pipeline_inputs, None) + print >> sys.stdout, eval_pipeline(executor, pipeline, pipeline_inputs, configuration) finally: executor.shutdown(True) diff --git a/src/pclc/parser/pcl_lexer.py b/src/pclc/parser/pcl_lexer.py index 0c5b85f..fc5ba6d 100644 --- a/src/pclc/parser/pcl_lexer.py +++ b/src/pclc/parser/pcl_lexer.py @@ -72,7 +72,7 @@ tokens = [ class PCLLexer(object): tokens = tokens - literals = ",()[]" + literals = ",()[]@" t_ASSIGN = r':=' t_EQUALS = r'==' diff --git a/src/pclc/parser/pcl_parser.py b/src/pclc/parser/pcl_parser.py index 45d3cf1..68d245c 100644 --- a/src/pclc/parser/pcl_parser.py +++ b/src/pclc/parser/pcl_parser.py @@ -135,7 +135,7 @@ def p_declaration(p): p.lineno(1), Identifier(p.parser.filename, p.lineno(1), p[1]), Identifier(p.parser.filename, p.lineno(4), p[4]), - p[5]) + p[5] if p[5] else list()) def p_opt_with_clause(p): '''opt_with_clause : WITH configuration_mappings diff --git a/src/pclc/pclc.py b/src/pclc/pclc.py index 67a85b1..5b9572e 100755 --- a/src/pclc/pclc.py +++ b/src/pclc/pclc.py @@ -27,7 +27,7 @@ from parser.resolver import Resolver from visitors.executor_visitor import ExecutorVisitor -__VERSION = "1.0.4" +__VERSION = "1.0.5" if __name__ == '__main__': diff --git a/src/pclc/visitors/executor_visitor.py b/src/pclc/visitors/executor_visitor.py index 65f2217..27ac5a2 100644 --- a/src/pclc/visitors/executor_visitor.py +++ b/src/pclc/visitors/executor_visitor.py @@ -227,12 +227,26 @@ class ExecutorVisitor(object): else m.literal) \ for cm in decl.configuration_mappings]))) \ for decl in self._module.resolution_symbols['components']] + # Guard against a module returning a non-Kleisli arrow type from initialise component_decl_guards = ["%(id)s = %(id)s " \ "if isinstance(%(id)s, KleisliArrow) " \ "else cons_function_component(%(id)s)" % \ {'id' : decl.identifier} \ for decl in self._module.resolution_symbols['components']] - initialise_fn = [t for pair in zip(component_initialisations, component_decl_guards) for t in pair] + # Wrap this component with any state conversion components + state_wrappers = ["%(id)s = ((cons_function_component(lambda a, s: a, state_mutator = lambda s: {%(state)s, '____prev_' : s})) >> %(id)s) >> cons_function_component(lambda a, s: a, state_mutator = lambda s: s['____prev_'])" % \ + {'id' : decl.identifier, + 'state' : "%s" % (", ".join(["'%s' : %s" % \ + (cm.to, \ + "s['%s']" % cm.from_ \ + if isinstance(cm.from_, Identifier) \ + else cm.from_.value.__repr__() \ + if isinstance(cm.from_.value, str) \ + else m.literal) \ + for cm in decl.configuration_mappings]))} if decl.configuration_mappings else "" + for decl in self._module.resolution_symbols['components']] + # + initialise_fn = [t for triple in zip(component_initialisations, component_decl_guards, state_wrappers) for t in triple] # Store variables in variable table for decl in self._module.resolution_symbols['components']: self._var_table[IdentifierExpression(None, diff --git a/src/pclc/visitors/first_pass_resolver_visitor.py b/src/pclc/visitors/first_pass_resolver_visitor.py index d038879..c03c56a 100644 --- a/src/pclc/visitors/first_pass_resolver_visitor.py +++ b/src/pclc/visitors/first_pass_resolver_visitor.py @@ -38,6 +38,7 @@ from parser.conditional_expressions import AndConditionalExpression, \ from parser.declaration import Declaration from parser.expressions import Literal, \ Identifier, \ + StateIdentifier, \ Expression, \ UnaryExpression, \ BinaryExpression, \ @@ -167,7 +168,7 @@ class FirstPassResolverVisitor(ResolverVisitor): duplicate_declarations = filter(lambda de: dups[de] > 1, dups) return (tuple(missing_config), - tuple(unused_config), + set(unused_config), tuple(unknown_imports), tuple(duplicate_declarations), tuple(unknown_module_configuration), @@ -192,7 +193,8 @@ class FirstPassResolverVisitor(ResolverVisitor): self._module.resolution_symbols = {'imports' : dict(), 'components' : dict(), 'used_components' : dict(), - 'configuration' : dict()} + 'configuration' : dict(), + 'unused_configuration' : list()} @multimethod(Import) def visit(self, an_import): @@ -306,82 +308,67 @@ class FirstPassResolverVisitor(ResolverVisitor): # Check that all the used configuration in declarations exist, and is used missing_configuration, \ - unused_configuration, \ + self._module.resolution_symbols['unused_configuration'], \ unknown_imports, \ duplicate_declarations, \ unknown_module_configuration, \ python_module_interace = FirstPassResolverVisitor.__check_declarations(component.configuration, component.declarations, component.module.resolution_symbols['imports']) - if duplicate_inputs or \ - duplicate_outputs or \ - duplicate_config or \ - duplicate_decl_identifiers or \ - missing_configuration or \ - unused_configuration or \ - unknown_imports or \ - duplicate_declarations or \ - unknown_module_configuration or \ - python_module_interace: - self._add_errors("ERROR: %(filename)s at line %(lineno)d, input " \ - "declaration contains duplicate identifier %(entity)s", - duplicate_inputs, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, output " \ - "declaration contains duplicate identifier %(entity)s", - duplicate_outputs, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, configuration " \ - "declaration contains duplicate identifier %(entity)s", - duplicate_config, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, component " \ - "declaration contains duplicate identifier %(entity)s", - duplicate_decl_identifiers, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, component " \ - "configuration does not exist %(entity)s", - missing_configuration, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_warnings("WARNING: %(filename)s at line %(lineno)d, component " \ - "configuration is not used %(entity)s", - unused_configuration, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, import not found " \ - "in declaration of %(entity)s", - unknown_imports, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, duplicate declaration " \ - "found %(entity)s", - duplicate_declarations, - lambda e: {'entity' : e, - 'filename' : e.filename, - 'lineno' : e.lineno}) - self._add_errors("ERROR: %(filename)s at line %(lineno)d, configuration %(entity)s " \ - "used which is not defined in module %(module_name)s", - unknown_module_configuration, - lambda e: {'entity' : e['config_map'].to, - 'module_name' : e['module_name'], - 'filename' : e['config_map'].filename, - 'lineno' : e['config_map'].lineno}) - self._add_errors("ERROR: Python module %(module_name)s does not define " \ - "mandatory function %(missing_function)s", - python_module_interace, - lambda e: e) + + self._add_errors("ERROR: %(filename)s at line %(lineno)d, input " \ + "declaration contains duplicate identifier %(entity)s", + duplicate_inputs, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, output " \ + "declaration contains duplicate identifier %(entity)s", + duplicate_outputs, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, configuration " \ + "declaration contains duplicate identifier %(entity)s", + duplicate_config, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, component " \ + "declaration contains duplicate identifier %(entity)s", + duplicate_decl_identifiers, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, component " \ + "configuration does not exist %(entity)s", + missing_configuration, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, import not found " \ + "in declaration of %(entity)s", + unknown_imports, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, duplicate declaration " \ + "found %(entity)s", + duplicate_declarations, + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) + self._add_errors("ERROR: %(filename)s at line %(lineno)d, configuration %(entity)s " \ + "used which is not defined in module %(module_name)s", + unknown_module_configuration, + lambda e: {'entity' : e['config_map'].to, + 'module_name' : e['module_name'], + 'filename' : e['config_map'].filename, + 'lineno' : e['config_map'].lineno}) + self._add_errors("ERROR: Python module %(module_name)s does not define " \ + "mandatory function %(missing_function)s", + python_module_interace, + lambda e: e) @multimethod(Declaration) def visit(self, decl): @@ -417,6 +404,12 @@ class FirstPassResolverVisitor(ResolverVisitor): lambda e: {'filename' : e.filename, 'lineno' : e.lineno, 'component' : e}) + self._add_warnings("WARNING: %(filename)s at line %(lineno)d, component " \ + "configuration %(entity)s is not used", + self._module.resolution_symbols['unused_configuration'], + lambda e: {'entity' : e, + 'filename' : e.filename, + 'lineno' : e.lineno}) @multimethod(UnaryExpression) def visit(self, unary_expr): @@ -643,7 +636,10 @@ class FirstPassResolverVisitor(ResolverVisitor): @multimethod(TerminalConditionalExpression) def visit(self, term_cond_expr): - pass + terminal = term_cond_expr.terminal + if isinstance(terminal, StateIdentifier) and \ + terminal in self._module.resolution_symbols['unused_configuration']: + self._module.resolution_symbols['unused_configuration'].remove(terminal) @multimethod(Mapping) def visit(self, mapping): diff --git a/src/pclc/visitors/second_pass_resolver_visitor.py b/src/pclc/visitors/second_pass_resolver_visitor.py index 6d1cf49..1cd6ca6 100644 --- a/src/pclc/visitors/second_pass_resolver_visitor.py +++ b/src/pclc/visitors/second_pass_resolver_visitor.py @@ -51,6 +51,10 @@ class SecondPassResolverVisitor(FirstPassResolverVisitor): def visit(self, decl): pass + @multimethod(object) + def visit(self, nowt): + pass + def __derive_inputs(self, expr): return self.__walk_expression(expr.parent, expr) @@ -114,3 +118,7 @@ class SecondPassResolverVisitor(FirstPassResolverVisitor): inputs = self.__derive_inputs(split_expr) split_expr.resolution_symbols['inputs'] = inputs split_expr.resolution_symbols['outputs'] = inputs >= (lambda ins: Just((ins, ins))) + + @multimethod(TerminalConditionalExpression) + def visit(self, term_cond_expr): + pass |