Skip to content

Commit bf9d671

Browse files
authored
Rewrite matchcontinue to try/else (#15683)
Rewrite matchcontinue as `try ... else ... end try`, which expresses the same attempt-then-fallback control flow without matchcontinue and assigns the outputs directly: * Lookup.lookupVarInPackagesIdent / Lookup.lookupClassInFrame — try the qualified-import lookup, fall back to the unqualified one. * DAEUtil (STMT_ASSIGN_ARR traversal) — try the CREF-lhs path, else the plain path. * InstSection.instEquationCommon — try the instantiation, else emit the appropriate error and fail (nested try distinguishes the state-transition failure from the generic case). * Static.elabExpList: the enum-array fast path was a side-effecting `() := matchcontinue`; rewrite as try/else. * Static.elabCall: rewrite the interactive/scripting matchcontinue as try/else (try elabCallArgs, else failtrace then elabCallInteractive). * Static.elabCodeExp_dispatch1: inner `() := matchcontinue` becomes try/else. * InstSection.instEquationCommon: 3-case matchcontinue becomes nested try/else. * InstSection (ALG_WHEN_A): bind when_stmt out of when_stmt_opt after the branch loop (a when always has at least one branch). * CevalFunction.evaluateStatement: initialise env := inEnv before the tail-call assignment loop so the empty-tuple path keeps it set. Also found code referencing Dangerous.listReverse, which should be Dangerous.listReverseInPlace (or listReverse).
1 parent 9ce1640 commit bf9d671

6 files changed

Lines changed: 117 additions & 176 deletions

File tree

OMCompiler/Compiler/FrontEnd/CevalFunction.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,7 @@ algorithm
11501150
then (cache, env, RETURN());
11511151
case DAE.TAIL(outVars=vars)
11521152
algorithm
1153+
env := inEnv;
11531154
Values.TUPLE(vals) := v;
11541155
for val in vals loop
11551156
var::vars := vars;

OMCompiler/Compiler/FrontEnd/ComponentReference.mo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2832,7 +2832,7 @@ public function explode
28322832
input DAE.ComponentRef inCref;
28332833
output list<DAE.ComponentRef> outParts;
28342834
algorithm
2835-
outParts := Dangerous.listReverse(explode_tail(inCref, {}));
2835+
outParts := Dangerous.listReverseInPlace(explode_tail(inCref, {}));
28362836
end explode;
28372837

28382838
protected function explode_tail

OMCompiler/Compiler/FrontEnd/DAEUtil.mo

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3746,7 +3746,7 @@ public function renameUniqueOuterVars "author: BZ, 2008-12
37463746
input DAE.DAElist dae;
37473747
output DAE.DAElist odae;
37483748
algorithm
3749-
(odae,_,_) := traverseDAE(dae, AvlTreePathFunction.Tree.EMPTY(), Expression.traverseSubexpressionsHelper, (removeUniqieIdentifierFromCref, {}));
3749+
(odae,_,_) := traverseDAE(dae, AvlTreePathFunction.Tree.EMPTY(), Expression.traverseSubexpressionsHelper, (removeUniqieIdentifierFromCref, 0));
37503750
end renameUniqueOuterVars;
37513751

37523752
protected function removeUniqieIdentifierFromCref "Function for Expression.traverseExpBottomUp, removes the constant 'UNIQUEIO' from any cref it might visit."
@@ -3779,7 +3779,7 @@ public function nameUniqueOuterVars "author: BZ, 2008-12
37793779
input DAE.DAElist dae;
37803780
output DAE.DAElist odae;
37813781
algorithm
3782-
(odae,_,_) := traverseDAE(dae, AvlTreePathFunction.Tree.EMPTY(), Expression.traverseSubexpressionsHelper, (addUniqueIdentifierToCref, {}));
3782+
(odae,_,_) := traverseDAE(dae, AvlTreePathFunction.Tree.EMPTY(), Expression.traverseSubexpressionsHelper, (addUniqueIdentifierToCref, 0));
37833783
end nameUniqueOuterVars;
37843784

37853785
protected function addUniqueIdentifierToCref "author: BZ, 2008-12
@@ -4602,25 +4602,11 @@ algorithm
46024602
case (DAE.STMT_ASSIGN_ARR(type_ = tp, lhs=e, exp = e2, source = source), extraArg)
46034603
algorithm
46044604
(e_2, extraArg) := func(e2, extraArg);
4605-
() := matchcontinue()
4606-
case ()
4607-
algorithm
4608-
(e_1 as DAE.CREF(_,_), extraArg) := traverseStatementsOptionsEvalLhs(e, extraArg, func, opt);
4609-
x := if referenceEq(e2,e_2) and referenceEq(e,e_1) then inStmt else DAE.STMT_ASSIGN_ARR(tp,e_1,e_2,source);
4610-
then
4611-
();
4612-
else
4613-
algorithm
4614-
failure((DAE.CREF(_,_), _) := func(e, extraArg));
4615-
x := if referenceEq(e2,e_2) then inStmt else DAE.STMT_ASSIGN_ARR(tp,e,e_2,source);
4616-
/* We need to pass this through because simplify/etc may scalarize the cref...
4617-
true = Flags.isSet(Flags.FAILTRACE);
4618-
print(DAEDump.ppStatementStr(x));
4619-
print("Warning, not allowed to set the componentRef to a expression in DAEUtil.traverseDAEEquationsStmts\n");
4620-
*/
4621-
then
4622-
();
4623-
end matchcontinue;
4605+
(e_1, extraArg) := traverseStatementsOptionsEvalLhs(e, extraArg, func, opt);
4606+
x := match e_1
4607+
case DAE.CREF() then if referenceEq(e2,e_2) and referenceEq(e,e_1) then inStmt else DAE.STMT_ASSIGN_ARR(tp,e_1,e_2,source);
4608+
else if referenceEq(e2,e_2) then inStmt else DAE.STMT_ASSIGN_ARR(tp,e,e_2,source);
4609+
end match;
46244610
then (x::{},extraArg);
46254611

46264612
case (DAE.STMT_IF(exp=e,statementLst=stmts,else_ = algElse, source = source), extraArg)

OMCompiler/Compiler/FrontEnd/InstSection.mo

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -175,43 +175,34 @@ protected function instEquationCommon
175175
output ConnectionGraph.ConnectionGraph outGraph;
176176
protected
177177
Integer errorCount = Error.getNumErrorMessages();
178+
String s;
179+
ClassInf.State state;
178180
algorithm
179-
() := matchcontinue()
180-
local
181-
String s;
182-
ClassInf.State state;
183-
184-
case ()
185-
algorithm
186-
state := ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION());
187-
(outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
188-
instEquationCommonWork(inCache, inEnv, inIH, inPrefix, inSets, state,
189-
inEquation, inInitial, inImpl, inGraph, DAE.FLATTEN(inEquation,NONE()));
190-
outDae := DAEUtil.traverseDAE(outDae, AvlTreePathFunction.Tree.EMPTY(),
191-
Expression.traverseSubexpressionsHelper,
192-
(ExpressionSimplify.simplifyWork, ExpressionSimplifyTypes.optionSimplifyOnly));
193-
then
194-
();
195-
196-
case ()
197-
algorithm
198-
failure(ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION()));
199-
s := ClassInfUtil.printStateStr(inState);
200-
Error.addSourceMessage(Error.EQUATION_TRANSITION_FAILURE, {s}, SCodeUtil.getEquationInfo(inEquation));
201-
then
202-
fail();
203-
204-
// We only want to print a generic error message if no other error message was printed
205-
// Providing two error messages for the same error is confusing (but better than none)
181+
try
182+
state := ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION());
183+
(outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
184+
instEquationCommonWork(inCache, inEnv, inIH, inPrefix, inSets, state,
185+
inEquation, inInitial, inImpl, inGraph, DAE.FLATTEN(inEquation,NONE()));
186+
outDae := DAEUtil.traverseDAE(outDae, AvlTreePathFunction.Tree.EMPTY(),
187+
Expression.traverseSubexpressionsHelper,
188+
(ExpressionSimplify.simplifyWork, ExpressionSimplifyTypes.optionSimplifyOnly));
189+
else
190+
// The instantiation failed; produce an appropriate error message and fail.
191+
try
192+
// If the class state cannot accept an equation, that is the cause.
193+
failure(ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION()));
194+
s := ClassInfUtil.printStateStr(inState);
195+
Error.addSourceMessage(Error.EQUATION_TRANSITION_FAILURE, {s}, SCodeUtil.getEquationInfo(inEquation));
206196
else
207-
algorithm
208-
true := errorCount == Error.getNumErrorMessages();
197+
// We only want to print a generic error message if no other error message was printed.
198+
// Providing two error messages for the same error is confusing (but better than none).
199+
if errorCount == Error.getNumErrorMessages() then
209200
s := "\n" + SCodeDump.equationStr(inEquation);
210201
Error.addSourceMessage(Error.EQUATION_GENERIC_FAILURE, {s}, SCodeUtil.getEquationInfo(inEquation));
211-
then
212-
fail();
213-
214-
end matchcontinue;
202+
end if;
203+
end try;
204+
fail();
205+
end try;
215206
end instEquationCommon;
216207

