diff --git a/artiq/compiler/transforms/iodelay_estimator.py b/artiq/compiler/transforms/iodelay_estimator.py index 378933029..4028aefd1 100644 --- a/artiq/compiler/transforms/iodelay_estimator.py +++ b/artiq/compiler/transforms/iodelay_estimator.py @@ -229,6 +229,23 @@ class IODelayEstimator(algorithm.Visitor): # inside a `with` statement after all. self.engine.process(error.cause) + flow_stmt = None + if self.current_goto is not None: + flow_stmt = self.current_goto + elif self.current_return is not None: + flow_stmt = self.current_return + + if flow_stmt is not None: + note = diagnostic.Diagnostic("note", + "this '{kind}' statement transfers control out of " + "the 'with parallel:' statement", + {"kind": flow_stmt.keyword_loc.source()}, + flow_stmt.loc) + diag = diagnostic.Diagnostic("error", + "cannot interleave this 'with parallel:' statement", {}, + node.keyword_loc.join(node.colon_loc), notes=[note]) + self.engine.process(diag) + elif len(node.items) == 1 and types.is_builtin(context_expr.type, "sequential"): self.visit(node.body) else: diff --git a/lit-test/test/interleaving/error_toplevel_control_flow.py b/lit-test/test/interleaving/error_toplevel_control_flow.py new file mode 100644 index 000000000..1424c39fb --- /dev/null +++ b/lit-test/test/interleaving/error_toplevel_control_flow.py @@ -0,0 +1,17 @@ +# RUN: %python -m artiq.compiler.testbench.signature +diag %s >%t +# RUN: OutputCheck %s --file-to-check=%t + +def f(): + # CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement + with parallel: + # CHECK-L: ${LINE:+1}: note: this 'return' statement transfers control out of the 'with parallel:' statement + return + delay(1.0) + +def g(): + while True: + # CHECK-L: ${LINE:+1}: error: cannot interleave this 'with parallel:' statement + with parallel: + # CHECK-L: ${LINE:+1}: note: this 'break' statement transfers control out of the 'with parallel:' statement + break + delay(1.0)