Skip to content

Commit

Permalink
Ticket 248: Kranc: EDL if/else blocks: Basic functionality.
Browse files Browse the repository at this point in the history
 - Modify grammar to recognize if/else. (Code by Steve Brandt)
 - Use IfThen operators for equations guarded by if/else.
  • Loading branch information
dmkoppelman committed Apr 13, 2018
1 parent 96738c6 commit b16893f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Auxiliary/Grammars/kranc2.peg
Expand Up @@ -43,7 +43,8 @@ ifexpr = if {cexpr} then {mexpr} else {mexpr}
eqn = ({dtensor}|{tensor}) \= {expr}{-end}
doper = {dname}{indices}
deqn = {doper} {barename} \= {expr}{-end}
eqns = {eqn}( {eqn})*
ifblock = if \( {cexpr} \) \{ {eqns} \}( else \{ {eqns} \}|)|{eqn}
eqns = {ifblock}( {ifblock})*
deqns = {deqn}( {deqn})*
at_or_in = (at|in)
on_clause = on {uname}
Expand Down
62 changes: 60 additions & 2 deletions Tools/CodeGen/KrancScript.m
Expand Up @@ -142,7 +142,7 @@

process[calc:"calculation"[content___]] :=
Module[
{name,eqs,joinWord,where},
{name,eqs,joinWord,where,dbeq},
name = Cases[calc, "uname"[n_]:>n][[1]];
eqs = Cases[calc, "eqns"[es___]:>{es}][[1]];

Expand All @@ -160,11 +160,51 @@
StringMatchQ[schedule,"analysis",IgnoreCase->True],
"at","in"];

dbeq = process["eqns"[eqs]];

(* Use IfThen operator for assignments in if/else blocks. *)
Module[{ condstack = {True}, currPred = True, varsCondAs = {} },

(* Replace assignments delineated by ChemoraIfBlock markers with Kranc
IfThen things. *)
dbeq =
( # /.
{ ( v_ -> ChemoraIfBlockStart[e_] ) :>
( condstack = Join[condstack,{currPred,v}];
currPred = ChemoraOpAnd[currPred, v];
v -> e ),
( _ -> ChemoraIfBlockElseMarker[] ) :>
( currPred = ChemoraOpAnd[condstack[[-2]], ! condstack[[-1]]];
{} ),
( _ -> ChemoraIfBlockEnd[] ) :>
( currPred = condstack[[-2]];
condstack = Drop[condstack,-2];
{} ),
( v_ -> e_ ) :>
If[ currPred === True,
v -> e,
AppendTo[varsCondAs,v];
v -> IfThen[currPred,e,v] ]
} )& /@ dbeq // Flatten;

(* Initialize variables assigned in if/else blocks to avoid
the use of an uninitialized variable in the first IfThen construct
for a variable. *)
dbeq = Join[ # -> 0 & /@ Union[varsCondAs], dbeq ];

dbeq = dbeq //. ChemoraOpAnd[True,v_] -> v;
];

{Name -> name,
Equations -> Map[process,eqs],
Equations -> dbeq,
Schedule -> {joinWord<>" "<>schedule},
Where -> where}];

process["eqns"[]] := {}
process["eqns"[ifbl:"ifblock"[___],more___]] :=
{ process[ifbl],process["eqns"[more]] }
process["eqns"[eqs_List]] := Flatten[ process /@ eqs ];

process["eqn"[lhs_,rhs_]] := Module[{name,eqs}, process[lhs] -> process[rhs]];
(*
process["tensor"["name"["Opast"],"indices"[ind___],follow___]] := Print["ind=",InputForm[ind]," follow=",InputForm[follow]];
Expand Down Expand Up @@ -261,6 +301,24 @@
process["ifexpr"[cond_, opt1_, opt2_]] :=
IfThen[ process[cond], process[opt1], process[opt2] ];

chemoraIntermediateCount = 0;
chemoraMakeIntermediate[]:=
"chemoraIntermediate" <> ToString[chemoraIntermediateCount++];

process["ifblock"[cexpr:"cexpr"[_],eqif:"eqns"[___],eqelse:"eqns"[___]]] :=
{ chemoraMakeIntermediate[] -> ChemoraIfBlockStart[process[cexpr]],
process[eqif],
chemoraMakeIntermediate[] -> ChemoraIfBlockElseMarker[],
process[eqelse],
chemoraMakeIntermediate[] -> ChemoraIfBlockEnd[] }

process["ifblock"[cexpr:"cexpr"[_],eqif:"eqns"[___]]] :=
{ chemoraMakeIntermediate[] -> ChemoraIfBlockStart[process[cexpr]],
process[eqif],
chemoraMakeIntermediate[] -> ChemoraIfBlockEnd[] }

process["ifblock"[eqn_]] := process[eqn];

process["coexpr"["cexpr"[cexpr__]]] := process["cexpr"[cexpr]];

process["cexpr"[Longest[v1__], "logop"["or"], v2__]] :=
Expand Down

0 comments on commit b16893f

Please sign in to comment.