217208
protected function instEquationCommonWork
@@ -2268,9 +2259,9 @@ algorithm
22682259
(outCache, branch) := instStatements(outCache, inEnv, inIH, inPrefix,
22692260
inState, sstmts, inSource, inInitial, inImpl, inUnrollLoops);
22702261

2271-
when_stmt := Algorithm.makeWhenA(cond_exp, cond_prop, branch, when_stmt_opt, source);
2272-
when_stmt_opt := SOME(when_stmt);
2262+
when_stmt_opt := SOME(Algorithm.makeWhenA(cond_exp, cond_prop, branch, when_stmt_opt, source));
22732263
end for;
2264+
SOME(when_stmt) := when_stmt_opt;
22742265
then
22752266
{when_stmt};
22762267

OMCompiler/Compiler/FrontEnd/Lookup.mo

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,28 +1717,25 @@ algorithm
17171717
algorithm
17181718
node := FNode.fromRef(FGraph.lastScopeRef(env));
17191719
(qimports, uqimports) := FNode.imports(node);
1720-
() := matchcontinue(qimports, uqimports)
1720+
try
17211721
// Search among qualified imports, e.g. import A.B; or import D=A.B;
1722-
case (_::_, _)
1723-
algorithm
1724-
cr := lookupQualifiedImportedVarInFrame(qimports, id);
1725-
Mutable.update(inState,true);
1726-
// if the first name of the import A.B is equal with the scope we are in, skip it!
1727-
cr := if FNode.name(FNode.fromRef(FGraph.lastScopeRef(env))) == ComponentReferenceBasics.crefFirstIdent(cr)
1728-
then ComponentReference.crefStripFirstIdent(cr)
1729-
else cr;
1730-
f::prevFrames := listReverse(FGraph.currentScope(env));
1731-
env := FGraph.setScope(env, {f});
1732-
(cache,p_env,attr,ty,bind,cnstForRange,splicedExpData,componentEnv,name) := lookupVarInPackages(cache,env,cr,prevFrames,inState);
1733-
then ();
1722+
false := listEmpty(qimports);
1723+
cr := lookupQualifiedImportedVarInFrame(qimports, id);
1724+
Mutable.update(inState,true);
1725+
// if the first name of the import A.B is equal with the scope we are in, skip it!
1726+
cr := if FNode.name(FNode.fromRef(FGraph.lastScopeRef(env))) == ComponentReferenceBasics.crefFirstIdent(cr)
1727+
then ComponentReference.crefStripFirstIdent(cr)
1728+
else cr;
1729+
f::prevFrames := listReverse(FGraph.currentScope(env));
1730+
env := FGraph.setScope(env, {f});
1731+
(cache,p_env,attr,ty,bind,cnstForRange,splicedExpData,componentEnv,name) := lookupVarInPackages(cache,env,cr,prevFrames,inState);
1732+
else
17341733
// Search among unqualified imports, e.g. import A.B.*
1735-
case (_, _::_)
1736-
algorithm
1737-
(cache,p_env,attr,ty,bind,cnstForRange,unique,splicedExpData,componentEnv,name) := lookupUnqualifiedImportedVarInFrame(cache, uqimports, env, id);
1738-
reportSeveralNamesError(unique,id);
1739-
Mutable.update(inState,true);
1740-
then ();
1741-
end matchcontinue;
1734+
false := listEmpty(uqimports);
1735+
(cache,p_env,attr,ty,bind,cnstForRange,unique,splicedExpData,componentEnv,name) := lookupUnqualifiedImportedVarInFrame(cache, uqimports, env, id);
1736+
reportSeveralNamesError(unique,id);
1737+
Mutable.update(inState,true);
1738+
end try;
17421739
then
17431740
(cache,p_env,attr,ty,bind,cnstForRange,splicedExpData,componentEnv,name);
17441741

