diff --git a/dagrt/codegen/fortran.py b/dagrt/codegen/fortran.py index 9596f203e32dd0a786ac5bcf840cf66be10cbfbb..0bb06c8934683dac4b47ace590a0e4db830a7e2f 100644 --- a/dagrt/codegen/fortran.py +++ b/dagrt/codegen/fortran.py @@ -2247,6 +2247,9 @@ class CodeGenerator(StructuredCodeGenerator): self.emit("goto 999") + def emit_inst_ExitStep(self, inst): + self.emit("goto 999") + def emit_inst_StateTransition(self, inst): self.emit( 'dagrt_state%dagrt_next_state = ' diff --git a/dagrt/codegen/python.py b/dagrt/codegen/python.py index 903b22b9eb98356e7d6b4657a8a41bf0a262f453..945d5cfbb723c23c2ca360fba6bde3f697386866 100644 --- a/dagrt/codegen/python.py +++ b/dagrt/codegen/python.py @@ -91,6 +91,10 @@ class FailStepException(RuntimeError): pass +class ExitStepException(RuntimeError): + pass + + class TransitionEvent(Exception): def __init__(self, next_state): @@ -326,6 +330,9 @@ class CodeGenerator(StructuredCodeGenerator): yield self.StepFailed(t=self.t) continue + except self.ExitStepException: + continue + except self.TransitionEvent as evt: self.next_state = evt.next_state @@ -467,6 +474,11 @@ class CodeGenerator(StructuredCodeGenerator): if not self._has_yield_inst: self._emit('yield') + def emit_inst_ExitStep(self, inst): + self._emit('raise self.ExitStepException()') + if not self._has_yield_inst: + self._emit('yield') + def emit_inst_StateTransition(self, inst): assert '\'' not in inst.next_state self._emit('raise self.TransitionEvent(\'' + inst.next_state + '\')') diff --git a/dagrt/exec_numpy.py b/dagrt/exec_numpy.py index 3d7041149430adc234c2617658cc15dca160a6f8..dd24c7377d653ca669cf6d2b3f31ecb7e8c91714 100644 --- a/dagrt/exec_numpy.py +++ b/dagrt/exec_numpy.py @@ -31,6 +31,10 @@ class FailStepException(Exception): pass +class ExitStepException(Exception): + pass + + class TransitionEvent(Exception): def __init__(self, next_state): @@ -148,6 +152,10 @@ class NumpyInterpreter(object): yield StepFailed(t=self.context[""]) continue + except ExitStepException: + yield StepFailed(t=self.context[""]) + continue + except TransitionEvent as evt: self.next_state = evt.next_state @@ -261,6 +269,9 @@ class NumpyInterpreter(object): def exec_FailStep(self, insn): raise FailStepException() + def exec_ExitStep(self, insn): + raise ExitStepException() + def exec_Nop(self, insn): pass diff --git a/dagrt/language.py b/dagrt/language.py index 107d1d3c963928de139569656c72638f4aaa114b..484ad1776610d6eea1a7eef16b3e5dcff44f08a7 100644 --- a/dagrt/language.py +++ b/dagrt/language.py @@ -107,19 +107,16 @@ Assignment Instructions ^^^^^^^^^^^^^^^^^^^^^^^ .. autoclass:: AssignSolved - .. autoclass:: AssignExpression - .. autoclass:: AssignFunctionCall State Instructions ^^^^^^^^^^^^^^^^^^ .. autoclass:: YieldState - .. autoclass:: Raise - .. autoclass:: FailStep +.. autoclass:: ExitStep Code Container ~~~~~~~~~~~~~~ @@ -131,7 +128,6 @@ Visualization ~~~~~~~~~~~~~ .. autofunction:: get_dot_dependency_graph - .. autofunction:: show_dependency_graph Code Creation @@ -570,7 +566,8 @@ class StateTransition(Instruction): class FailStep(Instruction): - """ + """Exits the current step with a failure indication to the controlling + program. Execution resumes with the next step as normal. """ def get_written_variables(self): @@ -582,6 +579,18 @@ class FailStep(Instruction): exec_method = six.moves.intern("exec_FailStep") +class ExitStep(Instruction): + """Exits the current step. Execution resumes with the next step as normal. + """ + + def get_written_variables(self): + return frozenset() + + def __str__(self): + return "ExitStep{cond}".format(cond=self._condition_printing_suffix()) + + exec_method = six.moves.intern("exec_ExitStep") + # }}} @@ -809,6 +818,7 @@ class CodeBuilder(object): .. automethod:: assign_solved_1 .. automethod:: yield_state .. automethod:: fail_step + .. automethod:: exit_step .. automethod:: raise_ .. automethod:: state_transition .. automethod:: __enter__ @@ -1139,6 +1149,10 @@ class CodeBuilder(object): self.fence() self._add_inst_to_context(FailStep()) + def exit_step(self): + self.fence() + self._add_inst_to_context(ExitStep()) + def raise_(self, error): self.fence() self._add_inst_to_context(Raise(error)) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index 51f60a070f8fb6d9b93a441b6865676dc015bc4b..88ca7aa661a11263550d1b2df09beb0caae8ed2c 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -143,6 +143,25 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): assert result == 3 +def test_CodeBuilder_exit_step(python_method_impl): + with CodeBuilder() as builder1: + builder1("

x", 1) + builder1.exit_step() + builder1.fence() + builder1("

x", 2) + + with CodeBuilder() as builder2: + builder2.yield_state(var('

x'), 'x', 0, 'final') + + code = DAGCode({ + "state1": builder1.as_execution_state("state2"), + "state2": builder2.as_execution_state("state2") + }, "state1") + + result = execute_and_return_single_result(python_method_impl, code) + assert result == 1 + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1])