Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 424
Functions: -% 0 / 1 / 1
Branches: 0.0% 0 / 0 / 70

OMCompiler/Compiler/MidCode/DAEToMid.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package DAEToMid
37
38 public
39 import MidCode;
40 import SimCodeFunction;
41
42 function DAEFunctionsToMid
43 input list<SimCodeFunction.Function> simfuncs;
44 output list<MidCode.Function> midfuncs;
45 algorithm
46 ✗ midfuncs := list(DAEFunctionToMid(simfunc) for simfunc in simfuncs);
47 end DAEFunctionsToMid;
48
49 protected
50 import Absyn;
51 import DAE;
52 import DAEDump;
53 import MidToMid;
54 import SimCode;
55 import Expression;
56 import ExpressionDump;
57 import ComponentReference;
58 protected import ComponentReferenceBasics;
59 import System;
60 import DoubleEnded;
61 import Mutable;
62 import BaseHashTable;
63 import HashTableMidVar;
64 import List;
65 import Error;
66 import Types;
67
68 uniontype State
69 record STATE
70 DoubleEnded.MutableList<MidCode.Var> locals;
71 DoubleEnded.MutableList<MidCode.VarBuf> localBufs;
72 DoubleEnded.MutableList<MidCode.VarBufPtr> localBufPtrs;
73 DoubleEnded.MutableList<MidCode.Block> blocks;
74 DoubleEnded.MutableList<MidCode.Stmt> stmts;
75 Mutable.Mutable<Integer> blockid;
76 Mutable.Mutable<list<Integer>> continuejumps;
77 Mutable.Mutable<list<Integer>> breakjumps;
78 Mutable.Mutable<HashTableMidVar.HashTable> vars;
79 end STATE;
80 end State;
81
82 function listZip<X,Y>
83 "List.zip fails for lists of unequal length
84 but truncating is the more common semantics."
85 input list<X> xs;
86 input list<Y> ys;
87 output list<tuple<X,Y>> zs;
88 protected
89 list<X> xs_;
90 list<Y> ys_;
91 X x;
92 Y y;
93 algorithm
94 zs := match (xs,ys)
95 case ({} , _) then {};
96 case (_ , {}) then {};
97 ✗ case (x::xs_, y::ys_) then (x,y) :: listZip(xs_,ys_);
98 end match;
99 end listZip;
100
101 function GenTmpVar
102 input DAE.Type ty;
103 input State state;
104 output MidCode.Var var;
105 algorithm
106 ✗ var := MidCode.VAR("_tmp_" + intString(System.tmpTickIndex(46)), ty, false);
107 ✗ DoubleEnded.push_back(state.locals, var);
108 end GenTmpVar;
109
110 function GenTmpVarVolatile
111 input DAE.Type ty;
112 input State state;
113 output MidCode.Var var;
114 algorithm
115 ✗ var := MidCode.VAR("_tmp_" + intString(System.tmpTickIndex(46)), ty, true);
116 ✗ DoubleEnded.push_back(state.locals, var);
117 end GenTmpVarVolatile;
118
119 function GenTmpVarBuf
120 /*
121 Uses same naming scheme as variables.
122 Doesn't have to as long as they don't collide.
123 */
124 input State state;
125 output MidCode.VarBuf var;
126 algorithm
127 ✗ var := MidCode.VARBUF("_jmpbuf_" + intString(System.tmpTickIndex(47)));
128 ✗ DoubleEnded.push_back(state.localBufs, var);
129 end GenTmpVarBuf;
130
131 function GenTmpVarBufPtr
132 /*
133 Uses same naming scheme as variables.
134 Doesn't have to as long as they don't collide.
135 */
136 input State state;
137 output MidCode.VarBufPtr var;
138 algorithm
139 ✗ var := MidCode.VARBUFPTR("_tmp_" + intString(System.tmpTickIndex(46)));
140 ✗ DoubleEnded.push_back(state.localBufPtrs, var);
141 end GenTmpVarBufPtr;
142
143 function GenBlockId
144 output Integer id;
145 algorithm
146 ✗ id := System.tmpTickIndex(45);
147 end GenBlockId;
148
149 function ConvertSimCodeVars
150 input SimCodeFunction.Variable simcodevar;
151 input State state;
152 output MidCode.Var var;
153 algorithm
154 var := match simcodevar
155 local
156 MidCode.Var midcodevar;
157 case SimCodeFunction.VARIABLE(__)
158 algorithm
159 ✗ midcodevar := CrefToMidVar(simcodevar.name, state);
160 () := match simcodevar.value
161 local
162 DAE.Exp exp;
163 case NONE() then ();
164 case SOME(exp)
165 algorithm
166 ✗ stateAddStmt(MidCode.ASSIGN(midcodevar, ExpToMid(exp, state)), state);
167 then ();
168 end match;
169 then midcodevar;
170 end match;
171 end ConvertSimCodeVars;
172
173 function GetCrefIndexVar
174 input DAE.ComponentRef cref;
175 input State state;
176 output Option<MidCode.Var> var;
177 protected
178 list<DAE.Subscript> subscripts;
179 algorithm
180 ✗ subscripts := ComponentReference.crefLastSubs(cref);
181
182 var := match subscripts
183 local
184 DAE.Subscript subscript;
185 MidCode.Var indexvar;
186 case {} then NONE();
187 case {subscript as DAE.INDEX(__)}
188 algorithm
189 ✗ indexvar := RValueToVar(ExpToMid(subscript.exp, state), state);
190 then SOME(indexvar);
191 end match;
192 end GetCrefIndexVar;
193
194 function CrefToMidVar
195 //TODO: handle scopes better
196 input DAE.ComponentRef cref;
197 input State state;
198 output MidCode.Var var;
199 protected
200 String ident;
201 DAE.Type ty;
202 algorithm
203 ✗ if not BaseHashTable.hasKey(cref, Mutable.access(state.vars)) then
204 (ident, ty) := match cref
205 local
206 String ident_;
207 DAE.Type ty_;
208 case DAE.CREF_IDENT(ident_, ty_, _) then (ident_, ty_);
209 else
210 algorithm
211 ✗ Error.addInternalError("CrefToMidVar error", sourceInfo());
212 ✗ then fail();
213 end match;
214 ✗ Mutable.update(state.vars, BaseHashTable.add((cref, MidCode.VAR(ident, Types.complicateType(ty), false)), Mutable.access(state.vars)));
215 end if;
216 ✗ var := BaseHashTable.get(cref, Mutable.access(state.vars));
217 end CrefToMidVar;
218
219 function RValueType
220 input MidCode.RValue rvalue;
221 output DAE.Type ty;
222 algorithm
223 ty := match rvalue
224 ✗ case MidCode.VARIABLE(__) then rvalue.src.ty;
225 //TODO: move comparisons to separate?
226 case MidCode.BINARYOP(__) then match rvalue.op
227 case MidCode.LESS() then DAE.T_BOOL_DEFAULT;
228 case MidCode.LESSEQ() then DAE.T_BOOL_DEFAULT;
229 case MidCode.GREATER() then DAE.T_BOOL_DEFAULT;
230 case MidCode.GREATEREQ() then DAE.T_BOOL_DEFAULT;
231 case MidCode.EQUAL() then DAE.T_BOOL_DEFAULT;
232 case MidCode.NEQUAL() then DAE.T_BOOL_DEFAULT;
233 ✗ else then rvalue.lsrc.ty;
234 end match;
235 ✗ case MidCode.UNARYOP(MidCode.BOX(),_) then Types.boxIfUnboxedType(rvalue.src.ty);
236 ✗ case MidCode.UNARYOP(MidCode.UNBOX(),_) then Types.unboxedType(rvalue.src.ty);
237 //TODO: separate CAST? since has new type
238 ✗ case MidCode.UNARYOP(__) then rvalue.src.ty;
239 case MidCode.LITERALINTEGER(__) then DAE.T_INTEGER_DEFAULT;
240 case MidCode.LITERALREAL(__) then DAE.T_REAL_DEFAULT;
241 case MidCode.LITERALBOOLEAN(__) then DAE.T_BOOL_DEFAULT;
242 case MidCode.LITERALSTRING(__) then DAE.T_STRING_DEFAULT;
243 ✗ case MidCode.LITERALMETATYPE(__) then rvalue.ty;
244 ✗ case MidCode.METAFIELD(__) then rvalue.ty;
245 case MidCode.UNIONTYPEVARIANT(__) then DAE.T_INTEGER_DEFAULT;
246 case MidCode.ISCONS(__) then DAE.T_BOOL_DEFAULT;
247 case MidCode.ISSOME(__) then DAE.T_BOOL_DEFAULT;
248 else
249 algorithm
250 ✗ Error.addInternalError("Could not find the correct type of an RValue.\n", sourceInfo());
251 ✗ then fail();
252 end match;
253 end RValueType;
254
255 function RValueToVar
256 input MidCode.RValue rvalue;
257 input State state;
258 output MidCode.Var var;
259 algorithm
260 var := match rvalue
261 local
262 MidCode.Var tmpvar;
263 ✗ case MidCode.VARIABLE(__) then rvalue.src;
264 else
265 algorithm
266 ✗ tmpvar := GenTmpVar(Types.complicateType(RValueType(rvalue)),state);
267 ✗ DoubleEnded.push_back(state.stmts, MidCode.ASSIGN(tmpvar, rvalue));
268 then tmpvar;
269 end match;
270 end RValueToVar;
271
272 function DAEFunctionToMid
273 input SimCodeFunction.Function simfunc;
274 output MidCode.Function midfunc;
275 protected
276 State state;
277 DoubleEnded.MutableList<MidCode.Var> inputs;
278 DoubleEnded.MutableList<MidCode.Var> outputs;
279 Absyn.Path path;
280 Integer labelFirst;
281
282 algorithm
283 ✗ System.tmpTickReset(47); //jump buffers
284 ✗ System.tmpTickReset(46); //variables
285 ✗ System.tmpTickReset(45); //block ids
286
287 () := match simfunc
288 local
289 Absyn.Path name;
290 list<SimCodeFunction.Variable> outVars;
291 list<SimCodeFunction.Variable> functionArguments;
292 list<SimCodeFunction.Variable> variableDeclarations;
293 list<DAE.Statement> body;
294
295 case SimCodeFunction.FUNCTION(name, outVars, functionArguments, variableDeclarations, body, _, _)
296 algorithm
297 ✗ labelFirst := GenBlockId();
298 path := name;
299 ✗ inputs := DoubleEnded.fromList({});
300 ✗ outputs := DoubleEnded.fromList({});
301 ✗ state := STATE(DoubleEnded.fromList({}),
302 DoubleEnded.fromList({}),
303 DoubleEnded.fromList({}),
304 DoubleEnded.fromList({}),
305 DoubleEnded.fromList({}),
306 Mutable.create(labelFirst),
307 Mutable.create({}),
308 Mutable.create({}),
309 Mutable.create(HashTableMidVar.emptyHashTable()));
310 ✗ for simcodeVar in variableDeclarations loop
311 ✗ DoubleEnded.push_back(state.locals, ConvertSimCodeVars(simcodeVar, state));
312 end for;
313 ✗ for simcodeVar in outVars loop
314 ✗ DoubleEnded.push_back(outputs, ConvertSimCodeVars(simcodeVar, state));
315 end for;
316 ✗ for simcodeVar in functionArguments loop
317 ✗ DoubleEnded.push_back(inputs, ConvertSimCodeVars(simcodeVar, state));
318 end for;
319
320 ✗ StmtsToMid(body, state);
321 then ();
322 else
323 algorithm
324 ✗ Error.addInternalError("Unsupported SimCodeFunction.Function type\n", sourceInfo());
325 ✗ fail();
326 then ();
327 end match;
328
329 ✗ stateTerminate(-1, MidCode.RETURN(), state);
330
331 ✗ midfunc := MidCode.FUNCTION(name=path,
332 locals=DoubleEnded.toListAndClear(state.locals),
333 localBufs=DoubleEnded.toListAndClear(state.localBufs),
334 localBufPtrs=DoubleEnded.toListAndClear(state.localBufPtrs),
335 inputs=DoubleEnded.toListAndClear(inputs),
336 outputs=DoubleEnded.toListAndClear(outputs),
337 body=DoubleEnded.toListAndClear(state.blocks),
338 entryId=labelFirst,
339 exitId=GenBlockId());
340 ✗ midfunc := MidToMid.longJmpGoto(midfunc);
341 end DAEFunctionToMid;
342
343 function StmtsToMid
344 input list<DAE.Statement> daestmts;
345 input State state;
346 algorithm
347 () := match daestmts
348 local
349 DAE.Statement stmt;
350 list<DAE.Statement> tail;
351 case {} then ();
352 case stmt::tail
353 algorithm
354 () := match stmt
355 local
356 DAE.Exp exp1;
357 DAE.Exp exp;
358 DAE.ComponentRef cref;
359 DAE.Pattern pattern;
360 list<DAE.Exp> expLst;
361 MidCode.Var varCref;
362 MidCode.Var varArray;
363 MidCode.Var varIndex;
364 MidCode.Var varValue;
365 MidCode.Var varCondition;
366 MidCode.Var varMessage;
367 MidCode.Var varLevel;
368 MidCode.Var varRHS;
369 Integer labelBody;
370 Integer labelNext;
371 Integer labelCondition;
372 DAE.Else else_;
373 DoubleEnded.MutableList<MidCode.OutVar> outvars;
374 String iter;
375 case DAE.STMT_ASSIGN(_, exp1 as DAE.CREF(__), exp, _)
376 algorithm
377 ✗ cref := ComponentReferenceBasics.crefLastCref(exp1.componentRef); //gå runt CREF_QUAL tills vidare
378 ✗ varCref := CrefToMidVar(cref,state);
379
380 ✗ stateAddStmt(MidCode.ASSIGN(varCref, ExpToMid(exp, state)), state);
381 then ();
382 case DAE.STMT_ASSIGN(_, exp1 as DAE.ASUB(__), exp, _)
383 algorithm
384 ✗ varArray := RValueToVar(ExpToMid(exp1.exp, state), state);
385 varIndex := match exp1.sub
386 local
387 DAE.Exp indexexp;
388 ✗ case {DAE.INDEX(indexexp)} then RValueToVar(ExpToMid(indexexp, state), state);
389 end match;
390 ✗ varValue := RValueToVar(ExpToMid(exp, state), state);
391
392 ✗ labelNext := GenBlockId();
393 ✗ stateTerminate(labelNext, MidCode.CALL(Absyn.IDENT("arrayUpdate"), true, {varArray, varIndex, varValue}, {}, labelNext), state);
394 then ();
395 case DAE.STMT_ASSIGN(_, DAE.PATTERN(pattern), exp, _)
396 algorithm
397 ✗ varRHS := RValueToVar(ExpToMid(exp,state),state);
398 ✗ patternToMidCode(matches={(varRHS,pattern)},labelNoMatch=1,state=state); // pattern match
399 then ();
400 case DAE.STMT_ASSIGN(__)
401 algorithm
402 ✗ Error.addInternalError("DAE.STMT_ASSIGN to Mid conversion failed " + ExpressionDump.dumpExpStr(stmt.exp1,0) + "\n", sourceInfo());
403 ✗ then fail();
404 case DAE.STMT_TUPLE_ASSIGN(_, expLst, exp, _)
405 algorithm
406 ✗ outvars := DoubleEnded.fromList({});
407 ✗ for exp1 in expLst loop
408 () := match exp1
409 case DAE.CREF(DAE.WILD())
410 algorithm
411 ✗ DoubleEnded.push_back(outvars, MidCode.OUT_WILD());
412 then ();
413 case DAE.CREF(__)
414 algorithm
415 ✗ varCref := CrefToMidVar(exp1.componentRef, state);
416 ✗ DoubleEnded.push_back(outvars, MidCode.OUT_VAR(varCref));
417 then ();
418 else
419 algorithm
420 ✗ Error.addInternalError("outvars convertion failed " + ExpressionDump.dumpExpStr(exp1,0) + "\n", sourceInfo());
421 ✗ then fail();
422 end match;
423 end for;
424 () := match exp
425 case DAE.CALL(__)
426 algorithm
427 ✗ CallToMid(exp, DoubleEnded.toListAndClear(outvars), state);
428 then ();
429 case DAE.MATCHEXPRESSION(__)
430 algorithm
431 ✗ MatchExpressionToMid(exp, DoubleEnded.toListAndClear(outvars), state);
432 then ();
433 end match;
434 then ();
435 case DAE.STMT_IF(__)
436 algorithm
437 ✗ IfToMid(stmt.exp, stmt.statementLst, stmt.else_, state);
438 then ();
439 case DAE.STMT_WHILE(__)
440 algorithm
441 ✗ labelCondition := GenBlockId();
442 ✗ labelBody := GenBlockId();
443 ✗ labelNext := GenBlockId();
444
445 ✗ Mutable.update(state.continuejumps, labelCondition :: Mutable.access(state.continuejumps));
446 ✗ Mutable.update(state.breakjumps, labelNext :: Mutable.access(state.breakjumps));
447
448 ✗ stateTerminate(labelCondition, MidCode.GOTO(labelCondition), state);
449
450 ✗ varCondition := RValueToVar(ExpToMid(stmt.exp, state), state);
451 ✗ stateTerminate(labelBody, MidCode.BRANCH(varCondition, labelBody, labelNext), state);
452
453 ✗ StmtsToMid(stmt.statementLst, state);
454 ✗ stateTerminate(labelNext, MidCode.GOTO(labelCondition), state);
455
456 ✗ Mutable.update(state.continuejumps, listRest(Mutable.access(state.continuejumps)));
457 ✗ Mutable.update(state.breakjumps, listRest(Mutable.access(state.breakjumps)));
458
459 then ();
460 case DAE.STMT_FOR(__)
461 algorithm
462 ✗ ForToMid(stmt.type_, stmt.iter, stmt.range, stmt.statementLst, state);
463 then ();
464 case DAE.STMT_BREAK(_)
465 algorithm
466 ✗ labelNext := GenBlockId();
467 ✗ stateTerminate(labelNext, MidCode.GOTO(listHead(Mutable.access(state.breakjumps))), state);
468 then ();
469 case DAE.STMT_CONTINUE(_)
470 algorithm
471 ✗ labelNext := GenBlockId();
472 ✗ stateTerminate(labelNext, MidCode.GOTO(listHead(Mutable.access(state.continuejumps))), state);
473 then ();
474 case DAE.STMT_RETURN(_)
475 algorithm
476 ✗ labelNext := GenBlockId();
477 ✗ stateTerminate(labelNext, MidCode.RETURN(), state);
478 then ();
479 case DAE.STMT_NORETCALL(__)
480 algorithm
481 () := match stmt.exp
482 case DAE.CALL(__)
483 algorithm
484 ✗ CallToMid(stmt.exp, {}, state);
485 then ();
486 case DAE.MATCHEXPRESSION(__)
487 algorithm
488 ✗ MatchExpressionToMid(stmt.exp, {}, state);
489 then ();
490 end match;
491 then ();
492 case DAE.STMT_ASSERT(__)
493 algorithm
494 ✗ varCondition := RValueToVar(ExpToMid(stmt.cond, state), state);
495 ✗ varMessage := RValueToVar(ExpToMid(stmt.msg, state), state);
496 ✗ varLevel := RValueToVar(ExpToMid(stmt.level, state), state);
497
498 ✗ labelNext := GenBlockId();
499
500 ✗ stateTerminate(labelNext, MidCode.ASSERT(varCondition, varMessage, varLevel, labelNext), state);
501 then ();
502 case DAE.STMT_TERMINATE(__)
503 algorithm
504 ✗ varMessage := RValueToVar(ExpToMid(stmt.msg, state), state);
505
506 ✗ labelNext := GenBlockId();
507
508 ✗ stateTerminate(labelNext, MidCode.TERMINATE(varMessage), state);
509 then ();
510 else
511 algorithm
512 ✗ Error.addInternalError("DAE.Statement to Mid conversion failed " + DAEDump.ppStatementStr(stmt), sourceInfo());
513 ✗ then fail();
514
515 end match;
516
517 ✗ StmtsToMid(tail, state);
518 then ();
519 end match;
520 end StmtsToMid;
521
522 function ExpToMid
523 input DAE.Exp exp;
524 input State state;
525 output MidCode.RValue rval;
526 algorithm
527 rval := match exp
528 local
529 MidCode.Var varExp;
530 MidCode.Var varExp2;
531 MidCode.Var varCref;
532 MidCode.Var varCar;
533 MidCode.Var varCdr;
534 MidCode.Var varTmp;
535 MidCode.BinaryOp binop;
536 MidCode.UnaryOp unop;
537 DAE.Exp exp1;
538 DAE.Exp exp2;
539 DAE.Exp exp3;
540 DAE.Operator operator;
541 DAE.Type ty;
542 DAE.ComponentRef cref;
543 Integer labelBody;
544 Integer labelElse;
545 Integer labelNext;
546 Integer index;
547 Integer numTailTypes;
548 MidCode.Terminator terminator;
549 list<DAE.Exp> expLst;
550 DoubleEnded.MutableList<MidCode.Var> values;
551 list<MidCode.OutVar> outvars;
552 DAE.CallAttributes callattrs;
553 list<DAE.Subscript> subscripts;
554 MidCode.RValue rvalue;
555 ✗ case DAE.ICONST(__) then MidCode.LITERALINTEGER(exp.integer);
556 ✗ case DAE.ENUM_LITERAL(__) then MidCode.LITERALINTEGER(exp.index);
557 ✗ case DAE.RCONST(__) then MidCode.LITERALREAL(exp.real);
558 ✗ case DAE.SCONST(__) then MidCode.LITERALSTRING(exp.string);
559 ✗ case DAE.SHARED_LITERAL(__) then ExpToMid(exp.exp, state); //don't bother with shared support yet
560 case DAE.BOX(__)
561 algorithm
562 ✗ varExp := RValueToVar(ExpToMid(exp.exp, state), state);
563 ✗ then MidCode.UNARYOP(MidCode.BOX(), varExp);
564 case DAE.UNBOX(__)
565 algorithm
566 ✗ varExp := RValueToVar(ExpToMid(exp.exp, state), state);
567 ✗ then MidCode.UNARYOP(MidCode.UNBOX(), varExp);
568 ✗ case DAE.BCONST(__) then MidCode.LITERALBOOLEAN(exp.bool);
569 case DAE.META_OPTION(SOME(exp1))
570 algorithm
571 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
572 ✗ then MidCode.LITERALMETATYPE({varExp}, Types.complicateType(DAE.T_METAOPTION(varExp.ty)));
573 case DAE.META_OPTION(NONE())
574 ✗ then MidCode.LITERALMETATYPE({}, Types.complicateType(DAE.T_NONE_DEFAULT));
575 case DAE.META_TUPLE(expLst)
576 algorithm
577 ✗ values := DoubleEnded.fromList({});
578 ✗ for exp in expLst loop
579 ✗ varExp := RValueToVar(ExpToMid(exp, state), state);
580 ✗ DoubleEnded.push_back(values, varExp);
581 end for;
582 ✗ then MidCode.LITERALMETATYPE(DoubleEnded.toListAndClear(values), Types.complicateType(Expression.typeof(exp)));
583 case DAE.METARECORDCALL(_, expLst, _, _, _)
584 algorithm
585 ✗ values := DoubleEnded.fromList({});
586 ✗ for exp in expLst loop
587 ✗ varExp := RValueToVar(ExpToMid(exp, state), state);
588 ✗ DoubleEnded.push_back(values, varExp);
589 end for;
590 ✗ then MidCode.LITERALMETATYPE(DoubleEnded.toListAndClear(values), Types.complicateType(Expression.typeof(exp)));
591 case DAE.CONS(__)
592 algorithm
593 ✗ varCar := RValueToVar(ExpToMid(exp.car, state), state);
594 ✗ varCdr := RValueToVar(ExpToMid(exp.cdr, state), state);
595 ✗ then MidCode.LITERALMETATYPE({varCar, varCdr}, Types.complicateType(DAE.T_METALIST(varCar.ty)));
596 case DAE.LIST(expLst)
597 algorithm
598 ✗ expLst := listReverse(expLst);
599
600 ✗ varCdr := GenTmpVar(DAE.T_METALIST_DEFAULT,state);
601 ✗ DoubleEnded.push_back(state.stmts, MidCode.ASSIGN(varCdr, MidCode.LITERALMETATYPE({}, DAE.T_METALIST_DEFAULT)));
602 ✗ for exp in expLst loop
603 ✗ varCar := RValueToVar(ExpToMid(exp, state), state);
604 ✗ varTmp := GenTmpVar(DAE.T_METALIST(Types.complicateType(varCar.ty)),state);
605 ✗ DoubleEnded.push_back(state.stmts, MidCode.ASSIGN(varTmp, MidCode.LITERALMETATYPE({varCar, varCdr}, Types.complicateType(DAE.T_METALIST(varCar.ty)))));
606 varCdr := varTmp;
607 end for;
608 ✗ then MidCode.VARIABLE(varCdr);
609 case DAE.CREF(cref, _)
610 algorithm
611 ✗ varCref := CrefToMidVar(cref, state);
612
613 rvalue := match GetCrefIndexVar(cref, state)
614 local
615 MidCode.Var indexvar;
616 ✗ case NONE() then MidCode.VARIABLE(varCref);
617 case SOME(indexvar)
618 algorithm
619 ✗ labelNext := GenBlockId();
620
621 ✗ varTmp := GenTmpVar(Types.complicateType(Expression.typeof(exp)),state);
622
623 ✗ stateTerminate(labelNext,
624 MidCode.CALL(Absyn.IDENT("arrayGet"), true, {varCref,indexvar}, {MidCode.OUT_VAR(varTmp)}, labelNext),
625 state);
626 ✗ then MidCode.VARIABLE(varTmp);
627 end match;
628 then rvalue;
629 case DAE.ASUB(exp1, subscripts)
630 algorithm
631 ✗ expLst := list(Expression.getSubscriptExp(sub) for sub in subscripts);
632 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
633 varExp2 := match expLst
634 local
635 DAE.Exp indexexp;
636 ✗ case {indexexp} then RValueToVar(ExpToMid(indexexp, state), state);
637 end match;
638
639 ✗ varTmp := GenTmpVar(Types.complicateType(Expression.typeof(exp)),state);
640
641 ✗ labelNext := GenBlockId();
642
643 ✗ stateTerminate(labelNext,
644 MidCode.CALL(Absyn.IDENT("arrayGet"), true, {varExp, varExp2}, {MidCode.OUT_VAR(varTmp)}, labelNext),
645 state);
646 ✗ then MidCode.VARIABLE(varTmp);
647 case DAE.TSUB(exp1 as DAE.CALL(_,_,callattrs), 1, _)
648 algorithm
649 /* stupid special case */
650 (ty,numTailTypes) := match callattrs.ty
651 local
652 DAE.Type actualType;
653 list<DAE.Type> tailTypes;
654 ✗ case DAE.T_TUPLE(actualType::tailTypes) then (actualType, listLength(tailTypes));
655 else fail();
656 end match;
657
658 ✗ varTmp := GenTmpVar(Types.complicateType(ty),state);
659
660 outvars := {};
661 ✗ for i in 1:numTailTypes loop
662 outvars := MidCode.OUT_WILD() :: outvars;
663 end for;
664 ✗ outvars := MidCode.OUT_VAR(varTmp) :: outvars;
665 ✗ CallToMid(exp1, outvars, state);
666 ✗ then MidCode.VARIABLE(varTmp);
667 case DAE.TSUB(__)
668 algorithm
669 ✗ varExp := RValueToVar(ExpToMid(exp.exp, state), state);
670 ✗ then MidCode.METAFIELD(varExp, exp.ix, Types.complicateType(exp.ty));
671 case DAE.RSUB(__)
672 algorithm
673 ✗ varExp := RValueToVar(ExpToMid(exp.exp, state), state);
674 ✗ then MidCode.METAFIELD(varExp, exp.ix, Types.complicateType(exp.ty));
675 case DAE.CAST(_, exp1)
676 algorithm
677 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
678 ✗ then MidCode.UNARYOP(MidCode.MOVE(), varExp); //TODO: return type?
679 case DAE.LUNARY(_, exp1)
680 algorithm
681 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
682 ✗ then MidCode.UNARYOP(MidCode.NOT(), varExp);
683 case DAE.LBINARY(exp1, operator, exp2)
684 algorithm
685 ✗ labelElse := GenBlockId();
686 ✗ labelNext := GenBlockId();
687
688 ty := match operator
689 ✗ case DAE.AND(__) then operator.ty;
690 ✗ case DAE.OR(__) then operator.ty;
691 end match;
692 ✗ varTmp := GenTmpVar(ty,state);
693
694 terminator := match operator
695 ✗ case DAE.AND(_) then MidCode.BRANCH(varTmp, labelElse, labelNext);
696 ✗ case DAE.OR(_) then MidCode.BRANCH(varTmp, labelNext, labelElse);
697 end match;
698
699 ✗ stateAddStmt(MidCode.ASSIGN(varTmp, ExpToMid(exp1, state)), state);
700 ✗ stateTerminate(labelElse, terminator, state);
701
702 ✗ stateAddStmt(MidCode.ASSIGN(varTmp, ExpToMid(exp2, state)), state);
703 ✗ stateTerminate(labelNext, MidCode.GOTO(labelNext), state);
704
705 ✗ then MidCode.VARIABLE(varTmp);
706 case DAE.UNARY(operator,exp1)
707 algorithm
708 unop := match operator
709 case DAE.UMINUS(__) then MidCode.UMINUS();
710 end match;
711
712 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
713 ✗ then MidCode.UNARYOP(unop, varExp);
714 case DAE.BINARY(exp1, operator, exp2)
715 algorithm
716 binop := match operator
717 case DAE.ADD(__) then MidCode.ADD();
718 case DAE.SUB(__) then MidCode.SUB();
719 case DAE.MUL(__) then MidCode.MUL();
720 case DAE.DIV(__) then MidCode.DIV();
721 case DAE.POW(__) then MidCode.POW();
722 end match;
723
724 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
725 ✗ varExp2 := RValueToVar(ExpToMid(exp2, state), state);
726 ✗ then MidCode.BINARYOP(binop, varExp, varExp2);
727 case DAE.RELATION(exp1, operator, exp2, _, _)
728 algorithm
729 binop := match operator
730 case DAE.LESS(__) then MidCode.LESS();
731 case DAE.LESSEQ(__) then MidCode.LESSEQ();
732 case DAE.GREATER(__) then MidCode.GREATER();
733 case DAE.GREATEREQ(__) then MidCode.GREATEREQ();
734 case DAE.EQUAL(__) then MidCode.EQUAL();
735 case DAE.NEQUAL(__) then MidCode.NEQUAL();
736 end match;
737
738 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
739 ✗ varExp2 := RValueToVar(ExpToMid(exp2, state), state);
740 ✗ then MidCode.BINARYOP(binop, varExp, varExp2);
741 case DAE.IFEXP(exp1, exp2, exp3)
742 algorithm
743
744 ✗ labelBody := GenBlockId();
745 ✗ labelElse := GenBlockId();
746 ✗ labelNext := GenBlockId();
747
748 ✗ varExp := RValueToVar(ExpToMid(exp1, state), state);
749
750 ✗ varTmp := GenTmpVar(Types.complicateType(Expression.typeof(exp2)),state);
751
752 ✗ stateTerminate(labelBody, MidCode.BRANCH(varExp, labelBody, labelElse), state);
753
754 ✗ stateAddStmt(MidCode.ASSIGN(varTmp, ExpToMid(exp2, state)), state);
755 ✗ stateTerminate(labelElse, MidCode.GOTO(labelNext), state);
756
757 ✗ stateAddStmt(MidCode.ASSIGN(varTmp, ExpToMid(exp3, state)), state);
758 ✗ stateTerminate(labelNext, MidCode.GOTO(labelNext), state);
759 ✗ then MidCode.VARIABLE(varTmp);
760 case DAE.CALL(_, _, callattrs)
761 algorithm
762 ✗ varTmp := GenTmpVar(Types.complicateType(callattrs.ty),state);
763 ✗ CallToMid(exp, {MidCode.OUT_VAR(varTmp)}, state);
764 ✗ then MidCode.VARIABLE(varTmp);
765 case DAE.MATCHEXPRESSION(et=ty)
766 algorithm
767 ✗ varTmp := GenTmpVar(Types.complicateType(ty),state);
768 () := match Types.complicateType(ty)
769 case DAE.T_TUPLE(__)
770 algorithm
771 ✗ Error.addInternalError("Not supposed to get tuple here.\n", sourceInfo());
772 ✗ then fail();
773 else then ();
774 end match;
775 ✗ MatchExpressionToMid(exp,{MidCode.OUT_VAR(varTmp)},state);
776 ✗ then MidCode.VARIABLE(varTmp);
777 else
778 algorithm
779 ✗ Error.addInternalError("DAE.Exp to Mid conversion failed:\n" + ExpressionDump.dumpExpStr(exp,0) + "\n", sourceInfo());
780 ✗ then fail();
781 end match;
782 end ExpToMid;
783
784 function CallToMid
785 input DAE.Exp call;
786 input list<MidCode.OutVar> outvars;
787 input State state;
788 algorithm
789 //TODO: maybe handle isFunctionPointerCall/isImpure
790 () := match call
791 local
792 Absyn.Path path;
793 list<DAE.Exp> expLst;
794 DAE.CallAttributes callattr;
795 Integer labelNext;
796 DoubleEnded.MutableList<MidCode.Var> inputs;
797 MidCode.Var var1;
798 case DAE.CALL(path, expLst, callattr)
799 algorithm
800 ✗ labelNext := GenBlockId();
801
802 ✗ inputs := DoubleEnded.fromList({});
803 ✗ for exp1 in expLst loop
804 ✗ var1 := RValueToVar(ExpToMid(exp1, state), state);
805 ✗ DoubleEnded.push_back(inputs, var1);
806 end for;
807
808 ✗ stateTerminate(labelNext,
809 MidCode.CALL(path,callattr.builtin,DoubleEnded.toListAndClear(inputs),outvars,labelNext),
810 state);
811
812 then ();
813 end match;
814 end CallToMid;
815
816 function ForToMid
817 input DAE.Type type_;
818 input String iter;
819 input DAE.Exp range;
820 input list<DAE.Statement> daestmtLst;
821 input State state;
822 protected
823 MidCode.Var varCref;
824 MidCode.Var varCondition;
825 Integer labelCondition;
826 Integer labelStep;
827 Integer labelBody;
828 Integer labelNext;
829 algorithm
830 ✗ varCref := CrefToMidVar(DAE.CREF_IDENT(iter, type_, {}), state);
831 ✗ DoubleEnded.push_back(state.locals, varCref);
832
833 ✗ labelCondition := GenBlockId();
834 ✗ labelStep := GenBlockId();
835 ✗ labelBody := GenBlockId();
836 ✗ labelNext := GenBlockId();
837
838 ✗ Mutable.update(state.continuejumps, labelStep :: Mutable.access(state.continuejumps));
839 ✗ Mutable.update(state.breakjumps, labelNext :: Mutable.access(state.breakjumps));
840
841 ✗ varCondition := GenTmpVar(DAE.T_BOOL_DEFAULT,state);
842
843 () := match range
844 local
845 DAE.Exp start;
846 Option<DAE.Exp> step;
847 DAE.Exp stop;
848 MidCode.Var varRange;
849 MidCode.Var varFirst;
850 MidCode.Var varIter;
851 MidCode.Var varLast;
852 MidCode.Var varStep;
853 Integer labelBody2;
854 Integer labelCondition2;
855 MidCode.RValue rvalueStep;
856 case DAE.RANGE(_, start, step, stop)
857 algorithm
858 ✗ labelCondition2 := GenBlockId();
859
860 ✗ varFirst := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
861 ✗ varIter := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
862 ✗ varLast := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
863 ✗ varStep := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
864
865 ✗ stateAddStmt(MidCode.ASSIGN(varFirst, ExpToMid(start, state)), state);
866 ✗ stateAddStmt(MidCode.ASSIGN(varIter, ExpToMid(start, state)), state);
867 ✗ stateAddStmt(MidCode.ASSIGN(varLast, ExpToMid(stop, state)), state);
868
869 rvalueStep := match step
870 local
871 DAE.Exp stepexp;
872 case NONE() then MidCode.LITERALINTEGER(1);
873 ✗ case SOME(stepexp) then ExpToMid(stepexp, state);
874 end match;
875
876 ✗ stateAddStmt(MidCode.ASSIGN(varStep, rvalueStep), state);
877 ✗ stateTerminate(labelCondition, MidCode.GOTO(labelCondition), state);
878
879 ✗ stateTerminate(labelCondition2,
880 MidCode.CALL(Absyn.IDENT("in_range_integer"), true, {varIter, varFirst, varLast}, {MidCode.OUT_VAR(varCondition)}, labelCondition2),
881 state);
882
883 ✗ stateTerminate(labelBody, MidCode.BRANCH(varCondition, labelBody, labelNext), state);
884
885 ✗ stateAddStmt(MidCode.ASSIGN(varCref, MidCode.VARIABLE(varIter)), state);
886 ✗ StmtsToMid(daestmtLst, state);
887 ✗ stateTerminate(labelStep, MidCode.GOTO(labelStep), state);
888
889 ✗ stateAddStmt(MidCode.ASSIGN(varIter, MidCode.BINARYOP(MidCode.ADD(), varIter, varStep)), state);
890 ✗ stateTerminate(labelNext, MidCode.GOTO(labelCondition), state);
891 then ();
892 else
893 algorithm
894 ✗ varRange := RValueToVar(ExpToMid(range, state), state);
895 () := match varRange.ty
896 case DAE.T_METATYPE(_)
897 algorithm
898 ✗ Error.addInternalError("metatype error", sourceInfo());
899 ✗ then fail();
900 case DAE.T_METAARRAY(_)
901 algorithm
902 ✗ labelBody2 := GenBlockId();
903
904 ✗ varIter := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
905 ✗ varLast := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
906 ✗ varStep := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
907
908 ✗ stateAddStmt(MidCode.ASSIGN(varIter, MidCode.LITERALINTEGER(1)), state);
909 ✗ stateAddStmt(MidCode.ASSIGN(varStep, MidCode.LITERALINTEGER(1)), state);
910 ✗ stateTerminate(labelCondition,
911 MidCode.CALL(Absyn.IDENT("arrayLength"), true, {varRange}, {MidCode.OUT_VAR(varLast)}, labelCondition),
912 state);
913
914 ✗ stateAddStmt(MidCode.ASSIGN(varCondition, MidCode.BINARYOP(MidCode.LESSEQ(), varIter, varLast)), state);
915 ✗ stateTerminate(labelBody, MidCode.BRANCH(varCondition, labelBody, labelNext), state);
916
917 ✗ stateTerminate(labelBody2,
918 MidCode.CALL(Absyn.IDENT("arrayGet"), true, {varRange, varIter}, {MidCode.OUT_VAR(varCref)}, labelBody2),
919 state);
920
921 ✗ StmtsToMid(daestmtLst, state);
922 ✗ stateTerminate(labelStep, MidCode.GOTO(labelStep), state);
923
924 ✗ stateAddStmt(MidCode.ASSIGN(varIter, MidCode.BINARYOP(MidCode.ADD(), varIter, varStep)), state);
925 ✗ stateTerminate(labelNext, MidCode.GOTO(labelCondition), state);
926 then ();
927 case DAE.T_METALIST(_)
928 algorithm
929 ✗ labelBody2 := GenBlockId();
930
931 varIter := varRange;
932 ✗ stateTerminate(labelCondition, MidCode.GOTO(labelCondition), state);
933
934 ✗ stateAddStmt(MidCode.ASSIGN(varCondition, MidCode.ISCONS(varIter)), state);
935 ✗ stateTerminate(labelBody, MidCode.BRANCH(varCondition, labelBody, labelNext), state);
936
937 ✗ stateTerminate(labelBody2,
938 MidCode.CALL(Absyn.IDENT("listHead"), true, {varIter}, {MidCode.OUT_VAR(varCref)}, labelBody2),
939 state);
940
941 ✗ StmtsToMid(daestmtLst, state);
942 ✗ stateTerminate(labelStep, MidCode.GOTO(labelStep), state);
943
944 ✗ stateTerminate(labelNext,
945 MidCode.CALL(Absyn.IDENT("listRest"), true, {varIter}, {MidCode.OUT_VAR(varIter)}, labelCondition),
946 state);
947 then ();
948 else
949 algorithm
950 ✗ Error.addInternalError("unknown for type " + DAEDump.daeTypeStr(varRange.ty) + "\n", sourceInfo());
951 ✗ then fail();
952 end match;
953 then ();
954 end match;
955
956 ✗ Mutable.update(state.continuejumps, listRest(Mutable.access(state.continuejumps)));
957 ✗ Mutable.update(state.breakjumps, listRest(Mutable.access(state.breakjumps)));
958 end ForToMid;
959
960 function IfToMid
961 input DAE.Exp exp;
962 input list<DAE.Statement> daestmtLst;
963 input DAE.Else else_;
964 input State state;
965 protected
966 Integer labelBody;
967 Integer labelElse;
968 Integer labelNext;
969 MidCode.Var var1;
970 algorithm
971 ✗ labelBody := GenBlockId();
972 ✗ labelElse := GenBlockId();
973 ✗ labelNext := GenBlockId();
974
975 ✗ var1 := RValueToVar(ExpToMid(exp, state), state);
976
977 ✗ stateTerminate(labelBody, MidCode.BRANCH(var1, labelBody, labelElse), state);
978
979 ✗ StmtsToMid(daestmtLst, state);
980 ✗ stateTerminate(labelElse, MidCode.GOTO(labelNext), state);
981
982 () := match else_
983 local
984 DAE.Exp subexp;
985 list<DAE.Statement> subdaestmtLst;
986 DAE.Else subelse;
987 case DAE.NOELSE() then ();
988 case DAE.ELSEIF(subexp, subdaestmtLst, subelse)
989 algorithm
990 ✗ IfToMid(subexp, subdaestmtLst, subelse, state);
991 then ();
992 case DAE.ELSE(subdaestmtLst)
993 algorithm
994 ✗ StmtsToMid(subdaestmtLst, state);
995 then ();
996 end match;
997
998 ✗ stateTerminate(labelNext, MidCode.GOTO(labelNext), state);
999 end IfToMid;
1000
1001
1002 function stateGetCurrentLabel
1003 input State state;
1004 output Integer label;
1005 algorithm
1006 ✗ label := Mutable.access(state.blockid);
1007 end stateGetCurrentLabel;
1008
1009 function stateSetCurrentLabel
1010 input Integer label;
1011 input State state;
1012 algorithm
1013 ✗ Mutable.update(state.blockid, label);
1014 end stateSetCurrentLabel;
1015
1016 function stateAddStmt
1017 input MidCode.Stmt stmt;
1018 input State state;
1019 algorithm
1020 ✗ DoubleEnded.push_back(state.stmts, stmt);
1021 end stateAddStmt;
1022
1023 function stateTerminate
1024 input Integer newLabel;
1025 input MidCode.Terminator terminator;
1026 input State state;
1027 protected
1028 MidCode.Block block_;
1029 algorithm
1030 ✗ block_ := MidCode.BLOCK(stateGetCurrentLabel(state),
1031 DoubleEnded.toListAndClear(state.stmts),
1032 terminator);
1033 ✗ DoubleEnded.push_back(state.blocks, block_);
1034
1035 ✗ stateSetCurrentLabel(newLabel, state);
1036 end stateTerminate;
1037
1038 // helper
1039 function stateAddBailOnFalse
1040 input MidCode.Var var;
1041 input Integer labelBail;
1042 input State state;
1043 protected
1044 Integer labelTmp;
1045 algorithm
1046 ✗ labelTmp := GenBlockId();
1047 ✗ stateTerminate(labelTmp,MidCode.BRANCH(var,onFalse=labelBail,onTrue=labelTmp), state);
1048 end stateAddBailOnFalse;
1049
1050 function unpackCrefFromExp
1051 input DAE.Exp exp;
1052 output DAE.ComponentRef cref;
1053 algorithm
1054 cref := match exp
1055 case DAE.CREF(cref)
1056 then cref;
1057 end match;
1058 end unpackCrefFromExp;
1059
1060
1061 //TODO: stuff needs to be volatile for setjmp.
1062 //TODO: could handle match separately from matchcontinue and add more simplifications
1063 /*
1064 The term matchexpression is used to include both matchcontinue and match.
1065 */
1066 function MatchExpressionToMid
1067 input DAE.Exp matchexpression;
1068 input list<MidCode.OutVar> outvars;
1069 input State state;
1070 protected
1071 Integer labelFin, labelMux, labelInit, labelFail, labelFin2, labelOut, caseLabel;
1072 list<Integer> caseLabels;
1073 MidCode.Var muxState, one, midvar,midvar2;
1074 MidCode.VarBufPtr muxOldBuf = MidCode.VARBUFPTR("");
1075 MidCode.VarBuf muxNewBuf;
1076 MidCode.OutVar outvar;
1077 Boolean matchContinue;
1078 DAE.MatchType matchType;
1079 list<DAE.MatchCase> cases;
1080 list<DAE.Exp> inputsCref;
1081 list<list<String>> aliases; // list of (list of alias) where each outer list corresponds to a input
1082 MidCode.Var srcVar, aliasVar;
1083 list<String> aliasList;
1084 DAE.Type ty;
1085 list<MidCode.Var> inputsMidVar;
1086 DAE.Exp daeExp;
1087 list<Integer> caseLabelIterator;
1088 algorithm
1089 /*
1090 I assume the Else case is a case with top level wild patterns (_,_,_).
1091 */
1092
1093 // match just to get match elements
1094 () := match matchexpression
1095 case DAE.MATCHEXPRESSION(matchType=matchType, cases=cases, inputs=inputsCref, aliases=aliases)
1096 algorithm
1097 ✗ labelInit := stateGetCurrentLabel(state);
1098 ✗ labelMux := GenBlockId();
1099 ✗ labelFin := GenBlockId();
1100
1101 matchContinue := match matchType
1102 case DAE.MATCHCONTINUE() then true;
1103 case DAE.MATCH() then false;
1104 end match;
1105
1106 // caseLabels <- sequence $ repeat (length cases) genBlockId
1107 // can write with list comprehension if I can make a range
1108 caseLabels := {};
1109 ✗ for i in 1:listLength(cases) loop
1110 ✗ caseLabels := GenBlockId() :: caseLabels;
1111 end for;
1112
1113 /*
1114 First we evaluate all inputs to the matchcontinue.
1115 We must also bind the aliases that were sent.
1116 If an input does not have an alias we must create a MidCode.Var for it to use.
1117
1118 zip inputs aliases : [(input,[alias])]
1119 where
1120 length inputs = length aliases
1121
1122 */
1123
1124 ✗ assert( listLength(inputsCref) == listLength(aliases), "MatchExpressionToMid: incorrect input: listLength(inputs) != listLength(aliases)" );
1125 inputsMidVar := {};
1126 ✗ for daeExp_aliasList in List.zip(inputsCref,aliases) loop
1127
1128 ✗ (daeExp,aliasList) := daeExp_aliasList;
1129 ✗ srcVar := RValueToVar(ExpToMid(daeExp, state), state);
1130 ✗ ty := RValueType(MidCode.VARIABLE(srcVar));
1131 inputsMidVar := srcVar :: inputsMidVar;
1132 ✗ for alias in aliasList loop
1133 ✗ aliasVar := MidCode.VAR(name=alias, ty=ty, volatile=false);
1134 ✗ DoubleEnded.push_back(state.locals, aliasVar);
1135 ✗ stateAddStmt( MidCode.ASSIGN(aliasVar, MidCode.VARIABLE(srcVar) ), state );
1136 end for;
1137 end for;
1138
1139 // inputsMidVar := list(CrefToMidVar(unpackCrefFromExp(expCref),state) for expCref in inputsCref);
1140
1141 /*
1142 init:
1143 state = 0
1144 #IF MATCHCONTINUE
1145 PUSHJMP(J_old,J_new)
1146 goto mux
1147 */
1148
1149 ✗ muxState := GenTmpVarVolatile(DAE.T_INTEGER_DEFAULT,state); // volatile since we mutate it after setjmp
1150 ✗ stateAddStmt(MidCode.ASSIGN(muxState, MidCode.LITERALINTEGER(0)), state);
1151
1152 ✗ if matchContinue
1153 then
1154 ✗ muxOldBuf := GenTmpVarBufPtr(state);
1155 ✗ muxNewBuf := GenTmpVarBuf(state);
1156 ✗ stateTerminate(labelMux, MidCode.PUSHJMP(muxOldBuf,muxNewBuf,labelMux),state);
1157 else
1158 ✗ stateTerminate(labelMux, MidCode.GOTO(labelMux),state);
1159 end if;
1160
1161 /*
1162 mux:
1163 #IF MATCHCONTINUE
1164 state+=1
1165 switch (state) {1:case1, 2:case2, ...,n:case_n,n+1:fin}
1166 #IF MATCH
1167 goto first case or fail if no case
1168 */
1169 ✗ if matchContinue
1170 then
1171 ✗ one := GenTmpVar(DAE.T_INTEGER_DEFAULT,state);
1172 ✗ stateAddStmt(MidCode.ASSIGN(one, MidCode.LITERALINTEGER(1)) ,state);
1173 ✗ stateAddStmt(MidCode.ASSIGN(muxState, MidCode.BINARYOP(MidCode.ADD(),muxState,one)),state);
1174 ✗ stateTerminate(labelFin, MidCode.SWITCH( muxState, List.zip( List.intRange(listLength(cases)+1), listAppend(caseLabels,{labelFin}) ) ), state);
1175 else
1176 ✗ stateTerminate(labelFin, MidCode.GOTO(if not listEmpty(caseLabels) then listHead(caseLabels) else labelFin), state);
1177 end if;
1178 /*
1179 fin:
1180 #IF MATCHCONTINUE
1181 POPJMP(J_old)
1182 if state == nr_cases+1
1183 longjmp
1184 else
1185 goto next
1186 */
1187
1188 /*
1189 We make the label for the next thing we generate after the match expression.
1190 We replace this in the case loop as we add more cases.
1191 */
1192 ✗ labelFail := GenBlockId();
1193 ✗ labelFin2 := GenBlockId();
1194 ✗ labelOut := GenBlockId();
1195
1196 ✗ if matchContinue
1197 then
1198 ✗ stateTerminate(labelFin2, MidCode.POPJMP( muxOldBuf, labelFin2 ), state);
1199 else
1200 ✗ stateTerminate(labelFin2, MidCode.GOTO(labelFin2), state);
1201 end if;
1202
1203 ✗ midvar := RValueToVar(MidCode.LITERALINTEGER(listLength(cases)+1),state);
1204 ✗ midvar2 := RValueToVar(MidCode.BINARYOP(MidCode.EQUAL(),muxState, midvar),state);
1205 ✗ stateTerminate(labelFail, MidCode.BRANCH(midvar2, labelFail, labelOut),state);
1206
1207 ✗ stateTerminate(labelOut, MidCode.LONGJMP(),state);
1208
1209 caseLabelIterator := caseLabels;
1210
1211 // for each case
1212 ✗ while not listEmpty(caseLabelIterator) loop
1213 ✗ caseLabel := listHead(caseLabelIterator);
1214 ✗ caseLabelIterator := listRest(caseLabelIterator);
1215 ✗ stateSetCurrentLabel(caseLabel, state);
1216 // left to right - depth first - through all patterns in the case
1217 () := match cases
1218 local
1219 list<DAE.Pattern> patterns;
1220 list<DAE.Statement> daeBody;
1221 Option<DAE.Exp> patternGuard;
1222 Option<DAE.Exp> caseResult;
1223 case {}
1224 algorithm
1225 // No more cases.
1226 then ();
1227 case DAE.CASE(patterns=patterns,body=daeBody,patternGuard=patternGuard,result=caseResult)::cases // note: modifies cases
1228 algorithm
1229 // first do checks and assignments
1230 // NOTE: If the guard fails we will have made pattern assignments for a failing case. This is how it was done before as far as I can tell.
1231 ✗ if matchContinue
1232 then
1233 ✗ patternToMidCode(state=state, matches=List.zip(inputsMidVar,patterns), labelNoMatch=labelMux);
1234 else
1235 ✗ patternToMidCode(state=state, matches=List.zip(inputsMidVar,patterns)
1236 ,labelNoMatch= if not listEmpty(caseLabelIterator) then listHead(caseLabelIterator) else labelFail);
1237 end if;
1238 // then guard
1239 () := match patternGuard
1240 case NONE()
1241 algorithm
1242 // No guard.
1243 then ();
1244 case SOME(daeExp)
1245 algorithm
1246 ✗ midvar := RValueToVar(ExpToMid(daeExp,state),state);
1247 ✗ if matchContinue
1248 then
1249 ✗ stateAddBailOnFalse(midvar,labelMux,state);
1250 else
1251 ✗ stateAddBailOnFalse(midvar,
1252 if not listEmpty(caseLabelIterator) then listHead(caseLabelIterator) else labelFail,
1253 state);
1254 end if;
1255 then ();
1256 end match;
1257 // followed by body
1258 ✗ StmtsToMid(daeBody,state);
1259 /*
1260 instead of caseResult being a list of exps there are 3 cases.
1261 - No result.
1262 NONE()
1263
1264 - One result.
1265 SOME(result)
1266
1267 - More results.
1268 SOME(TUPLE(result0,result1,...))
1269
1270 Also outvars is unexpectedly removed of trailing wildcards and can be shorter than expList,
1271 including tuples of length 1 (probably 0 too, but who knows).
1272 So we define and use listZip instead of List.zip.
1273
1274 TODO: Document the unintuitive undocumented interface somewhere.
1275 */
1276 () := match (caseResult, outvars)
1277 local
1278 list<DAE.Exp> expList;
1279 case (SOME(DAE.TUPLE(expList)),_)
1280 algorithm
1281 ✗ for outvarDaeExp in listZip(outvars, expList) loop
1282 ✗ (outvar, daeExp) := outvarDaeExp;
1283 () := match outvar
1284 local
1285 MidCode.Var var;
1286 case MidCode.OUT_VAR(var)
1287 algorithm
1288 ✗ stateAddStmt(MidCode.ASSIGN(var, ExpToMid(daeExp,state)),state);
1289 then ();
1290 case MidCode.OUT_WILD() then ();
1291 end match;
1292
1293 end for;
1294
1295 then ();
1296 case (SOME(daeExp as DAE.CALL(__)), _)
1297 algorithm
1298 ✗ CallToMid(daeExp, outvars, state);
1299 then ();
1300 case (SOME(daeExp as DAE.MATCHEXPRESSION(__)), _)
1301 algorithm
1302 ✗ MatchExpressionToMid(daeExp, outvars, state);
1303 then ();
1304 case (SOME(daeExp), {MidCode.OUT_VAR(midvar)})
1305 algorithm
1306 ✗ stateAddStmt(MidCode.ASSIGN(midvar, ExpToMid(daeExp,state)),state);
1307 then ();
1308 case (SOME(daeExp), _)
1309 algorithm
1310 ✗ Error.addInternalError("Match expression output to Mid conversion failed:\n" + ExpressionDump.dumpExpStr(daeExp,0) + "\n", sourceInfo());
1311 then ();
1312 case (NONE(), {})
1313 algorithm
1314 // No result.
1315 then ();
1316 case (NONE(), _)
1317 algorithm
1318 ✗ Error.addInternalError("case fail", sourceInfo());
1319 ✗ then fail();
1320 end match;
1321 // finally go to end
1322 ✗ stateTerminate(labelOut, MidCode.GOTO(labelFin),state);
1323 then ();
1324 end match;
1325 end while;
1326 then ();
1327 end match;
1328 end MatchExpressionToMid;
1329
1330 function patternToMidCode
1331 "
1332 Performs pattern matching.
1333
1334 The state will be left so that if the
1335 matching was successful then we
1336 continue in the active block. And
1337 variables in pattern will be bound.
1338 But failures will have jumped to
1339 labelNoMatch. And nothing will be bound.
1340
1341 For example in a match a failure means handling
1342 the next case. Except for the last case where
1343 failure is a longjmp.
1344 "
1345 input list<tuple<MidCode.Var,DAE.Pattern>> matches "List of variables and their corresponding patterns";
1346 input Integer labelNoMatch "where to go on a failed match";
1347 input State state;
1348 output array<list<MidCode.Stmt>> assignBlock "A block of assignments to perform for a pattern.";
1349 algorithm
1350 ✗ assignBlock := arrayCreate(1,{});
1351
1352 ✗ patternToMidCode2(state=state,matches=matches,labelNoMatch=labelNoMatch,assignBlock=assignBlock);
1353
1354 ✗ for stmt in listReverse(arrayGet(assignBlock,1)) loop
1355 ✗ stateAddStmt(stmt,state);
1356 end for;
1357 end patternToMidCode;
1358
1359 function patternToMidCode2
1360 "
1361 Recursive worker function for
1362 patternToMidCode handling.
1363 "
1364 input State state;
1365 input list<tuple<MidCode.Var,DAE.Pattern>> matches;
1366 input Integer labelNoMatch; /* where to go on a failed match*/
1367 input array<list<MidCode.Stmt>> assignBlock; /* A block of assignments to perform for a pattern. */
1368 protected
1369 Integer index;
1370 list<DAE.Pattern> morePatterns, iterator;
1371 list<DAE.Var> fields;
1372 Boolean knownSingleton;
1373 Integer fieldNr;
1374 algorithm
1375 /*
1376 case0:
1377 check some pattern
1378 if not match then goto mux (e.g. METACONSTRUCTOR)
1379 extract scrutinees for sub-patterns (e.g. METAFIELD)
1380 note down if there is a binding to be done later (assignBlock)
1381 check another part of pattern
1382 ...
1383 if not guard expression
1384 goto mux
1385 else goto body0
1386
1387 guard and body is handled in the caller, not here
1388
1389 */
1390
1391 () := match matches
1392 local
1393 list<tuple<MidCode.Var,DAE.Pattern>> restMatches, moreMatches;
1394 list<DAE.Type> listTypes;
1395 MidCode.Var ok; /* Just a MidCode boolean variable */
1396 MidCode.Var scrutinee, midvar, headVar, restVar;
1397 String id;
1398 DAE.Pattern pattern, headPattern, restPattern;
1399 DAE.Exp exp;
1400 DAE.Type ty;
1401 MidCode.Var scrutineeCompareVar;
1402 MidCode.Var patCompareVar;
1403 Option<DAE.Type> optType;
1404
1405 Boolean bool;
1406 Integer integer;
1407 Real real;
1408 String string;
1409
1410 case {}
1411 algorithm
1412 // All patterns have been matched. Fall through to what happens on succesful match.
1413 then ();
1414
1415 case (_,DAE.PAT_WILD()) :: restMatches
1416 algorithm
1417 ✗ patternToMidCode2(matches = restMatches, state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1418 then ();
1419
1420 case (scrutinee,DAE.PAT_AS(id=id,ty=NONE(),pat=pattern)) :: restMatches
1421 algorithm
1422 ✗ ty := RValueType(MidCode.VARIABLE(scrutinee));
1423 ✗ midvar := MidCode.VAR(id, ty, false);
1424 ✗ arrayUpdate(assignBlock, 1, MidCode.ASSIGN(midvar, MidCode.VARIABLE(scrutinee))::arrayGet(assignBlock,1));
1425 ✗ patternToMidCode2(matches = (scrutinee, pattern) :: restMatches, state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1426 then ();
1427
1428 case (scrutinee,DAE.PAT_AS(id=id,ty=SOME(ty),pat=pattern)) :: restMatches
1429 algorithm
1430 // ty=SOME(_) means that the contained value needs unboxing
1431 ✗ midvar := MidCode.VAR(id, ty, false);
1432 ✗ arrayUpdate(assignBlock, 1, MidCode.ASSIGN(midvar, MidCode.UNARYOP(MidCode.UNBOX(),scrutinee))::arrayGet(assignBlock,1));
1433 ✗ patternToMidCode2(matches = (scrutinee, pattern) :: restMatches, state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1434 then ();
1435
1436 case (scrutinee,DAE.PAT_CONSTANT(ty=optType,exp=exp)) :: restMatches // TODO: what to do about optType
1437 algorithm
1438 //remove shared literal
1439 exp := match exp
1440 case DAE.SHARED_LITERAL(exp=exp) then exp;
1441 else then exp;
1442 end match;
1443
1444 //unbox
1445 scrutinee := match optType
1446 case NONE() then scrutinee;
1447 ✗ case SOME(_) then RValueToVar(MidCode.UNARYOP(MidCode.UNBOX(),scrutinee),state);
1448 end match;
1449
1450 // test
1451 () := match exp
1452 case DAE.BCONST(bool=bool)
1453 algorithm
1454 scrutineeCompareVar := scrutinee;
1455 ✗ patCompareVar := RValueToVar(MidCode.LITERALBOOLEAN(bool), state);
1456 then ();
1457 case DAE.ICONST(integer=integer)
1458 algorithm
1459 scrutineeCompareVar := scrutinee;
1460 ✗ patCompareVar := RValueToVar(MidCode.LITERALINTEGER(integer), state);
1461 then ();
1462 case DAE.RCONST(real=real)
1463 algorithm
1464 scrutineeCompareVar := scrutinee;
1465 ✗ patCompareVar := RValueToVar(MidCode.LITERALREAL(real), state);
1466 then ();
1467 case DAE.ENUM_LITERAL(index=integer)
1468 algorithm
1469 scrutineeCompareVar := scrutinee;
1470 ✗ patCompareVar := RValueToVar(MidCode.LITERALINTEGER(integer), state);
1471 then ();
1472 case DAE.LIST(valList = {})
1473 algorithm
1474 ✗ scrutineeCompareVar := RValueToVar(MidCode.ISCONS(scrutinee), state);
1475 ✗ patCompareVar := RValueToVar(MidCode.LITERALBOOLEAN(false), state);
1476 then ();
1477 case DAE.META_OPTION(exp = NONE())
1478 algorithm
1479 ✗ scrutineeCompareVar := RValueToVar(MidCode.ISSOME(scrutinee), state);
1480 ✗ patCompareVar := RValueToVar(MidCode.LITERALBOOLEAN(false), state);
1481 then ();
1482 case DAE.SCONST(string=string)
1483 algorithm
1484 scrutineeCompareVar := scrutinee;
1485 ✗ patCompareVar := RValueToVar(MidCode.LITERALSTRING(string), state);
1486 then ();
1487 else
1488 algorithm
1489 ✗ Error.addInternalError("DAE.Exp to Mid conversion failed for pattern constant. Exp:" + ExpressionDump.dumpExpStr(exp,0) + ".\n", sourceInfo());
1490 ✗ then fail();
1491 end match;
1492
1493 // generic part of test
1494 ✗ ok := GenTmpVar(DAE.T_BOOL_DEFAULT,state);
1495
1496 ✗ stateAddStmt(MidCode.ASSIGN(ok, MidCode.BINARYOP(MidCode.EQUAL(), scrutineeCompareVar, patCompareVar )), state);
1497 ✗ stateAddBailOnFalse(ok, labelNoMatch, state);
1498 ✗ patternToMidCode2(matches = restMatches, state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1499 then ();
1500
1501 case (scrutinee,DAE.PAT_META_TUPLE(morePatterns)) :: restMatches
1502 algorithm
1503 listTypes := match scrutinee.ty
1504 case DAE.T_METATUPLE(listTypes) then listTypes;
1505 ✗ else algorithm Error.addInternalError("Wrong type of midvar in tuple pattern: " + DAEDump.daeTypeStr(scrutinee.ty) + ".\n", sourceInfo()); then fail();
1506 end match;
1507
1508 moreMatches := {};
1509 iterator := morePatterns;
1510 fieldNr := 0;
1511 ✗ while not listEmpty(iterator) loop
1512 ✗ midvar := RValueToVar(MidCode.METAFIELD(scrutinee,fieldNr,listHead(listTypes)),state);
1513 ✗ moreMatches := (midvar, listHead(iterator)) :: moreMatches;
1514 ✗ fieldNr := fieldNr + 1;
1515 ✗ iterator := listRest(iterator);
1516 ✗ listTypes := listRest(listTypes);
1517 end while;
1518 ✗ moreMatches := listReverse(moreMatches);
1519 ✗ patternToMidCode2(matches = listAppend(moreMatches, restMatches), state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1520 then ();
1521
1522 case (scrutinee,DAE.PAT_SOME(pattern)) :: restMatches
1523 algorithm
1524 ✗ ok := GenTmpVar(DAE.T_BOOL_DEFAULT,state);
1525 ✗ scrutineeCompareVar := RValueToVar(MidCode.ISSOME(scrutinee), state);
1526 ✗ patCompareVar := RValueToVar(MidCode.LITERALBOOLEAN(true), state);
1527 ✗ stateAddStmt(MidCode.ASSIGN(ok, MidCode.BINARYOP(MidCode.EQUAL(),scrutineeCompareVar, patCompareVar )), state);
1528 ✗ stateAddBailOnFalse(ok, labelNoMatch, state);
1529
1530 ty := match scrutinee.ty
1531 case DAE.T_METAOPTION(ty=ty)
1532 then ty;
1533 ✗ else algorithm Error.addInternalError("Wrong type of midvar in option pattern.\n", sourceInfo()); then fail();
1534 end match;
1535
1536 ✗ midvar := RValueToVar(MidCode.METAFIELD(scrutinee,0,ty),state);
1537 ✗ patternToMidCode2(
1538 matches = (midvar,pattern)::restMatches,
1539 state=state,
1540 assignBlock=assignBlock,
1541 labelNoMatch=labelNoMatch
1542 );
1543 then ();
1544
1545 case (scrutinee,DAE.PAT_CONS(head=headPattern,tail=restPattern)) :: restMatches
1546 algorithm
1547 ✗ scrutineeCompareVar := RValueToVar(MidCode.ISCONS(scrutinee), state);
1548 ✗ patCompareVar := RValueToVar(MidCode.LITERALBOOLEAN(true), state);
1549 ✗ ok := GenTmpVar(DAE.T_BOOL_DEFAULT,state);
1550 ✗ stateAddStmt(MidCode.ASSIGN(ok, MidCode.BINARYOP(MidCode.EQUAL(),scrutineeCompareVar, patCompareVar )), state);
1551 ✗ stateAddBailOnFalse(ok, labelNoMatch, state);
1552
1553 ty := match scrutinee.ty
1554 case DAE.T_METALIST(ty=DAE.T_UNKNOWN())
1555 ✗ algorithm Error.addInternalError("Found list of unknown in cons pattern: " + DAEDump.daeTypeStr(scrutinee.ty) +".\n", sourceInfo()); then fail();
1556 case DAE.T_METALIST(ty=ty)
1557 then ty;
1558 ✗ else algorithm Error.addInternalError("Wrong type of midvar in option pattern.\n", sourceInfo()); then fail();
1559 end match;
1560
1561 ✗ headVar := RValueToVar(MidCode.METAFIELD(scrutinee,0,ty),state);
1562 ✗ restVar := RValueToVar(MidCode.METAFIELD(scrutinee,1,scrutinee.ty),state);
1563
1564 ✗ patternToMidCode2(
1565 matches=(headVar,headPattern)::(restVar,restPattern)::restMatches,
1566 state=state,
1567 assignBlock=assignBlock,
1568 labelNoMatch=labelNoMatch
1569 );
1570
1571 then ();
1572
1573 case (scrutinee,DAE.PAT_CALL(_,index,morePatterns,fields,_,knownSingleton)) :: restMatches
1574 algorithm
1575 // TODO: Is this correct usage of knownSingleton?
1576
1577 ✗ if not knownSingleton
1578 then
1579 ✗ ok := GenTmpVar(DAE.T_BOOL_DEFAULT,state);
1580 ✗ scrutineeCompareVar := RValueToVar(MidCode.UNIONTYPEVARIANT(scrutinee) , state);
1581 ✗ patCompareVar := RValueToVar(MidCode.LITERALINTEGER(index) , state);
1582 ✗ stateAddStmt(MidCode.ASSIGN(ok, MidCode.BINARYOP(MidCode.EQUAL(),scrutineeCompareVar, patCompareVar )), state);
1583 ✗ stateAddBailOnFalse(ok, labelNoMatch, state);
1584 end if;
1585
1586 ✗ listTypes := list(v.ty for v in fields);
1587
1588 moreMatches := {};
1589 iterator := morePatterns;
1590 fieldNr := 1;
1591 ✗ while not listEmpty(iterator) loop
1592 ✗ midvar := RValueToVar(MidCode.METAFIELD(scrutinee,fieldNr,listHead(listTypes)),state);
1593 ✗ moreMatches := (midvar, listHead(iterator)) :: moreMatches;
1594 ✗ fieldNr := fieldNr + 1;
1595 ✗ iterator := listRest(iterator);
1596 ✗ listTypes := listRest(listTypes);
1597 end while;
1598 ✗ moreMatches := listReverse(moreMatches);
1599
1600 ✗ patternToMidCode2(matches = listAppend(moreMatches, restMatches), state=state, assignBlock=assignBlock, labelNoMatch=labelNoMatch);
1601 then ();
1602
1603 case (_,DAE.PAT_AS_FUNC_PTR())::_
1604 algorithm
1605 ✗ Error.addInternalError("DAE.Pattern to Mid conversion failed. Unimplemented pattern: PAT_AS_FUNC_PTR.\n", sourceInfo());
1606 ✗ then fail();
1607 case (_,DAE.PAT_CALL_TUPLE())::_
1608 algorithm
1609 ✗ Error.addInternalError("DAE.Pattern to Mid conversion failed. Unimplemented pattern: PAT_CALL_TUPLE.\n", sourceInfo());
1610 ✗ then fail();
1611 case (_,DAE.PAT_CALL_NAMED())::_
1612 algorithm
1613 ✗ Error.addInternalError("DAE.Pattern to Mid conversion failed. Unimplemented pattern: PAT_CALL_NAMED.\n", sourceInfo());
1614 ✗ then fail();
1615 else
1616 algorithm
1617 ✗ Error.addInternalError("DAE.Pattern to Mid conversion failed\n", sourceInfo());
1618 ✗ then fail();
1619 end match;
1620 end patternToMidCode2;
1621
1622 annotation(__OpenModelica_Interface="backend_tools");
1623
1624 end DAEToMid;
1625