@@ -2859,20 +2856,17 @@ algorithm
28592856
case (cache, _, totenv, name, _)
28602857
algorithm
28612858
(qimports, uqimports) := FNode.imports(inFrame);
2862-
() := matchcontinue (qimports, uqimports)
2859+
try
28632860
// Search among the qualified imports, e.g. import A.B; or import D=A.B;
2864-
case (_::_, _)
2865-
algorithm
2866-
(cache,c,env_1,prevFrames) := lookupQualifiedImportedClassInFrame(cache,qimports,totenv,name,inState,inInfo);
2867-
then ();
2861+
false := listEmpty(qimports);
2862+
(cache,c,env_1,prevFrames) := lookupQualifiedImportedClassInFrame(cache,qimports,totenv,name,inState,inInfo);
2863+
else
28682864
// Search among the unqualified imports, e.g. import A.B.*;
2869-
case (_, _::_)
2870-
algorithm
2871-
(cache,c,env_1,prevFrames,unique) := lookupUnqualifiedImportedClassInFrame(cache,uqimports,totenv,name,inInfo);
2872-
Mutable.update(inState,true);
2873-
reportSeveralNamesError(unique,name);
2874-
then ();
2875-
end matchcontinue;
2865+
false := listEmpty(uqimports);
2866+
(cache,c,env_1,prevFrames,unique) := lookupUnqualifiedImportedClassInFrame(cache,uqimports,totenv,name,inInfo);
2867+
Mutable.update(inState,true);
2868+
reportSeveralNamesError(unique,name);
2869+
end try;
28762870
then
28772871
(cache,c,env_1,prevFrames);
28782872

