diff --git a/dagrt/codegen/__init__.py b/dagrt/codegen/__init__.py index ea14edc49c5fc57786696e4dcdcb712e1af960da..982be026e819b57ffbeb9289ad929dfe1d8a87fb 100644 --- a/dagrt/codegen/__init__.py +++ b/dagrt/codegen/__init__.py @@ -22,9 +22,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from . import analysis -from . import python - - -CodeGenerationError = analysis.CodeGenerationError -PythonCodeGenerator = python.CodeGenerator +from dagrt.codegen.analysis import CodeGenerationError # noqa +from dagrt.codegen.python import CodeGenerator as PythonCodeGenerator # noqa diff --git a/dagrt/codegen/codegen_base.py b/dagrt/codegen/codegen_base.py index 897df17dfec9af19c809df60a3d00397b82a763e..7bab08ee6b0279cbc17b68867fcf1c31c9646aa3 100644 --- a/dagrt/codegen/codegen_base.py +++ b/dagrt/codegen/codegen_base.py @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from .ast import Block, IfThen, IfThenElse, InstructionWrapper +from dagrt.codegen.dag_ast import Block, IfThen, IfThenElse, InstructionWrapper class StructuredCodeGenerator(object): diff --git a/dagrt/codegen/ast.py b/dagrt/codegen/dag_ast.py similarity index 100% rename from dagrt/codegen/ast.py rename to dagrt/codegen/dag_ast.py diff --git a/dagrt/codegen/data.py b/dagrt/codegen/data.py index 824e33a1975f3c10ddcb638322bdcd114fbd60cf..61176fb975fcb47ff3a1d997b3b245960b8f5986 100644 --- a/dagrt/codegen/data.py +++ b/dagrt/codegen/data.py @@ -410,7 +410,7 @@ class SymbolKindFinder(object): result = SymbolKindTable() - from .ast import get_instructions_in_ast + from dagrt.codegen.dag_ast import get_instructions_in_ast def make_kim(func_name, check): return KindInferenceMapper( diff --git a/dagrt/codegen/expressions.py b/dagrt/codegen/expressions.py index e20d4409950e344a54800c965c217174f28b2716..6f530ad7e304de626a6e00148f4b75f9bf5bec17 100644 --- a/dagrt/codegen/expressions.py +++ b/dagrt/codegen/expressions.py @@ -1,6 +1,6 @@ """Code generation of expressions""" from pymbolic.mapper.stringifier import ( - StringifyMapper, PREC_NONE, PREC_CALL, PREC_PRODUCT) + StringifyMapper, PREC_NONE, PREC_CALL, PREC_PRODUCT, PREC_LOGICAL_OR) import numpy as np @@ -139,7 +139,7 @@ class PythonExpressionMapper(StringifyMapper): """Converts expressions to Python code.""" def __init__(self, name_manager, function_registry, - numpy='numpy'): + numpy="numpy"): """name_manager is a map from a variable name (as a string) to its representation (as a string). @@ -152,7 +152,7 @@ class PythonExpressionMapper(StringifyMapper): def map_foreign(self, expr, *args): if expr is None: - return 'None' + return "None" elif isinstance(expr, str): return repr(expr) else: @@ -165,11 +165,11 @@ class PythonExpressionMapper(StringifyMapper): def map_numpy_array(self, expr, *args): if len(expr.shape) > 1: - raise ValueError('Representing multidimensional arrays is ' + - 'not supported') + raise ValueError( + "Representing multidimensional arrays is not supported") elements = [self.rec(element, *args) for element in expr] - return '{numpy}.array([{elements}],dtype=\'object\')'.format( - numpy=self._numpy, elements=', '.join(elements)) + return "{numpy}.array([{elements}],dtype=\'object\')".format( + numpy=self._numpy, elements=", ".join(elements)) def map_generic_call(self, symbol, args, kwargs): arg_strs_dict = {} @@ -187,12 +187,12 @@ class PythonExpressionMapper(StringifyMapper): self.rec(val, PREC_NONE) for val in args ] + [ - '{name}={expr}'.format( + "{name}={expr}".format( name=name, expr=self.rec(val, PREC_NONE)) for name, val in kwargs.items()] - return '{rhs}({args})'.format( + return "{rhs}({args})".format( rhs=self._name_manager.name_function(symbol.name), args=", ".join(args_strs)) @@ -212,10 +212,12 @@ class PythonExpressionMapper(StringifyMapper): from dagrt.expression import PREC_IFTHENELSE return self.parenthesize_if_needed( "{then} if {cond} else {else_}".format( - then=self.rec(expr.then, PREC_IFTHENELSE), - cond=self.rec(expr.condition, PREC_IFTHENELSE), - else_=self.rec(expr.else_, PREC_IFTHENELSE)), - enclosing_prec, PREC_NONE) + # "1 if 0 if 1 else 2 else 3" is not valid Python. + # So force parens by using an artificially higher precedence. + then=self.rec(expr.then, PREC_LOGICAL_OR), + cond=self.rec(expr.condition, PREC_LOGICAL_OR), + else_=self.rec(expr.else_, PREC_LOGICAL_OR)), + enclosing_prec, PREC_IFTHENELSE) # }}} diff --git a/dagrt/codegen/fortran.py b/dagrt/codegen/fortran.py index ce839bd4445d1572dbb22f17f4e29ff0453c5a83..e4c8a5ddbbe428c772f4b6efca3e2eb5454be750 100644 --- a/dagrt/codegen/fortran.py +++ b/dagrt/codegen/fortran.py @@ -28,8 +28,8 @@ from functools import partial import re # noqa import six -from .expressions import FortranExpressionMapper -from .codegen_base import StructuredCodeGenerator +from dagrt.codegen.expressions import FortranExpressionMapper +from dagrt.codegen.codegen_base import StructuredCodeGenerator from dagrt.utils import is_state_variable from dagrt.codegen.data import UserType from pytools.py_codegen import ( @@ -38,7 +38,7 @@ from pytools.py_codegen import ( from pymbolic.primitives import (Call, CallWithKwargs, Variable, Subscript, Lookup) from pymbolic.mapper import IdentityMapper -from .utils import (wrap_line_base, KeyToUniqueNameMap, +from dagrt.codegen.utils import (wrap_line_base, KeyToUniqueNameMap, make_identifier_from_name) @@ -1028,10 +1028,10 @@ class CodeGenerator(StructuredCodeGenerator): "used more than once") self.used = True - from .analysis import verify_code + from dagrt.codegen.analysis import verify_code verify_code(dag) - from .transform import ( + from dagrt.codegen.transform import ( eliminate_self_dependencies, isolate_function_arguments, isolate_function_calls, @@ -1046,7 +1046,7 @@ class CodeGenerator(StructuredCodeGenerator): # {{{ produce function name / function AST pairs - from .ast import create_ast_from_phase + from dagrt.codegen.dag_ast import create_ast_from_phase from collections import namedtuple NameASTPair = namedtuple("NameASTPair", "name, ast") # noqa @@ -1064,7 +1064,7 @@ class CodeGenerator(StructuredCodeGenerator): [fd.name for fd in fdescrs], [fd.ast for fd in fdescrs]) - from .analysis import collect_ode_component_names_from_dag + from dagrt.codegen.analysis import collect_ode_component_names_from_dag component_ids = collect_ode_component_names_from_dag(dag) if not component_ids <= set(self.user_type_map): @@ -1204,7 +1204,7 @@ class CodeGenerator(StructuredCodeGenerator): self.emit(l) self.emit('') - from .analysis import collect_time_ids_from_dag + from dagrt.codegen.analysis import collect_time_ids_from_dag for i, time_id in enumerate(sorted(collect_time_ids_from_dag(dag))): self.emit("integer dagrt_time_{time_id}".format(time_id=time_id)) self.emit("parameter (dagrt_time_{time_id} = {i})".format( @@ -1226,7 +1226,7 @@ class CodeGenerator(StructuredCodeGenerator): # {{{ component name constants - from .analysis import collect_ode_component_names_from_dag + from dagrt.codegen.analysis import collect_ode_component_names_from_dag component_ids = collect_ode_component_names_from_dag(dag) for i, comp_id in enumerate(sorted(component_ids)): diff --git a/dagrt/codegen/python.py b/dagrt/codegen/python.py index b02c7588e87f1be08059248971ba314e6b589550..cf09a682d0134964e6ba83d724c4e80727c6262a 100644 --- a/dagrt/codegen/python.py +++ b/dagrt/codegen/python.py @@ -22,9 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from .expressions import PythonExpressionMapper -from .codegen_base import StructuredCodeGenerator -from .utils import (wrap_line_base, exec_in_new_namespace, +from dagrt.codegen.expressions import PythonExpressionMapper +from dagrt.codegen.codegen_base import StructuredCodeGenerator +from dagrt.codegen.utils import (wrap_line_base, exec_in_new_namespace, KeyToUniqueNameMap) from pytools.py_codegen import ( PythonCodeGenerator as PythonEmitter, @@ -34,9 +34,6 @@ from functools import partial import six -# from .ir import YieldStateInst - - def pad_python(line, width): line += ' ' * (width - 1 - len(line)) line += '\\' @@ -203,10 +200,10 @@ class CodeGenerator(StructuredCodeGenerator): self._name_manager, function_registry, numpy='self._numpy') def __call__(self, dag): - from .analysis import verify_code + from dagrt.codegen.analysis import verify_code verify_code(dag) - from .ast import create_ast_from_phase + from dagrt.codegen.dag_ast import create_ast_from_phase self.begin_emit(dag) for phase_name in six.iterkeys(dag.phases): @@ -220,7 +217,7 @@ class CodeGenerator(StructuredCodeGenerator): def _pre_lower(self, ast): self._has_yield_inst = False from dagrt.language import YieldState - from .ast import get_instructions_in_ast + from dagrt.codegen.dag_ast import get_instructions_in_ast for inst in get_instructions_in_ast(ast): if isinstance(inst, YieldState): self._has_yield_inst = True diff --git a/dagrt/expression.py b/dagrt/expression.py index 41f53180d242a64c8bb8fe1b2ee36c8a6f439abe..63f1b7c5d1d0e37df6e21354c2c035ea7aa82422 100644 --- a/dagrt/expression.py +++ b/dagrt/expression.py @@ -32,6 +32,7 @@ from pymbolic.mapper.unifier import UnidirectionalUnifier from pymbolic.primitives import Variable, is_constant from pymbolic.parser import Parser, _less, _greater, _identifier from pymbolic.primitives import If as IfThenElse # noqa +from pymbolic.mapper.stringifier import PREC_LOGICAL_OR import logging import operator @@ -42,7 +43,7 @@ logger = logging.getLogger(__name__) # Precedence constant for IfThenElse. -PREC_IFTHENELSE = 1 +PREC_IFTHENELSE = PREC_LOGICAL_OR - 1 class ExtendedDependencyMapper(DependencyMapper): diff --git a/dagrt/language.py b/dagrt/language.py index 4441ff59c8b5cc61e672b3f78087e7d05f910f0c..6130ceba5eaca4a32241eb5d172bc13061cfbc00 100644 --- a/dagrt/language.py +++ b/dagrt/language.py @@ -106,6 +106,8 @@ Instructions Assignment Instructions ^^^^^^^^^^^^^^^^^^^^^^^ +These instructions perform updates to the execution state, i.e. the variables. + .. autoclass:: AssignSolved .. autoclass:: AssignExpression .. autoclass:: AssignFunctionCall @@ -113,12 +115,20 @@ Assignment Instructions Control Instructions ^^^^^^^^^^^^^^^^^^^^ +These instructions affect the execution of a phase, or cause a phase to interact +with user code. + .. autoclass:: YieldState .. autoclass:: Raise .. autoclass:: FailStep .. autoclass:: ExitStep .. autoclass:: PhaseTransition +Miscellaneous Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. autoclass:: Nop + Code Container ~~~~~~~~~~~~~~ diff --git a/test/test_ast.py b/test/test_ast.py index 1cd726addff56da8bd1e8e76f1fa20529e39b733..aa6c451ec10ea8685612e7c2cedb1b0d6975646b 100755 --- a/test/test_ast.py +++ b/test/test_ast.py @@ -27,7 +27,7 @@ from pymbolic import var from pymbolic.primitives import LogicalNot -from dagrt.codegen.ast import (IfThen, IfThenElse, Block, InstructionWrapper, +from dagrt.codegen.dag_ast import (IfThen, IfThenElse, Block, InstructionWrapper, create_ast_from_phase, simplify_ast) from dagrt.language import Instruction, DAGCode