require "python-visitor.k" require "python-semantics-boolean-ops.k" module PYTHON-SEMANTICS-FUNCTIONS imports PYTHON-VISITOR imports PYTHON-SEMANTICS-BOOLEAN-OPS syntax K ::= "makeFunction" "(" Int "," List "," K "," Bool ")" | "makeCodeObject" "(" Int "," List "," K "," Bool ")" syntax String ::= "paramName" "(" Argument ")" rule paramName(X:Id) => Id2String(X) rule paramName(X = _) => Id2String(X) rule paramName(* X:Id) => Id2String(X) rule paramName(** X) => Id2String(X) syntax ObjRef ::= "function" "(" Parameters "," Exp "," K ")" [strict(2)] rule [evaluate-function-object]: function(Ps:K, O:Object, Return:K) => setref(N, "__doc__", (O . String2Id("co_consts") [0])) ~> setref(N, "__name__", O . String2Id("co_name")) ~> setref(N, "__module__", (ref("globals")(.Arguments) . String2Id("get")("__name__"))) ~> setref(N, "__defaults__", ref("None")) ~> setref(N, "__globals__", (ref("globals")(.Arguments))) ~> setref(N, "__dict__", {.KeyData}) ~> setref(N, "__closure__", ref("None")) ~> setref(N, "__annotations__", {.KeyData}) ~> setref(N, "__kwdefaults__", ref("None")) ~> setref(N, "__frame__", ref(N2)) ~> makeFunction(N, Listify(Ps), Return, false) ~> ref(N) ... N:Int => N +Int 1 N2 (. => N "__code__" |-> ref(id(O)) "__class__" |-> ref("function") ) [allocation] rule codeObject(X, Ps, Ss:K, T:CodeObjectType) => setref(N, "co_varnames", tuple(.Exps)) ~> setref(N, "co_consts", tuple(docString(Ss))) ~> makescope(N, T) ~> makeCodeObject(N, Listify(Ps), Ss, false) ~> ref(N) ... N => N +Int 1 (. => ... N "co_name" |-> Id2String(X) "co_argcount" |-> 0 "co_kwonlyargcount" |-> 0 "co_nlocals" |-> 0 "__class__" |-> ref("code") "co_flags" |-> 0 ...) [allocation] context makeFunction(_, (ListItem((X:NAME = HOLE)::Argument) _:List), _, _) context makeFunction(_, (_:List ListItem(_:Argument : HOLE) _:List), _, _) context makeFunction(_, (ListItem((X = HOLE)::Argument : _) _:List), _, _) context makeFunction(_, (_:List ListItem((X = _)::Argument : HOLE) _:List), _, _) context makeFunction(_, (_:List ListItem((* _:Exp) : HOLE) _:List), _, _) context makeFunction(_, (_:List ListItem((** _) : HOLE) _:List), _, _) context makeFunction(_, _, HOLE, _) rule (. => addParam(X)) ~> makeCodeObject(N, (ListItem(X:NAME) L:List => L), _, false) ... ... N ... "co_argcount" |-> (N2:Int => N2 +Int 1) "co_nlocals" |-> (N3:Int => N3 +Int 1) ... ... rule (. => addParam(X)) ~> makeCodeObject(N, (ListItem(X:NAME) L:List => L), _, true) ... ... N ... "co_nlocals" |-> (N2 => N2 +Int 1) "co_kwonlyargcount" |-> (N3 => N3 +Int 1) ... ... rule makeCodeObject(_, ((ListItem((X:NAME = _)::Argument) => ListItem(X)) _), _, _) rule [makeFunction-defaults]: (. => setref(N, "__defaults__", test(plbool(getref2(ref(N), "__defaults__") is ref("None")), tuple(O), (getref2(ref(N), "__defaults__") + tuple(O))))) ~> makeFunction(N, ((ListItem((X:NAME = O:Object)::Argument) => ListItem(X)) _), _, false) rule [makeFunction-kwdefaults]: (. => test(plbool(getref2(ref(N), "__kwdefaults__") is ref("None")), setref(N, "__kwdefaults__", {Id2String(X) : O}), (getref2(ref(N), "__kwdefaults__")[Id2String(X)] = O))) ~> makeFunction(N, ((ListItem((X:Id = O:Object)::Argument) => ListItem(X)) _), _, true) rule [makeFunction-parameter]: makeFunction(_, ((ListItem(X:Id) => .) _), _, _) rule (. => setattr(N, "co_flags", (getattr(ref(N), "co_flags") |Int 4)) ~> addParam(* X:NAME ::Exp)) ~> makeCodeObject(N, ((ListItem(* (X) ::Exp) => ListItem(*)) L), _, false) context setattr(_, _, (getattr(HOLE, _) |Int _:Int)) rule [makeFunction-vararg]: makeFunction(N, ((ListItem(* X:NAME ::Exp) => ListItem(*)) L), _, _) rule makeFunction(_, ((ListItem(*) => .) L), _, (false => true)) rule makeCodeObject(_, ((ListItem(*) => .) L), _, (false => true)) rule (. => setattr(N, "co_flags", (getattr(ref(N), "co_flags") |Int 8)) ~> addParam(** X)) ~> makeCodeObject(N, ((ListItem(** X:NAME) => .) L), _, _) rule makeFunction(N, ((ListItem(** X) => .) L), _, _) rule (. => getref2(ref(N), "__annotations__")[paramName(Arg)] = O) ~> makeFunction(N, ((ListItem(Arg:Argument : O:Object) => ListItem(Arg)) _), _, _) rule (. => getref2(ref(N), "__annotations__")["return"] = O) ~> makeFunction(N, _, (O:Object => .Obj), _) rule makeCodeObject(N, ((ListItem(Arg:Argument : _) => ListItem(Arg)) _), _, _) syntax ObjRef ::= "makeClosure" "(" Exp ")" [strict] | "cellNum" "(" Exp "," Exp "," Exp ")" [strict] rule [dissolve-makeFunction]: makeFunction(N, ., .Obj, _) => setref(N, "__closure__", makeClosure(ref(N) . String2Id("__code__") . String2Id("co_freevars"))) rule makeClosure(O:Object) => makeClosure(list(listvalue(O))) rule makeClosure(list(.)) => tuple(.Exps) rule makeClosure(list(ListItem(N) L)) => tuple((getref2(ref(Frame), "f_cells")[N])) + makeClosure(list(L)) ... Frame:Int syntax K ::= createFunction(Id, K, K, Exp) [strict(4)] | createLambda(K, Exp) [strict(2)] | createClass(Id, K, Exp) [strict(3)] | createGenerator(Exp) [strict] | comprehension(Exp, Comps) [function] | makescope(K, CodeObjectType) | "storescope" | "propscope" | "delscope" syntax K ::= scope(K , Set, Set, Set, Set, Set, List, CodeObjectType, Bool) rule makescope (K, T:CodeObjectType) => . ... . => ListItem(scope(ref(K), .Set, .Set, .Set, .Set, .Set, .List, T, false)) ... rule visited(_) ~> storescope => . ... ListItem(scope(.K, _:Set, _:Set, _:Set, _:Set, _:Set, _:List, _, _)) ... rule [storescope]: visited(K) ~> storescope => setattr(N, "co_code", K) ~> setref(N, "co_freevars", tuple(DeListify(DeSetify( FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L) -Set LOCAL(Defs, Globals, Nonlocals, Params, Type))))) ~> setref(N, "co_cellvars", tuple(DeListify(DeSetify( FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L) &Set LOCAL(Defs, Globals, Nonlocals, Params, Type))))) ~> setref(N, "co_varnames", tuple(DeListify(PARAMS(Params) DeSetify( (LOCAL(Defs, Globals, Nonlocals, Params, Type) -Set FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L)) -Set Setify(PARAMS(Params)))))) ~> setref(N, "co_names", tuple(DeListify(DeSetify( ((Defs Uses Globals) -Set FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L)) -Set LOCAL(Defs, Globals, Nonlocals, Params, Type))))) ~> setref(N, "co_globals", tuple(DeListify(DeSetify(Globals)))) ~> setref(N, "co_nonlocals", tuple(DeListify(DeSetify(Nonlocals)))) ~> setattr(N, "co_type", Type ==K typeobject) ~> #if T #then setattr(N, "co_flags", getattr(ref(N), "co_flags") |Int 32) #else . #fi ... ListItem(scope(ref(N), Defs:Set, Uses:Set, Nonlocals:Set, Globals:Set, ChildFree:Set, Params:List, Type, T:Bool)) L rule propscope => . ... LI:ListItem rule propscope => . ... ListItem(scope(_, Defs, Uses, Nonlocals, Globals, ChildFree, Params, Type, _)) ListItem(scope(ref(N), Defs2:Set, Uses2:Set, Nonlocals2:Set, Globals2:Set, ChildFree2:Set (. => (FREE(Defs, Uses, Globals, Nonlocals, ChildFree, ListItem(scope(N, Defs2, Uses2, Nonlocals2, Globals2, ChildFree2, Params2, T, T2)) L)) -Set LOCAL(Defs, Globals, Nonlocals, Params, Type)), Params2:List, T, T2)) L rule delscope => . ... LI:ListItem => . ... syntax Set ::= FREE(Set, Set, Set, Set, Set, List) [function] syntax Set ::= LOCAL(Set, Set, Set, List, CodeObjectType) [function] syntax Set ::= BOUND(Set, List) [function] syntax List ::= PARAMS(List) [function] rule LOCAL(Defs, Globals, Nonlocals, Params, Type) => ((Defs Setify(PARAMS(Params))) -Set Globals) -Set Nonlocals when Setify(PARAMS(Params)) &Set Nonlocals ==Set . andBool Setify(PARAMS(Params)) &Set Globals ==Set . andBool Type =/=K typeobject rule LOCAL(_, Globals, Nonlocals, _, typeobject) => (SetItem("__class__") -Set Globals) -Set Nonlocals rule FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L) => Nonlocals ChildFree (((Uses) &Set BOUND(.,L)) -Set Globals) when (Nonlocals &Set BOUND(., L)) ==Set Nonlocals andBool notBool "super" in Uses rule FREE(Defs, Uses, Globals, Nonlocals, ChildFree, L) => Nonlocals ChildFree (((Uses SetItem("__class__")) &Set BOUND(.,L)) -Set Globals) when (Nonlocals &Set BOUND(., L)) ==Set Nonlocals andBool "super" in Uses rule BOUND(Bound:Set, L ListItem(scope(_, Defs, _, Nonlocals, Globals, _, Params, funcobject, _))) => BOUND((Bound LOCAL(Defs, Globals, Nonlocals, Params, funcobject)) -Set Globals, L) // if we are computing what is bound by a class definition scope, the only thing bound is __class__. Nothing in the local environment is bound. rule BOUND(Bound:Set, L ListItem(scope(_, _:Set, _:Set, _:Set, Globals:Set, _:Set, _:List, typeobject, _))) => BOUND(Bound SetItem("__class__"), L) when notBool "__class__" in Globals rule BOUND(Bound:Set, L ListItem(scope(_, _:Set, _:Set, _:Set, Globals:Set, _:Set, _:List, moduleobject, _))) => BOUND(Bound, L) rule BOUND(Bound, .) => Bound rule PARAMS(ListItem(X:Id) Params) => ListItem(Id2String(X)) PARAMS(Params) rule PARAMS(ListItem(* X:Exp) Params) => PARAMS(Params ListItem(* X)) when Params =/=List . rule PARAMS(ListItem(** X:Id) ListItem(* (Y:Id)::Exp)) => ListItem(Id2String(Y)) ListItem(Id2String(X)) rule PARAMS(ListItem(* (X:Id)::Exp)) => ListItem(Id2String(X)) rule PARAMS(ListItem(** X:Id)) => ListItem(Id2String(X)) rule PARAMS(ListItem(* (X:Id)::Exp) ListItem(** Y:Id)) => ListItem(Id2String(X)) ListItem(Id2String(Y)) rule PARAMS(.) => . rule createFunction(X:Id, Ps, K:K, O:Object) => visited((X)::Target = function(Ps, O, K)) rule createLambda(Ps, O:Object) => visited(function(Ps, O, .Obj)) rule createClass(X:Id, As, O:Object) => visited((X)::Target = class(As, O)) rule createGenerator(O:Object) => visited(function(.Parameters, O, .Obj)(.Arguments)) rule comprehension(E, for T in E2 Comps ::Comps) => for T in E2 : comprehension(E, Comps) rule comprehension(E, if E2 Comps ::Comps) => if E2 : comprehension(E, Comps) rule comprehension(E, .Comps) => yield E ; rule makeCodeObject(N, ., Ss, _) => visit(Ss, 'optimizeVisitor) ~> visit(Ss, 'compileVisitor) ~> visit(Ss, 'childScopeVisitor) ~> visit(Ss, 'syntaxCheckerVisitor) ~> storescope ~> propscope ~> delscope rule (visited(Ss) => .) ~> visit((_ => Ss), 'compileVisitor) rule (visited(Ss) => .) ~> visit((_ => Ss), 'childScopeVisitor) rule (visited(Ss) => .) ~> visit((_ => Ss), 'syntaxCheckerVisitor) syntax K ::= compileVisitor(KLabel, Int, K) | parameterVisitor(KLabel, Int, K) | bindVisitor(KLabel, Int, K) | importVisitor(KLabel, Int, K) | withVisitor(KLabel, Int, K) | childScopeVisitor(KLabel, Int, K) | syntaxCheckerVisitor(KLabel, Int, K) | optimizeVisitor(KLabel, Int, K) syntax K ::= addDef(Id) | addUse(Id) | addNonlocals(NAMES) | addGlobals(NAMES) | addParam(Parameter) | "setGenerator" rule addDef(X) => . ... ListItem(scope(_, _ (. => SetItem(Id2String(X))), _, _, _, _, _, _, _)) ... rule addUse(X) => . ... ListItem(scope(_, _, _ (. => SetItem(Id2String(X))), _, _, _, _, _, _)) ... rule addNonlocals(X , Xs => Xs) ... ListItem(scope(_, _, _, _ (. => SetItem(Id2String(X))), _, _, _, _, _)) ... rule addGlobals(X, Xs => Xs) ... ListItem(scope(_, _, _, _, _ (. => SetItem(Id2String(X))), _, _, _, _)) ... rule addParam(K) => . ... ListItem(scope(_, _:Set, _:Set, _:Set, _:Set, _:Set, _ (. => ListItem(K)), _, _)) ... rule setGenerator => . ... ListItem(scope(_, _:Set, _:Set, _:Set, _:Set, _:Set, _, _, (_ => true))) ... rule addGlobals(.NAMES) => . rule addNonlocals(.NAMES) => . rule compileVisitor('import_, 0, K) => visit(K, 'importVisitor) rule compileVisitor('from_import_, 0, K) => visited(K) rule compileVisitor('from_import_, 1, K) => visit(K, 'importVisitor) rule importVisitor('_._, 1, K) => visited(K) rule importVisitor('_as_, 0, K) => visited(K) rule importVisitor(Lbl:KLabel, N, K) => visit(K, 'importVisitor) when notBool((N ==Int 1 andBool Lbl ==KLabel '_._) orBool (N ==Int 0 andBool Lbl ==KLabel '_as_)) andBool N =/=Int -1 rule importVisitor(returner, -1, X:Id) => visit(X, 'bindVisitor) rule importVisitor(returner, -1, K) => visited(K) when isId(K) =/=K true rule compileVisitor('def_`(_`):_, 0, X) => visit(X, 'bindVisitor) rule compileVisitor('def_`(_`):_, 1, Ps) => visit(Ps, 'parameterVisitor) rule compileVisitor('def_`(_`):_, 2, Ss) => visited(Ss) rule childScopeVisitor('def_`(_`):_, N, K) => visited(K) rule childScopeVisitor(returner, -1, (def X (Ps): Ss)) => createFunction(X, Ps, .Obj, codeObject(X, Ps, Ss, funcobject)) rule compileVisitor('def_`(_`)->_:_, 0, X) => visit(X, 'bindVisitor) rule compileVisitor('def_`(_`)->_:_, 1, Ps) => visit(Ps, 'parameterVisitor) rule compileVisitor('def_`(_`)->_:_, 3, Ss) => visited(Ss) rule childScopeVisitor('def_`(_`)->_:_, N, K) => visited(K) rule childScopeVisitor(returner, -1, (def X (Ps)-> K : Ss)) => createFunction(X, Ps, K, codeObject(X, Ps, Ss, funcobject)) rule compileVisitor('lambda_:_, 0, Ps) => visit(Ps, 'parameterVisitor) rule compileVisitor('lambda_:_, 1, K) => visited(K) rule childScopeVisitor('lambda_:_, N, K) => visited(K) rule childScopeVisitor(returner, -1, (lambda Ps : K)) => createLambda(Ps, codeObject(String2Id(""), Ps, return K, funcobject)) rule compileVisitor('GeneratorExp, N, K) => visited(K) rule childScopeVisitor('GeneratorExp, N, K) => visited(K) rule childScopeVisitor(returner, -1, generator(E Comp)) => createGenerator(codeObject(String2Id(""), .Parameters, comprehension(E, Comp), funcobject)) rule parameterVisitor('_=_,1,K) => visit(K, 'compileVisitor) rule parameterVisitor('_:_,1,K) => visit(K, 'compileVisitor) rule parameterVisitor(Lbl, N, K) => visit(K, 'parameterVisitor) when notBool(N ==Int 1 andBool (Lbl ==KLabel '_=_ orBool Lbl ==KLabel '_:_)) andBool N =/=Int -1 rule parameterVisitor(returner, -1, K) => visited(K) rule compileVisitor('class_`(_`):_, 0, X) => visit(X, 'bindVisitor) rule compileVisitor('class_`(_`):_, 2, Ss) => visited(Ss) rule childScopeVisitor('class_`(_`):_, N, K) => visited(K) rule childScopeVisitor(returner, -1, (class X (As:K): Ss)) => createClass(X, As, codeObject(X, .Parameters, Ss, typeobject)) rule compileVisitor(returner, -1, (yield E)) => setGenerator ~> visited(yield E) rule compileVisitor('_=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_+=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_-=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_*=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_/=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_FloorDiv=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_%=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_**=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_>>=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_<<=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_&=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_^=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('_|=_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('for_in_:_else:_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('with_:_,0,K) => visit(K, 'withVisitor) rule compileVisitor('except_as_:_,1,K) => visit(K, 'bindVisitor) rule compileVisitor('del_,0,K) => visit(K, 'bindVisitor) rule compileVisitor('global_,0,Xs:NAMES) => addGlobals(Xs) ~> visited(Xs) rule compileVisitor('nonlocal_,0,Xs:NAMES) => addNonlocals(Xs) ~> visited(Xs) rule compileVisitor(returner, -1, X:Id) => addUse(X) ~> visited(X) rule compileVisitor('_=_, 0, K) => visited(K) rule withVisitor('_as_, 0, K) => visit(K, 'compileVisitor) rule withVisitor('_as_, 1, K) => visit(K, 'bindVisitor) rule withVisitor(Lbl, N, K) => visit(K, 'compileVisitor) when notBool(Lbl ==KLabel '_as_) andBool N =/=Int -1 rule withVisitor(returner, -1, K) => visited(K) rule bindVisitor('_._, 0, K) => visit(K, 'compileVisitor) rule bindVisitor('_._, 1, K) => visited(K) rule bindVisitor('_`[_`], 0, K) => visit(K, 'compileVisitor) rule bindVisitor('_`[_`], 1, K) => visited(K) rule bindVisitor('_as_, 0, K) => visit(K, 'compileVisitor) rule bindVisitor('_as_, 1, K) => visited(K) rule bindVisitor(Lbl, N, K) => visit(K, 'bindVisitor) when notBool(Lbl ==KLabel '_as_ orBool Lbl ==KLabel '_._ orBool Lbl ==KLabel '_`[_`]) andBool N =/=Int -1 rule bindVisitor(returner, -1, X:Id) => addDef(X) ~> visited(X) rule bindVisitor(returner, -1, K) => visited(K) when isId(K) =/=K true rule childScopeVisitor(Lbl, N, K) => visit(K, 'childScopeVisitor) when notBool (Lbl ==KLabel 'def_`(_`)->_:_ orElseBool Lbl ==KLabel 'class_`(_`):_ orElseBool Lbl ==KLabel 'def_`(_`):_ orElseBool Lbl ==KLabel 'lambda_:_ orElseBool Lbl ==KLabel 'GeneratorExp) andBool N =/=Int -1 rule compileVisitor(Lbl, N, K) => visit(K, 'compileVisitor) when notBool ((Lbl ==KLabel 'def_`(_`)->_:_ andBool N =/=Int 2) orElseBool (Lbl ==KLabel 'class_`(_`):_ andBool N =/=Int 1) orElseBool (N ==Int 0 andBool (Lbl ==KLabel '_=_ orElseBool Lbl ==KLabel '_+=_ orElseBool Lbl ==KLabel '_-=_ orElseBool Lbl ==KLabel '_*=_ orElseBool Lbl ==KLabel '_/=_ orElseBool Lbl ==KLabel '_FloorDiv=_ orElseBool Lbl ==KLabel '_%=_ orElseBool Lbl ==KLabel '_**=_ orElseBool Lbl ==KLabel '_>>=_ orElseBool Lbl ==KLabel '_<<=_ orElseBool Lbl ==KLabel '_&=_ orElseBool Lbl ==KLabel '_^=_ orElseBool Lbl ==KLabel '_|=_)) orElseBool (Lbl ==KLabel 'for_in_:_else:_ andBool N ==Int 0) orElseBool (Lbl ==KLabel 'with_:_ andBool N ==Int 0) orElseBool (Lbl ==KLabel 'except_as_:_ andBool N ==Int 1) orElseBool Lbl ==KLabel 'del_ orElseBool Lbl ==KLabel 'global_ orElseBool Lbl ==KLabel 'nonlocal_ orElseBool (Lbl ==KLabel '_=_ andBool N ==Int 0) orElseBool Lbl ==KLabel 'import_ orElseBool Lbl ==KLabel 'from_import_ orElseBool Lbl ==KLabel 'def_`(_`):_ orElseBool Lbl ==KLabel 'lambda_:_ orElseBool Lbl ==KLabel 'GeneratorExp) andBool N =/=Int -1 rule syntaxCheckerVisitor('return_, 0, K) => #if Type:CodeObjectType ==K funcobject #then visit(K, 'syntaxCheckerVisitor) #else raiseInternal("SyntaxError", "return outside function") #fi ... ListItem(scope(_, _, _, _, _, _, _, Type, _)) ... rule syntaxCheckerVisitor(Lbl, N, K) => visit(K, 'syntaxCheckerVisitor) when notBool(Lbl ==KLabel 'return_) andBool N =/=Int -1 rule syntaxCheckerVisitor(returner, -1, K) => visited(K) rule compileVisitor(returner, -1, K) => visited(K) when isId(K) =/=K true andBool getKLabel K =/=KLabel 'yield_ rule childScopeVisitor(returner, -1, K) => visited(K) when getKLabel K =/=KLabel 'def_`(_`)->_:_ andBool getKLabel K =/=KLabel 'def_`(_`):_ andBool getKLabel K =/=KLabel 'class_`(_`):_ rule compileVisitor(returner, -1, .) => visited(.) rule childScopeVisitor(returner, -1, .) => visited(.) rule optimizeVisitor(returner, -1, if __debug__ : Ss else: Ss2) => visited(#if N ==Int 0 #then Ss #else Ss2 #fi) ... N rule optimizeVisitor(Lbl, N, K) => visit(K, 'optimizeVisitor) when N =/=Int -1 rule optimizeVisitor(returner, -1, if K:K : Ss else: Ss2) => visited(if K : Ss else: Ss2) when K =/=K __debug__ rule optimizeVisitor(returner, -1, K) => visited(K) when getKLabel K =/=KLabel 'if_:_else:_ andBool isId(K) =/=K true rule optimizeVisitor(returner, -1, X:Id) => visited(ref(Id2String(X))) when Id2String(X) in keywords rule optimizeVisitor(returner, -1, X:Id) => visited(X) when notBool Id2String(X) in keywords syntax Set ::= "keywords" [function] rule keywords => SetItem("True") SetItem("False") SetItem("None") endmodule