OMCompiler/Compiler/FrontEnd/Static.mo

Lines changed: 56 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -155,38 +155,28 @@ protected
155155
DAE.Exp exp;
156156
DAE.Properties prop;
157157
DAE.Type last_ty = inLastType;
158+
Absyn.ComponentRef cr;
159+
Absyn.Path path, path1, path2;
160+
String name;
161+
list<String> names;
162+
Integer idx;
158163
algorithm
159164
for e in inExpl loop
160-
() := matchcontinue(e, last_ty)
161-
local
162-
Absyn.ComponentRef cr;
163-
Absyn.Path path, path1, path2;
164-
String name;
165-
list<String> names;
166-
Integer idx;
167-
165+
try
168166
// Hack to make enumeration arrays elaborate a _lot_ faster
169-
case (Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()),
170-
DAE.T_ENUMERATION(path = path2, names = names))
171-
algorithm
172-
path := AbsynUtil.crefToPath(cr);
173-
(path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path);
174-
true := AbsynUtil.pathEqual(path1, path2);
175-
idx := List.position(name, names);
176-
exp := DAE.ENUM_LITERAL(path, idx);
177-
prop := DAE.PROP(last_ty, DAE.C_CONST());
178-
then
179-
();
180-
181-
else
182-
algorithm
183-
(outCache, exp, prop) := elabExpInExpression(outCache, inEnv,
184-
e, inImplicit, inDoVect, inPrefix, inInfo);
185-
last_ty := Types.getPropType(prop);
186-
then
187-
();
188-
189-
end matchcontinue;
167+
Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()) := e;
168+
DAE.T_ENUMERATION(path = path2, names = names) := last_ty;
169+
path := AbsynUtil.crefToPath(cr);
170+
(path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path);
171+
true := AbsynUtil.pathEqual(path1, path2);
172+
idx := List.position(name, names);
173+
exp := DAE.ENUM_LITERAL(path, idx);
174+
prop := DAE.PROP(last_ty, DAE.C_CONST());
175+
else
176+
(outCache, exp, prop) := elabExpInExpression(outCache, inEnv,
177+
e, inImplicit, inDoVect, inPrefix, inInfo);
178+
last_ty := Types.getPropType(prop);
179+
end try;
190180

