require "python-semantics-boolean-ops.k" require "python-semantics-try.k" module PYTHON-SEMANTICS-STATEMENTS imports PYTHON-SEMANTICS-BOOLEAN-OPS imports PYTHON-SEMANTICS-TRY syntax K ::= "lmark" syntax K ::= loop(K, K, CurrentFrameCellFragment) rule global _ => . rule nonlocal _ => . rule [if]: if O:Object : Ss:K else : Ss2:K => test(plbool(bool(O)), Ss, Ss2) rule E:K if O else E2:K => test(plbool(bool(O)), E, E2) rule (. => lmark) ~> (while Condition:K : Ss else: Ss2) ~> (K:K => break) . => ListItem(loop(K, while Condition : Ss else: Ss2, C)) ... C:Bag rule lmark ~> while Condition : Ss else: Ss2 => if Condition : (Ss ~> lmark ~> while Condition : Ss else: Ss2) else: Ss2 rule [terminate-loop]: break ~> _ => K ListItem(loop(K, _, C)) => . ... (_ => C) rule (. => Finally:K) ~> break ... ListItem(finally(Finally, C, XL:List, _, FL:List, Ex)) => . ... _ => XL _ => FL _ => Ex (_ => C) rule continue => lmark ~> K ~> break ... ListItem(loop(_, K, _:Bag)) ... rule (. => Finally) ~> continue ... ListItem(finally(Finally, C, XL:List, _, FL:List, Ex)) => . ... _ => XL _ => FL _ => Ex (_ => C) rule for T in E : S1 else: S2 => ref("iter") (E ::Exp) ~> (for T in HOLE : S1 else: S2) [heat] rule O:Object ~> (for T in HOLE : S1 else: S2) => for T in O : S1 else: S2 [cool] rule [mark-for]: (. => lmark) ~> (for Targets:K in O:Object : Ss else: Ss2) ~> (K => break) . => ListItem(loop(K, for Targets in O : Ss else: Ss2, C)) ... C:Bag rule [unroll-for]: lmark ~> for Target:Target in O : Ss else: Ss2 => try: (((Target) = getmember(O, "__next__", true, false, true) (.Arguments))) except ref("StopIteration"): Ss2 else: (Ss ~> lmark ~> for Target in O : Ss else: Ss2) rule O:Object ; => . rule Stmt:K newline Ss => Stmt ~> Ss rule Stmt newline .K => Stmt [macro] rule .Stmts => .K [macro] rule with O:Object : Ss => doWith(getmember(O, "__exit__", true, false, true), getmember(O, "__enter__", true, false, true) (.Arguments), ., Ss) rule with O:Object as T:Exp : Ss => doWith(getmember(O, "__exit__", true, false, true), getmember(O, "__enter__", true, false, true) (.Arguments), T, Ss) syntax K ::= doWith(Exp, Exp, K, K) [seqstrict(1, 2)] rule isKResult(O:KResult as _) => true // we copy from python-semantics-try.k so we can reuse finally functionality and still choose whether we suppress a raised exception rule (doWith(Exit:Object, Enter:Object, T, Ss) => #if T ==K . #then . #else (T) ::Target = Enter #fi ~> Ss ~> popfinally ~> Exit(* ref("sys_exc_info")(.Arguments)) ;) ~> K (. => ListItem(finally(if not Exit(* ref("sys_exc_info")(.Arguments)): raise else: (setx(Ex) ~> K), C, XL, LL, FL, Ex))) XL:List (. => ListItem(finally(Exit(* ref("sys_exc_info")(.Arguments)) ;, C, XL, LL, FL, Ex))) LL:List (. => ListItem(finally(Exit(* ref("sys_exc_info")(.Arguments)) ;, C, XL, LL, FL, Ex))) FL:List Ex C:Bag endmodule