191181
outExpl := exp :: outExpl;
192182
outProperties := prop :: outProperties;
@@ -6664,6 +6654,9 @@ protected
66646654
Integer numErrorMessages = Error.getNumErrorMessages();
66656655
list<Integer> handles;
66666656
String name, s, s1, s2;
6657+
Absyn.Path fn_1;
6658+
String fnstr,argstr,prestr;
6659+
list<String> argstrs;
66676660
algorithm
66686661
if hasBuiltInHandler(fn) then
66696662
try
@@ -6681,47 +6674,31 @@ algorithm
66816674
end try;
66826675
end if;
66836676
handles := {};
6684-
(cache,e,prop):=
6685-
matchcontinue ()
6686-
local
6687-
Absyn.Path fn_1;
6688-
String fnstr,argstr,prestr;
6689-
list<String> argstrs;
6690-
6677+
try
66916678
// Interactive mode
6692-
case ()
6693-
algorithm
6694-
ErrorExt.setCheckpoint("elabCall_InteractiveFunction");
6695-
fn_1 := AbsynUtil.crefToPath(fn);
6696-
(cache,e,prop) := elabCallArgs(cache,env, fn_1, args, nargs, typeVars, impl,pre,info);
6697-
ErrorExt.delCheckpoint("elabCall_InteractiveFunction");
6698-
then
6699-
(cache,e,prop);
6700-
6701-
case ()
6702-
algorithm
6703-
true := Flags.isSet(Flags.FAILTRACE);
6704-
Debug.traceln("- Static.elabCall failed\n");
6705-
Debug.trace(" function: ");
6706-
fnstr := Dump.printComponentRefStr(fn);
6707-
Debug.trace(fnstr);
6708-
Debug.trace(" posargs: ");
6709-
argstrs := List.map(args, Dump.printExpStr);
6710-
argstr := stringDelimitList(argstrs, ", ");
6711-
Debug.traceln(argstr);
6712-
Debug.trace(" prefix: ");
6713-
prestr := PrefixUtil.printPrefixStr(pre);
6714-
Debug.traceln(prestr);
6715-
then
6716-
fail();
6717-
6718-
case ()
6719-
/* Handle the scripting interface */
6720-
algorithm
6721-
(cache,e,prop) := BackendCevalInterface.elabCallInteractive(cache, env, fn, args, nargs, impl, pre, info) "Elaborate interactive function calls, such as simulate(), plot() etc." ;
6722-
then (cache,e,prop);
6723-
6724-
end matchcontinue;
6679+
ErrorExt.setCheckpoint("elabCall_InteractiveFunction");
6680+
fn_1 := AbsynUtil.crefToPath(fn);
6681+
(cache,e,prop) := elabCallArgs(cache,env, fn_1, args, nargs, typeVars, impl,pre,info);
6682+
// If elabCallArgs fails, BackendCevalInterface.elabCallInteractive handles the checkpoint
6683+
ErrorExt.delCheckpoint("elabCall_InteractiveFunction");
6684+
else
6685+
// Best-effort failure trace before trying the scripting interface.
6686+
if Flags.isSet(Flags.FAILTRACE) then
6687+
Debug.traceln("- Static.elabCall failed\n");
6688+
Debug.trace(" function: ");
6689+
fnstr := Dump.printComponentRefStr(fn);
6690+
Debug.trace(fnstr);
6691+
Debug.trace(" posargs: ");
6692+
argstrs := List.map(args, Dump.printExpStr);
6693+
argstr := stringDelimitList(argstrs, ", ");
6694+
Debug.traceln(argstr);
6695+
Debug.trace(" prefix: ");
6696+
prestr := PrefixUtil.printPrefixStr(pre);
6697+
Debug.traceln(prestr);
6698+
end if;
6699+
// Handle the scripting interface: simulate(), plot() etc.
6700+
(cache,e,prop) := BackendCevalInterface.elabCallInteractive(cache, env, fn, args, nargs, impl, pre, info);
6701+
end try;
67256702
end elabCall;
67266703

67276704
protected function hasBuiltInHandler "Determine if a function has a builtin handler or not."
@@ -12242,24 +12219,16 @@ algorithm
1224212219
algorithm
1224312220
ErrorExt.setCheckpoint("elabCodeExp_dispatch1");
1224412221
id := AbsynUtil.crefFirstIdent(cr);
12245-
() := matchcontinue()
12246-
case () // if the first one is OpenModelica, search
12247-
algorithm
12248-
true := id == "OpenModelica";
12249-
(_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12250-
then
12251-
();
12252-
12253-
case () // not a class or OpenModelica, continue
12254-
algorithm
12255-
failure(Lookup.lookupClassIdent(cache, env, id));
12256-
(_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12257-
then
12258-
();
12259-
12260-
// a class which is not OpenModelica, fail
12261-
else fail();
12262-
end matchcontinue;
12222+
try
12223+
// if the first one is OpenModelica, search
12224+
true := id == "OpenModelica";
12225+
(_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12226+
else
12227+
// not a class or OpenModelica, continue; a class which is not
12228+
// OpenModelica makes this fail (and the enclosing case rolls back).
12229+
failure(Lookup.lookupClassIdent(cache, env, id));
12230+
(_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12231+
end try;
1226312232
DAE.T_CODE(ty=ct2) := Types.getPropType(prop);
1226412233
true := valueEq(ct,ct2);
1226512234
ErrorExt.delCheckpoint("elabCodeExp_dispatch1");

0 commit comments

Comments
 (0)