source: branches/dev-1247-jw/Compiler/ModelicaCBackEnd/src/jastadd/CCodeGen/CCodeGenExpressions.jrag @ 13653

Last change on this file since 13653 was 13653, checked in by jwedin, 2 months ago

Refactored the code generation for delay expressions. #5852

File size: 61.2 KB
Line 
1/*
2Copyright (C) 2016-2018 Modelon AB
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, version 3 of the License.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program.  If not, see <http://www.gnu.org/licenses/>.
15*/
16
17import java.util.Arrays;
18import org.jmodelica.common.ccodegen.CFuncParamDirection;
19
20aspect CCodeGenExpressions {
21    /*=========================================================================
22     * Simple Expressions
23     * Those that don't need special treatment (no extra helpers etc)
24     * For each class the method should be order Class.genVarDecls_C(),
25     * Class.genTempVars_C(), Class.prettyPrint_C() and finaly
26     * Class.genTempFree_C().
27     =========================================================================*/
28
29    @Override
30    public void FNoExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
31        str.print("NULL");
32    }
33
34    @Override
35    public void FAbsExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
36        str.print("jmi_abs(");
37        p.print(getFExp(), str, indent);
38        str.print(")");
39    }
40
41    @Override
42    public void FAssert.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
43        p.printVarDecls(getTest(), str, indent);
44    }
45   
46    @Override
47    public void FInitArrayStmt.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
48        if (getShallow()) {
49            p.printVarDecls(getSizes(), str, indent);
50        } else {
51            p.printVarDecls(type(), str, indent);
52        }
53    }
54
55    @Override
56    public void FAssert.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
57        p.printPreSteps(getTest(), str, indent);
58                prettyPrint_C(p, str, indent);
59        p.printPostSteps(getTest(), str, indent);
60    }
61
62    @Override
63    public void FAssert.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
64        str.print(indent);
65        str.print("if (");
66        p.print(getTest(), str, indent);
67        str.print(" == JMI_FALSE) {\n");
68        p.printVarDecls(getMsg(), str, p.indent(indent));
69        p.printPreSteps(getMsg(), str, p.indent(indent));
70        str.print(p.indent(indent));
71        str.print("jmi_assert_failed(");
72        p.print(getMsg(), str, indent);
73        boolean warning = hasLevel() && getLevel().ceval().intValue() == 2;
74        str.format(", JMI_ASSERT_%s);\n", warning ? "WARNING" : "ERROR");
75        p.printPostSteps(getMsg(), str, p.indent(indent));
76        str.print(indent);
77        str.print("}\n");
78    }
79
80    @Override
81    public void FAssert.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
82        p.printPostSteps(getTest(), str, indent);
83    }
84
85    @Override
86    public void FBooleanLitExpFalse.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
87        str.print("JMI_FALSE");
88    }
89
90    @Override
91    public void FBooleanLitExpTrue.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
92        str.print("JMI_TRUE");
93    }
94
95    @Override
96    public void FCeilFuncExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
97        str.print("ceil(");
98        p.print(getX(), str, indent);
99        str.print(")");
100    }
101
102    @Override
103    public void FDivFuncExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
104        str.print("((long)");
105        if (inFunction()) {
106            str.format("jmi_divide_function(\"%s\", ", containingFFunctionDecl().name());
107        } else {
108            str.print("jmi_divide_equation(jmi, ");
109        }
110        p.print(getX(),str,indent);
111        str.print(","); 
112        p.print(getY(),str,indent);
113        str.print(","); 
114        str.print("\""+prettyPrint("")+"\")");
115        str.print(")");
116    }
117
118    @Override
119    public void FEnumIntegerExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
120        str.print('(');
121        p.print(getFExp(), str, indent);
122        str.print(')');
123    }
124
125    @Override
126    public void FFloorFuncExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
127        str.print("floor(");
128        p.print(getX(), str, indent);
129        str.print(")");
130    }
131
132    @Override
133    public void FHomotopyExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
134        if (p.inInitialSystem()) {
135            if (p.inHomotopySimplified()) {
136                str.print("(");
137                p.print(getSimplified(), str, indent);
138                str.print(")");
139            } else {
140                str.print("(__homotopy_lambda * (");
141                p.print(getActual(), str, indent);
142                str.print(") + (1 - __homotopy_lambda) * (");
143                p.print(getSimplified(), str, indent);
144                str.print("))");
145            }
146        } else {
147            str.print("(");
148            p.print(getActual(), str, indent);
149            str.print(")");
150        }
151    }
152   
153    @Override
154    public void FIfExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
155        boolean arg = isFunctionCallArg();
156        p.printVarDecls(getIfExp(), str, indent);
157        if (arg) {
158            getThenExp().genTempArg(p.DeclStep, str, indent);
159            getElseExp().genTempArg(p.DeclStep, str, indent);
160        } else {
161            p.printVarDecls(getThenExp(), str, indent);
162            p.printVarDecls(getElseExp(), str, indent);
163        }
164    }
165   
166    @Override
167    public void FIfExp.genTempVars_C(CodePrinter p, CodeStream ostr, String indent) {
168        boolean arg = isFunctionCallArg();
169        p.printPreSteps(getIfExp(), ostr, indent);
170        ConditionalCodeStream  str = new ConditionalCodeStream(ostr);
171        String next = p.indent(indent);
172        str.setBufferMode(true);
173        str.print(indent);
174        str.print("if (");
175        p.print(getIfExp(), str, next);
176        str.print(") {\n");
177        str.setBufferMode(false);
178        if (arg) {
179            getThenExp().genTempArg(p.PreStep, str, next);
180        } else {
181            p.printPreSteps(getThenExp(), str, next);
182        }
183        str.setBufferMode(true);
184        str.print(indent);
185        str.print("}");
186        str.clear();
187        str.print(" else {\n");
188        str.setBufferMode(false);
189        if (arg) {
190            getElseExp().genTempArg(p.PreStep, str, next);
191        } else {
192            p.printPreSteps(getElseExp(), str, next);
193        }
194        str.setBufferMode(true);
195        str.print(indent);
196        str.print("}\n");
197        str.close();
198    }
199   
200    @Override
201    public void FIfExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
202        prettyPrint_C(p.ExecStep, str, indent);
203    }
204
205    public void FIfExp.prettyPrint_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
206        boolean arg = isFunctionCallArg();
207        str.print(FEqExp.macro_C);
208        str.print("(");
209        p.codePrinter().print(getIfExp(), str, indent);
210        str.print(", JMI_TRUE, ");
211        if (arg) {
212            getThenExp().genTempArg(p, str, indent);
213        } else {
214            p.print(getThenExp(),str,indent);
215        }
216        str.print(", ");
217        if (arg) {
218            getElseExp().genTempArg(p, str, indent);
219        } else {
220            p.print(getElseExp(),str,indent);
221        }
222        str.print(")");
223    }
224
225    @Override
226    public void FIfExp.genTempFree_C(CodePrinter p, CodeStream ostr, String indent) {
227
228    }
229   
230    @Override
231    public void FInitialExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
232        str.print("_atInitial");
233    }
234
235    @Override
236    public void FLoadResource.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
237        str.formatln("%schar %s[JMI_PATH_MAX];", indent, tempName_C());
238    }
239
240    @Override
241    public void FLoadResource.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
242        if (inFunction()) {
243            error("Cannot generate code for loadResource() in function");
244        } else {
245            str.formatln("%sjmi_load_resource(jmi, %s, \"/%s\");", indent, tempName_C(), loadedResourceRelativePath());
246        }
247    }
248
249    @Override
250    public void FLoadResource.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
251        str.print(tempName_C());
252    }
253
254    @Override
255    public void FLogBinExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
256        str.print(macro_C());
257        str.print("(");
258        p.print(getLeft(), str, indent);
259        str.print(", ");
260        p.print(getRight(), str, indent);
261        str.print(")");
262    }
263
264    @Override
265    public void FMinMaxExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
266        str.print("jmi_" + builtInName() + "(");
267        p.print(getX(), str, indent);
268        str.print(", ");
269        p.print(getY(), str, indent);
270        str.print(")");
271    }
272
273    @Override
274    public void FNoEventExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
275        str.print('(');
276        p.print(getFExp(), str, indent);
277        str.print(')');
278    }
279
280    @Override
281    public void FNotExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
282        str.print(FNotExp.macro_C);
283        str.print("(");
284        p.print(getFExp(), str, indent);
285        str.print(")");
286    }
287
288    @Override
289    public void FPreExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
290        FAbstractVariable fv = myFV();
291        if (fv.isUnknown()) {
292            fv = myNonPreFV();
293        }
294        str.print(fv.preName_C());
295    }
296
297    @Override
298    public void FSampleExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
299        str.print("jmi_sample(jmi,");
300        p.print(getOffset(),str,"");
301        str.print(",");
302        p.print(getInterval(),str,"");
303        str.print(")");
304    }
305
306    @Override
307    public void FSemiLinearExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
308        throw new UnsupportedOperationException("Untransformed semiLinear() expression");
309    }
310
311    @Override
312    public void FSignExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
313        str.print("jmi_sign(");
314        p.print(getFExp(), str, indent);
315        str.print(")");
316    }
317
318    @Override
319    public void FSizeExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
320        size().printSize_C(p, str, indent, getFExp(), dimension());
321    }
322
323    @Override
324    public void FSmoothExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
325        str.print('(');
326        p.print(getFExp(), str, indent);
327        str.print(')');
328    }
329
330    @Override
331    public void FTerminalExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
332        str.print("JMI_FALSE");
333    }
334
335    @Override
336    public void FTerminate.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
337        str.print(indent);
338        str.print("jmi_flag_termination(jmi, ");
339        p.print(getFExp(), str, indent);
340        str.print(");\n");
341    }
342
343    @Override
344    public void FTerminate.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
345        super.genTempVars_C(p, str, indent);
346        p.print(this, str, indent);
347    }
348
349    @Override
350    public void FTimeExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
351        str.print("_time");
352    }
353
354    @Override
355    public void FInStreamEpsExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
356        str.print("jmi_in_stream_eps(jmi)");
357    }
358
359    /*=========================================================================
360     * Numeric Literal Expressions
361     ========================================================================*/
362
363    @Override
364    public void FLitExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
365        str.print(toString());
366        if (convertToDouble(p)) {
367            str.print(".0");
368        }
369    }
370
371    @Override
372    public void FIntegerLitExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
373        if (getValue() == Integer.MAX_VALUE) {
374            str.print("INT_MAX");
375        } else if (getValue() == Integer.MIN_VALUE) {
376            str.print("INT_MIN");
377        } else {
378            super.prettyPrint_C(p, str, indent);
379        }
380    }
381
382    @Override
383    public void FEnumLitExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
384        str.print(ceval().intValue());
385        if (convertToDouble(p)) {
386            str.print(".0");
387        }
388    }
389
390    syn boolean FLitExp.convertToDouble(CodePrinter p) = inIfCondition() || inFunctionArg() || p.inGeneratedFunctionCall(this);
391    eq FRealLitExp.convertToDouble(CodePrinter p) = false;
392
393    public abstract boolean CodePrinter.inGeneratedFunctionCall(FExp exp);
394    public boolean CPrettyPrinter.inGeneratedFunctionCall(FExp exp) {
395        return false;
396    }
397
398    /**
399     * Helper, returns true if the expression is in an function argument
400     */
401    inh boolean FLitExp.inFunctionArg();
402    eq FAbstractFunctionCall.getChild().inFunctionArg() = true;
403    eq FArraySubscripts.getChild().inFunctionArg()      = false;
404    eq FAbstractVariable.getChild().inFunctionArg()     = false;
405    eq FAbstractEquation.getChild().inFunctionArg()     = false;
406    eq Root.getChild().inFunctionArg()                  = false;
407
408    /*=========================================================================
409     * Guarded Expressions
410     * Those that need an jmi guard
411     ========================================================================*/
412
413    /**
414     * Helper, prints jmi guard around an operator
415     */
416    protected void FExp.prettyPrintGuardedStmt(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent, FExp ... exps) {
417        str.print(indent);
418        prettyPrintGuarded(p, str, indent, exps);
419        str.println(";");
420    }
421    protected void FExp.prettyPrintGuarded(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent, FExp ... exps) {
422        new RuntimeCallComputation(p, "").prettyPrintHead(p, str, indent, this, exps, p.codePrinter().returnArguments(this));
423    }
424
425    protected void RuntimeCallComputation.prettyPrintHead(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent, FExp ctx, FExp[] inputs, FExp[] outputs) {
426        boolean func = ctx.inFunction();
427        str.print("jmi_");
428        str.print(p.guardedFunctionName(ctx));
429        str.print(func ? "_function(" : "_equation(");
430        str.print(func ? "\"" + ctx.containingFFunctionDecl().name() + "\", ": "jmi, ");
431        p.codePrinter().print(this, str, indent, CFuncParamDirection.INPUT, Arrays.asList(inputs));
432        p.codePrinter().print(this, str, indent, CFuncParamDirection.OUTPUT, Arrays.asList(outputs));
433        str.print(p.codePrinter().sep());
434        str.print('"');
435        CStringCodeStream tstr = new CStringCodeStream(str);
436        ctx.prettyPrint(tstr, "");
437        tstr.close();
438        str.print("\")");
439    }
440   
441/**
442 * Computes the parameters to use when calling a function defined in the runtime
443 * Unlike a normal ParameterComputation, the number of parameters also depend on
444 * the ExecuteStep of the surrounding context.
445 */
446    public class RuntimeCallComputation extends ParameterComputation {
447            protected CodePrinter.ExecuteCodePrinter exp_p;
448        public RuntimeCallComputation(CodePrinter.ExecuteCodePrinter exp_p, String sep) {
449            super(null, sep);
450            this.exp_p = exp_p;
451        }
452    }
453
454    /**
455     * Helper, returns the specific part of the C guard function
456     */
457    syn String FExp.guardedFunctionName_C() { throw new UnsupportedOperationException(); }
458    eq FDotDivExp.guardedFunctionName_C()           = "divide";
459    eq FDotPowExp.guardedFunctionName_C()           = "pow";
460    eq FBuiltInFunctionCall.guardedFunctionName_C() = builtInName();
461
462    public abstract void CodePrinter.print(IOComputation ioc, CodeStream str, String indent, CFuncParamDirection direction,
463            Iterable<FExp> args);
464   
465    @Override
466    public void CPrettyPrinter.print(IOComputation ioc, CodeStream str, String indent, CFuncParamDirection direction,
467            Iterable<FExp> args) {
468        ioc.print(ExecStep, str, indent, direction, args);
469    }
470
471    public void HeadComputation.print(CodePrinter.ExecuteCodePrinter p, CodeStream str,
472            String indent, CFuncParamDirection direction, Iterable<FExp> args) {}
473
474    @Override
475    public void RuntimeCallComputation.print(CodePrinter.ExecuteCodePrinter p, CodeStream str,
476            String indent, CFuncParamDirection direction, Iterable<FExp> args) {
477        if(!p.isDer() || p.isDer() && exp_p.isDer()) {
478            int i = 0;
479            for (FExp arg : args) {
480                str.print(sep);
481                if(direction == CFuncParamDirection.OUTPUT) {
482                    str.print('&');
483                }
484                arg.genArgument(p, str, indent);
485                sep = p.codePrinter().sep();
486                i++;
487            }
488        }
489    }
490   
491    public abstract FExp[] CodePrinter.returnArguments(FExp exp);
492   
493    @Override
494    public FExp[] CPrettyPrinter.returnArguments(FExp exp) {
495        return exp.returnArguments_C();
496    }
497
498    public FExp[] FExp.returnArguments_C() {
499        return new FExp[] {};
500    }
501   
502
503    @Override
504    public void FDotPowExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
505        int exponent = 100;
506        if (getRight().variability().constantVariability() && getRight().type().isInteger())
507            exponent = getRight().ceval().intValue();
508        if (exponent < 10 && exponent > -10) {
509            str.print("(");
510            String op = (exponent > 0) ? " * " : " / ";
511            exponent = Math.abs(exponent);
512            str.print("1.0");
513            for (int i = 0; i < exponent; i++) {
514                str.print(op);
515                str.print("(");
516                p.print(getLeft(), str, indent);
517                str.print(")");
518            }
519            str.print(")");
520        } else {
521            prettyPrintGuarded(p.ExecStep, str, indent, getLeft(), getRight());
522        }
523    }
524
525    @Override
526    public void FExpExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
527        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
528    }
529
530    @Override
531    public void  FLogExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
532        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
533    }
534
535    @Override
536    public void  FLog10Exp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
537        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
538    }
539
540    @Override
541    public void  FSinhExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
542        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
543    }
544
545    @Override
546    public void  FCoshExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
547        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
548    }
549
550    @Override
551    public void  FTanExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
552        prettyPrintGuarded(p.ExecStep, str, indent, getFExp());
553    }
554
555    @Override
556    public void FAtan2Exp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
557        prettyPrintGuarded(p.ExecStep, str, indent, getFExp(), getY());
558    }
559
560    /**
561     * Helper that generates the C token for the operation
562     */
563    syn String FBinExp.op_C() = op();
564    eq FDotAddExp.op_C() = " + ";
565    eq FDotSubExp.op_C() = " - ";
566    eq FDotMulExp.op_C() = " * ";
567    eq FDotDivExp.op_C() = " / ";
568
569    @Override
570    public void FDotDivExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
571        prettyPrintGuarded(p.ExecStep, str, indent, getLeft(), getRight());
572    }
573
574    /*=========================================================================
575     * Variable Reference Expressions
576     ========================================================================*/
577
578    /**
579     * Helper method that prints the variable reference for assignment (LHS).
580     */
581    public void FAccessExp.genAssignedRef(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
582        p.print(getFAccess(), str, "");
583    }
584
585    public void FAccessExp.genAssignedRef(FAbstractVariable v, CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
586        genAssignedRef(p, str, indent);
587    }
588
589    @Override
590    public void FAbstractDerExp.genAssignedRef(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
591        str.print(p.name(myFV()));
592    }
593
594    public void FAlgorithm.genAssignedRef(FAbstractVariable v, CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
595        str.print(p.name(v));
596    }
597
598    public void FAccessExp.genScaledAssignedRef(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
599        if (needsScaling()) {
600            genScaledAssignedRef(myFV(), p, str, indent);
601        } else {
602            genAssignedRef(p, str, indent);
603        }
604    }
605
606    syn boolean FAbstractVariable.needsScaling(WriteBackContext ctx) = isReal() && myOptions().getBooleanOption("enable_variable_scaling") && !ctx.inFunction();
607    syn boolean FExp.needsScaling() = type().isReal() && myOptions().getBooleanOption("enable_variable_scaling") && !inFunction();
608
609    public void FAccessExp.genScaledAssignedRef(FAbstractVariable v, CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
610        if (needsScaling()) {
611            str.print("(");
612            genAssignedRef(v, p, str, indent);
613            str.print("*sf(");
614            str.print(v.valueReference());
615            str.print("))");
616        } else {
617            genAssignedRef(v, p, str, indent);
618        }
619    }
620
621    public void FAlgorithm.genScaledAssignedRef(FAbstractVariable v, CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
622        if (v.needsScaling(this)) {
623            str.print("(");
624            genAssignedRef(v, p, str, indent);
625            str.print("*sf(");
626            str.print(v.valueReference());
627            str.print("))");
628        } else {
629            genAssignedRef(v, p, str, indent);
630        }
631    }
632
633    @Override
634    public void FAccessExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
635        genScaledAssignedRef(p.ExecStep, str, indent);
636    }
637
638
639    @Override
640    public void FDSRefExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
641        p.print(getOrg(), str, indent);
642    }
643
644    @Override
645    public void FDSDerExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
646        p.print(this, indent, type(), p.createDeclPrinter(str));
647    }
648
649    @Override
650    public void FDSDerExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
651        boolean first = true;
652        String innerIndent = p.indent(indent);
653        for (FVariable[] combination : mySet().stateCombinations()) {
654            if (first)
655                str.format("%sif (", indent);
656            else
657                str.format("%s} else if (", indent);
658            first = false;
659            str.format("jmi_dynamic_state_check_is_state(jmi, %d", mySet().id_C());
660            for (FVariable var : combination)
661                str.format(", %d", var.valueReference());
662            str.println(")) {");
663            FExp valueExp = getUse(combination[getNumber() - 1].dynamicStateVarIndex() - 1);
664            p.printVarDecls(valueExp, str, indent);
665            p.printPreSteps(valueExp, str, indent);
666            p.printAssign(type(), str, innerIndent, this, valueExp);
667            p.printPostSteps(valueExp, str, indent);
668        }
669        str.formatln("%s}", indent);
670    }
671
672    @Override
673    public void FDSDerExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
674        str.print(tempName_C());
675    }
676
677    @Override
678    public void CommonAccess.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
679        str.print(toString_C(p));
680    }
681
682    /**
683     * Checks if the use is in an assignment possition, LHS of a function call
684     * equation or LHS of a statemet.
685     */
686    inh boolean CommonAccess.isAssignUse();
687    eq InstNode.getChild().isAssignUse()          = false;
688    eq FClass.getChild().isAssignUse()            = false;
689    eq FFunctionCallLeft.getChild().isAssignUse() = true;
690    eq FAssignStmt.getLeft().isAssignUse()        = true;
691    eq FAssignStmt.getRight().isAssignUse()       = false;
692
693    syn String CommonAccess.name_C() = toString_C(printer_C);
694
695    syn String CommonAccess.toString_C(CodePrinter p);
696    eq FAccess.toString_C(CodePrinter p) = toString_C(p.getExecStep());
697
698    syn String FAccess.toString_C(CodePrinter.ExecuteCodePrinter p) {
699        return myFV().genUse_C(p, getFArraySubscripts(), myFV().funcArrayType(isAssignUse()));
700    }
701
702    syn String FAccessFull.toString_C(CodePrinter.ExecuteCodePrinter p) {
703        if (getNumFAccessPart() < 2) {
704            return super.toString_C(p);
705        }
706       
707        String type = myFV().funcArrayType(isAssignUse());
708        FAccessPart part = getFAccessPart(0);
709        FArraySubscripts fas = part.hasFArraySubscripts() ? part.getFArraySubscripts() : null;
710        String res = myOutermostFV().genUse_C(p, fas, C_ARRAY_RECORD);
711        for (int i = 1, n = getNumFAccessPart(); i < n; i++) {
712            part = getFAccessPart(i);
713            res = res + "->" + part.getName();
714            if (part.hasFArraySubscripts()) {
715                String curType = (n - i > 1 ? C_ARRAY_RECORD : type);
716                res = part.getFArraySubscripts().genFunctionArrayUse_C(p.codePrinter(), res, curType);
717            }
718        }
719        return res;
720    }
721
722    /**
723     * Helper, generates an regular variable use
724     */
725    public String FAbstractVariable.genUse_C(CodePrinter.ExecuteCodePrinter p, FArraySubscripts fas, String type) {
726        if (fas == null || !fas.isSlice() ) {
727            return p.name(this);
728        } else {
729            return fas.genFunctionArrayUse_C(p.codePrinter(), p.name(this), type);
730        }
731    }
732
733    /**
734     * Helper, generates an array variable use
735     */
736    public String FArraySubscripts.genFunctionArrayUse_C(CodePrinter p, String name, String type) {
737        ByteArrayOutputStream os = new ByteArrayOutputStream();
738        CodeStream str = new CodeStream(os);
739        str.print("jmi_array_", type, "_", numSubscript(), "(", name, ", ");
740        p.print(this, str, "");
741        str.print(")");
742        return os.toString();
743    }
744
745    public void FArrayExpSubscripts.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
746        getFSubscripts().prettyPrintWithSep(p, str, "", ", ");
747    }
748
749    public void FArrayLitSubscripts.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
750        for (int i = 0; i < subscripts.length; i++) {
751            if (i != 0) {
752                str.print(", ");
753            }
754            str.print(subscripts[i]);
755        }
756    }
757
758    /*=========================================================================
759     * Reinit Expression
760     ========================================================================*/
761
762    @Override
763    public void FReinit.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
764        str.print(FExp.global_C(tempName_C()));
765    }
766
767    @Override
768    public void FReinit.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
769        super.genTempVars_C(p, str, indent);
770        String next = indent;
771        if (p.inBlock()) {
772            str.format("%sif (evaluation_mode & JMI_BLOCK_EVALUATE_NON_REALS) {\n", indent);
773            next = p.indent(indent);
774        }
775        p.printAssign(type(), str, next, this, getFExp());
776        genReinitWritebacks_C(p, str, next, true, true);
777        if (p.inBlock()) {
778            str.format("%s}\n", indent);
779        }
780    }
781
782    /*=========================================================================
783     * String Expressions
784     ========================================================================*/
785   
786    /**
787     * Produces statement which writes the string to the variable. This is the
788     * default implementation, subclasses may override it.
789     */
790    public void FExp.genStringExpWrite_C(CodePrinter p, CodeStream str, String indent, String dest) {
791        str.print(indent, "snprintf(JMI_STR_END(", dest, "), JMI_STR_LEFT(", dest, "), ");
792        genStringFormat_C(p, str, indent);
793        str.print(", ");
794        genStringParts_C(p, str, indent);
795        str.println(");");
796    }
797
798    /**
799     * Computes the maximum length of the produced string. This is the default
800     * implementation, subclasses may override it.
801     */
802    public void FExp.genMaxStringLength_C(CodePrinter p, CodeStream str, String indent) {
803        str.print("JMI_LEN(");
804        p.print(this, str, indent);
805        str.print(")");
806    }
807
808    /**
809     * Computes the format string for this expression. This is the default
810     * implementation, subclasses may override it.
811     */
812    public void FExp.genStringFormat_C(CodePrinter p, CodeStream str, String indent) {
813        str.print("\"");
814        if (type().isString())
815            str.print("%s");
816        else
817            throw new IllegalArgumentException("Trying to use expression '" + toString() + "' in string type expression!");
818        str.print("\"");
819    }
820
821    @Override
822    public void FStringAddExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
823        super.genVarDecls_C(p, str, indent);
824        genTopStringDecl(p, str, indent);
825    }
826
827    @Override
828    public void FStringAddExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
829        super.genTempVars_C(p, str, indent);
830        genTopStringInit(p, str, indent);
831    }
832
833    @Override
834    public void FStringAddExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
835        str.print(tempName_C());
836    }
837
838    @Override
839    public void FStringAddExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
840        super.genTempFree_C(p, str, indent);
841    }
842
843    @Override
844    public void FStringAddExp.genStringExpWrite_C(CodePrinter p, CodeStream str, String indent, String dest) {
845        getLeft().genStringExpWrite_C(p, str, indent, dest);
846        getRight().genStringExpWrite_C(p, str, indent, dest);
847    }
848
849    @Override
850    public void FStringAddExp.genMaxStringLength_C(CodePrinter p, CodeStream str, String indent) {
851        getLeft().genMaxStringLength_C(p, str, indent);
852        str.print(" + ");
853        getRight().genMaxStringLength_C(p, str, indent);
854    }
855
856    @Override
857    public void FStringExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
858        super.genVarDecls_C(p, str, indent);
859        genTopStringDecl(p, str, indent);
860    }
861
862    @Override
863    public void FStringExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
864        super.genTempVars_C(p, str, indent);
865        genTopStringInit(p, str, indent);
866    }
867
868    @Override
869    public void FStringExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
870        str.print(tempName_C());
871    }
872
873    @Override
874    public void FStringExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
875        super.genTempFree_C(p, str, indent);
876    }
877
878    @Override
879    public void FStringExp.genMaxStringLength_C(CodePrinter p, CodeStream str, String indent) {
880        if (hasFormat()) {
881            str.print(getValue().type().maxNumericStringLength_C(DEFAULT_PRECISION));
882        } else {
883            if (hasMinimumLength()) {
884                str.print("jmi_max(");
885            }
886            str.print(getValue().type().maxStringLength_C(0));
887            if (getValue().type().isReal()) {
888                str.print(" + ");
889                if (hasSignificantDigits()) {
890                    p.print(getSignificantDigits(), str, indent);
891                } else {
892                    str.print(DEFAULT_PRECISION);
893                }
894            }
895            if (hasMinimumLength()) {
896                str.print(", ");
897                p.print(getMinimumLength(), str, indent);
898                str.print(")");
899            }
900        }
901    }
902
903    @Override
904    public void FStringLitExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
905        str.print('"');
906        str.print(string_C());
907        str.print('"');
908    }
909
910    @Override
911    public void FStringLitExp.genMaxStringLength_C(CodePrinter p, CodeStream str, String indent) {
912        str.print(maxStringLength_C());
913    }
914
915
916    /**
917     * Helper?
918     */
919    public void FExp.genTopStringDecl(CodePrinter p, CodeStream str, String indent) {
920        if (isTopStringOp()) {
921            boolean k = isKnownStringLength();
922            str.format("%sJMI_DEF_%s(%s", indent, k ? "STR_STAT" : "STR_DYNA", tempName_C());
923            if (k) {
924                str.format(", %d", maxStringLength_C());
925            }
926            str.println(")");
927        }
928    }
929
930    /**
931     * Helper?
932     */
933    public void FExp.genTopStringInit(CodePrinter p, CodeStream str, String indent) {
934        if (isTopStringOp()) {
935            boolean k = isKnownStringLength();
936            str.format("%sJMI_INI_%s(%s", indent, k ? "STR_STAT" : "STR_DYNA", tempName_C());
937            if (!k) {
938                str.print(", ");
939                genMaxStringLength_C(p, str, indent);
940            }
941            str.println(")");
942            genStringExpWrite_C(p, str, indent, tempName_C());
943        }
944    }
945
946    @Override
947    public void FStringExp.genStringFormat_C(CodePrinter p, CodeStream str, String indent) {
948        if (hasFormat()) {
949            p.print(getFormat(), str, indent);
950        } else {
951            if (hasLeftJustified()) {
952                str.print("COND_EXP_EQ(");
953                p.print(getLeftJustified(), str, indent);
954                str.print(", JMI_TRUE, ");
955            }
956           
957            genStringFormat_C(str, true);
958           
959            if (hasLeftJustified()) {
960                str.print(", ");
961                genStringFormat_C(str, false);
962                str.print(")");
963            }
964           
965            if (hasMinimumLength()) {
966                str.print(", (int) ");
967                p.print(getMinimumLength(), str, indent);
968            }
969           
970            if (getValue().type().isReal()) {
971                str.print(", (int) ");
972                if (hasSignificantDigits()) {
973                    p.print(getSignificantDigits(), str, indent);
974                } else {
975                    str.print(DEFAULT_PRECISION);
976                }
977            }
978        }
979    }
980
981    public void FStringExp.genStringFormat_C(CodeStream str, boolean justifyLeft) {
982        str.print("\"%");
983        if (justifyLeft)
984            str.print("-");
985        if (hasMinimumLength())
986            str.print("*");
987        if (getValue().type().isReal())
988            str.print(".*");
989        str.print(getValue().type().formatSpecifier());
990        str.print("\"");
991    }
992
993    public void FExp.genStringParts_C(CodePrinter p, CodeStream str, String indent) {
994        // TODO: This method should dispatch to the type!
995        FType t = type();
996        if (t.isEnum()) {
997            str.print(t.enumNames_C());
998            str.print("[(int) ");
999            p.print(this, str, indent);
1000            str.print("]");
1001        } else if (t.isBoolean()) {
1002            str.print("COND_EXP_EQ(");
1003            p.print(this, str, indent);
1004            str.print(", JMI_TRUE, \"true\", \"false\")");
1005        } else {
1006            if (t.isInteger())
1007                str.print("(int) ");
1008            p.print(this, str, indent);
1009        }
1010    }
1011
1012    @Override
1013    public void FStringExp.genStringParts_C(CodePrinter p, CodeStream str, String indent) {
1014        getValue().genStringParts_C(p, str, indent);
1015    }
1016
1017    /**
1018     * Check if this string concatenation or String operator is the top node in an expression consisting of
1019     * one or more string concatenations, i.e. returns true if parent is not an FStringAddExp.
1020     */
1021    inh boolean FExp.isTopStringOp();
1022    eq FStringAddExp.getChild().isTopStringOp() = false;
1023    eq BaseNode.getChild().isTopStringOp()      = true;
1024   
1025    /**
1026     * The value of this string, encoded as UTF-8.
1027     *
1028     * All line breaks are encoded as LF.
1029     */
1030    syn lazy byte[] FStringLitExp.stringUtf8() = getString().replaceAll("\r\n|\r", "\n").getBytes(UTF8);
1031   
1032    /**
1033     * The C representation of this string literal.
1034     */
1035    syn String FStringLitExp.string_C() {
1036        // TODO: Use CStringCodeStream instead?
1037        StringBuffer buf = new StringBuffer();
1038        byte[] str = stringUtf8();
1039        for (int i = 0; i < str.length; i++) {
1040            byte c = str[i];
1041            if (c == '\n') {
1042                buf.append("\\n");
1043            } else if (c > 31 && c < 127) {
1044                buf.append((char) c);
1045            } else if (c != 0) {
1046                int c2 = (c < 0) ? 256 + c : c;
1047                buf.append((c2 < 16) ? "\\x0" : "\\x");
1048                buf.append(Integer.toHexString(c2));
1049                if (i + 1 < str.length && (str[i + 1] >= '0' && str[i + 1] <= '9' || 
1050                        str[i + 1] >= 'a' && str[i + 1] <= 'f' || str[i + 1] >= 'A' && str[i + 1] <= 'F')) {
1051                    buf.append("\"\"");
1052                }
1053            }
1054        }
1055        return buf.toString();
1056    }
1057   
1058    syn boolean FExp.isKnownStringLength() = variability().knownParameterOrLess();
1059    eq FFunctionCall.isKnownStringLength() = false;
1060    eq FStringAddExp.isKnownStringLength() = getLeft().isKnownStringLength() && getRight().isKnownStringLength();
1061    eq FStringExp.isKnownStringLength() = (!hasSignificantDigits() || getSignificantDigits().variability().knownParameterOrLess())
1062            && (!hasMinimumLength() || getMinimumLength().variability().knownParameterOrLess());
1063   
1064    /**
1065     * The maximum length string the representation of the value of this expression can have in C.
1066     */
1067    syn int FExp.maxStringLength_C() { 
1068        if (type().isString())
1069            return MAX_STRING_LENGTH_C;
1070        else
1071            throw new IllegalArgumentException("Trying to use expression '" + toString() + "' in string type expression!");
1072    }
1073    syn lazy int FStringAddExp.maxStringLength_C() = Math.min(getLeft().maxStringLength_C() + getRight().maxStringLength_C(), MAX_STRING_LENGTH_C);
1074    eq FStringLitExp.maxStringLength_C()           = stringUtf8().length;
1075    eq FStringExp.maxStringLength_C() {
1076        // TODO: if there is a format arg, there is no significantDigits
1077        // TODO: handle case where arguments are variables (use MAX_STRING_LENGTH_C?)
1078        VariableEvaluator ev = defaultVariableEvaluator();
1079        if (hasFormat()) {
1080            return type().maxNumericStringLength_C(significantDigits(ev));
1081        } else {
1082            return Math.max(getValue().type().maxStringLength_C(significantDigits(ev)), minimumLength(ev));
1083        }
1084    }
1085   
1086    /**
1087     * The maximum length string representations of values of this type can have in C.
1088     */
1089    syn int FType.maxStringLength_C(int precision) {
1090        throw new UnsupportedOperationException();
1091    }
1092    eq FRealType.maxStringLength_C(int precision)    = 7 + precision;
1093    eq FIntegerType.maxStringLength_C(int precision) = 10;
1094    eq FBooleanType.maxStringLength_C(int precision) = 5;
1095    eq FEnumType.maxStringLength_C(int precision) {
1096        int res = 0;
1097        for (FEnumLiteralType lit : getFEnumLiteralTypes())
1098            res = Math.max(res, lit.getName().length());
1099        return res;
1100    }
1101   
1102    syn int FType.maxNumericStringLength_C(int precision) {
1103        return 10 + precision;
1104    }
1105   
1106    public static final int FExp.MAX_STRING_LENGTH_C = 16 * 1024 - 1;
1107
1108    /*=========================================================================
1109     * Relational Expressions
1110     ========================================================================*/
1111   
1112    @Override
1113    public void FRelExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1114        if (myOptions().getBooleanOption("generate_dae") || !generatesEvent(p.inInitialSystem())) {
1115            super.genVarDecls_C(p, str, indent);
1116        }
1117    }
1118   
1119    @Override
1120    public void FRelExp.genTempVars_C(CodePrinter p, CodeStream str, String outerIndent) {
1121        if (myOptions().getBooleanOption("generate_dae") || !generatesEvent(p.inInitialSystem())) {
1122            super.genTempVars_C(p, str, outerIndent);
1123        } else if (p.writeSwitches()) {
1124            str.print(outerIndent, "if (");
1125            if (p.inBlock())
1126                str.print("evaluation_mode & JMI_BLOCK_EVALUATE_NON_REALS");
1127            else
1128                str.print("jmi->atInitial || jmi->atEvent");
1129            str.println(") {");
1130           
1131            String indent = p.indent(outerIndent);
1132            printIndicator(p.DeclStep, str, indent, false);
1133            printIndicator(p.PreStep, str, indent, false);
1134            str.print(indent);
1135            printSwitchMacro_C(p, str, indent);
1136            boolean time = isTimeEventGenerating();
1137            if (time) {
1138                str.print(" = jmi_turn_switch_time(");
1139            } else {
1140                str.print(" = jmi_turn_switch(");
1141            }
1142            str.print("jmi");
1143            str.print(", ");
1144            printIndicator(p.ExecStep, str, indent, false);
1145            str.print(", ");
1146            printSwitchMacro_C(p, str, indent);
1147            str.print(", ");
1148            boolean phased = isPhased();
1149            if (phased) {
1150                str.print("jmi->eventPhase ? (");
1151                genRelExpKindPhased(str);
1152                str.print(") : (");
1153            }
1154            genRelExpKind(str);
1155            if (phased) {
1156                str.print(")");
1157            }
1158           
1159            str.print(");\n");
1160            printIndicator(p.PostStep, str, indent, false);
1161            str.print(outerIndent, "}\n");
1162        }
1163    }
1164   
1165    @Override
1166    public void FRelExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1167        if (cevalType().isString()) {
1168            str.print("strcmp(");
1169            p.print(getLeft(), str, indent);
1170            str.print(", ");
1171            p.print(getRight(), str, indent);
1172            str.print(")");
1173            str.print(op_C());
1174            str.print("0");
1175        } else if (!generatesEvent(p.inInitialSystem())) {
1176            str.print(macro_C()+"(");
1177            p.print(getLeft(), str, indent);
1178            str.print(", ");
1179            p.print(getRight(), str, indent);
1180            str.print(relIsInverted_C() ? ", JMI_FALSE, JMI_TRUE)" : ", JMI_TRUE, JMI_FALSE)");
1181        } else {
1182            printSwitchMacro_C(p, str, indent);
1183        }
1184    }
1185   
1186    /**
1187     * JMI macro to use for this relational expression
1188     */
1189    syn String FBoolBinExp.macro_C();
1190    eq FEqExp.macro_C()  = FEqExp.macro_C;
1191    eq FNeqExp.macro_C() = FEqExp.macro_C;
1192    eq FLtExp.macro_C()  = "COND_EXP_LT";
1193    eq FLeqExp.macro_C() = "COND_EXP_LE";
1194    eq FGtExp.macro_C()  = "COND_EXP_GT";
1195    eq FGeqExp.macro_C() = "COND_EXP_GE";
1196    eq FAndExp.macro_C() = FAndExp.macro_C;
1197    eq FOrExp.macro_C()  = "LOG_EXP_OR";
1198
1199    public static String FEqExp.macro_C = "COND_EXP_EQ";
1200    public static String FAndExp.macro_C = "LOG_EXP_AND";
1201
1202    public static String FNotExp.macro_C = "LOG_EXP_NOT";
1203
1204    /**
1205     * If the relational expression is negated
1206     */
1207    syn boolean FRelExp.relIsInverted_C() = false;
1208    eq FNeqExp.relIsInverted_C() = true;
1209   
1210
1211    /**
1212     * Helper, prints the appropiate jmi switch macro
1213     */
1214    private void FRelExp.printSwitchMacro_C(CodePrinter p, CodeStream str, String indent) {
1215        if (originalFExp().generatesEventInDAE()) {
1216            str.print("_sw(", mySwitchIndex(), ")");
1217        } else {
1218            str.print("_sw_init(", relExpInInitialEquationsIndex(), ")");
1219        }
1220    }
1221
1222    /**
1223     * Helper, gets the relational c operator
1224     */
1225    syn String FRelExp.op_C() = op();
1226    eq FNeqExp.op_C() = " != ";
1227   
1228
1229    /**
1230     * Helper, check if the relational expression generates phased events
1231     */
1232    syn boolean FRelExp.isPhased() = isTimeEventGenerating() && isPhased_sub();
1233   
1234    /**
1235     * Helper, subcall for isPhased()
1236     */
1237    syn boolean FRelExp.isPhased_sub() { throw new UnsupportedOperationException(); }
1238    eq FGtExp.isPhased_sub()  = getLeft() instanceof FTimeExp;
1239    eq FGeqExp.isPhased_sub() = getRight() instanceof FTimeExp;
1240    eq FLtExp.isPhased_sub()  = getRight() instanceof FTimeExp;
1241    eq FLeqExp.isPhased_sub() = getLeft() instanceof FTimeExp;
1242   
1243    /*=========================================================================
1244     * Function calls
1245     ========================================================================*/
1246
1247    class CodePrinter {
1248        public abstract boolean needsTemp(Named_C exp);
1249        public abstract boolean needsStatement(FFunctionCall call);
1250        public abstract void printCall(FFunctionCall call, CodeStream str, String indent);
1251        public abstract void print(TypePrintable_C n, String indent, FType type, TypePrinter_C tp);
1252    }
1253
1254    class CPrettyPrinter {
1255        @Override
1256        public boolean needsTemp(Named_C exp) {
1257            return exp.needsTemp_C();
1258        }
1259       
1260        @Override
1261        public boolean needsStatement(FFunctionCall call) {
1262            return call.needsStatement_C(this);
1263        }
1264       
1265        @Override
1266        public void printCall(FFunctionCall call, CodeStream str, String indent) {
1267            call.myFCallable().prettyPrintCall(this, str, indent, call);
1268        }
1269       
1270        @Override
1271        public void print(TypePrintable_C n, String indent, FType type, TypePrinter_C tp) {
1272            type.print(tp, indent, ExecStep, n, false);
1273        }
1274       
1275    }
1276
1277    interface Named_C {
1278        public boolean needsTemp_C();
1279    }
1280   
1281    syn boolean FExp.needsTemp_C() = isComposite();
1282    eq     FDSDerExp.needsTemp_C() = true;
1283    eq FFunctionCall.needsTemp_C() =
1284            (!isFunctionCallClause() && isComposite()) || isStringExp() ||
1285            (!functionCallIsExp() && myFCallable().isPartialFunction() && !isPartialFunctionCall());
1286    eq FAccessExp.needsTemp_C() = isSlice() || (isFunctionCallLeft() && (!inFunction() || alsoInRHS() || type().isString()));
1287
1288    syn boolean FFunctionCallLeft.needsTemp_C() = hasFExp() && getFExp().needsTemp_C();
1289    syn boolean FAbstractVariable.needsTemp_C() { return false; }
1290
1291    syn boolean FFunctionCall.needsStatement_C(CodePrinter p) = 
1292            (functionCallIsExp() && isComposite()) || isStringExp() || !functionCallIsExp();
1293
1294    @Override
1295    public void FFunctionCall.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1296        getArgs().genTempArg(p.DeclStep, str, indent);
1297        if (p.needsTemp(this)) {
1298            if (myFCallable().isPartialFunction()) {
1299                str.formatln("%s%s %s;", indent, p.funcNameUnderscore(myFCallable().actualFFunctionDecl(), C_SUFFIX_FPOUT), tempName_C());
1300                if (p.needsOutputVarArgs()) {
1301                    p.print(this, indent, type(), p.createDeclPrinter(str));
1302                }
1303            } else {
1304                p.print(this, indent, type(), p.createDeclPrinter(str));
1305            }
1306        }
1307    }
1308   
1309    @Override
1310    public void FFunctionCall.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1311        getArgs().genTempArg(p.PreStep, str, indent);
1312        if (p.needsTemp(this)) {
1313            p.print(this, indent, type(), p.createInitPrinter(str));
1314        }
1315        if (p.needsStatement(this)) {
1316            p.printCall(this, str, indent);
1317            getArgs().genTempArg(p.PostStep, str, indent);
1318        }
1319    }
1320
1321    @Override
1322    public void FFunctionCall.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1323        if (p.needsStatement(this)) {
1324            str.print(tempName_C());
1325        } else if (impureCodeGen(p)) {
1326            str.print("JMI_CACHED(", tempName_C(), ", ");
1327            p.printCall(this, str, indent);
1328            str.print(")");
1329        } else {
1330            p.printCall(this, str, indent);
1331        }
1332    }
1333
1334    @Override
1335    public void FFunctionCall.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1336        if (!p.needsStatement(this)) {
1337            getArgs().genTempArg(p.PostStep, str, indent);
1338        }
1339    }
1340
1341    syn boolean FFunctionCall.isStringExp() = functionCallIsExp() && type().isString();
1342   
1343    /*=========================================================================
1344     * Delay and Spacial Distribution Expressions
1345     ========================================================================*/
1346   
1347    /**
1348     * Generate temp declarations for the initialization of delay blocks.
1349     */
1350    public void FDelayExp.genInitVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1351        p.printVarDecls(getFExp(), str, indent);
1352        p.printVarDecls(myMaxDelayExp(), str, indent);
1353    }
1354
1355    /**
1356     * Generates the first part of a delay_init call
1357     */
1358        private void FDelayExp.genInit_C_Header(CodePrinter p, CodeStream str, String indent, FExp maxDelayExp, boolean fixed,
1359                        int delayIndex) {
1360                p.printPreSteps(getFExp(), str, indent);
1361        p.printPreSteps(maxDelayExp, str, indent);
1362        str.format("%sjmi_delay_init(jmi, %d, ", indent, delayIndex);
1363        str.print(boolValue_C(fixed)); // jmi_boolean fixed
1364        str.print(", "); 
1365        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1366        str.print(", "); 
1367        p.print(fixed ? getDelay() : maxDelayExp, str, indent); // jmi_real_t max_delay
1368        str.print(", ");
1369        }
1370   
1371    /**
1372     * Generate the initialization of delay blocks.
1373     */
1374    public void FDelayExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1375                FExp maxDelayExp = myMaxDelayExp();
1376        boolean fixed = isTimeEventGenerating();
1377
1378                genInit_C_Header(p, str, indent, maxDelayExp, fixed, myDelayIndex()); 
1379                p.print(getFExp(), str, indent); // jmi_real_t y0
1380                str.println(");");
1381
1382        p.printPostSteps(getFExp(), str, indent);
1383        p.printPostSteps(maxDelayExp, str, indent);
1384    }
1385    syn FExp FDelayExp.myMaxDelayExp() = hasMax() ? getMax() : getDelay();
1386
1387    /**
1388     *
1389     */
1390    public static String ASTNode.boolValue_C(boolean value) {
1391        return value ? "JMI_TRUE" : "JMI_FALSE";
1392    }
1393
1394    /**
1395     * Generate temp declarations for the sampling of delay blocks.
1396     */
1397    public void FDelayExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1398        p.printVarDecls(getFExp(), str, indent);
1399    }
1400
1401    /**
1402     * Generate the sampling of delay blocks.
1403     */
1404    public void FDelayExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1405        p.printPreSteps(getFExp(), str, indent);
1406        str.format("%sjmi_delay_record_sample(jmi, %d, ", indent, myDelayIndex());
1407        p.print(getFExp(), str, indent);
1408        str.println(");");
1409        p.printPostSteps(getFExp(), str, indent);
1410    }
1411
1412    @Override
1413    public void FDelayExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1414        str.format("jmi_delay_evaluate(jmi, %d, ", myDelayIndex());
1415        p.print(getFExp(), str, indent);
1416        str.print(", ");
1417        p.print(getDelay(), str, indent);
1418        str.print(")");
1419    }
1420
1421    @Override
1422    public void FDelayIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1423        if (!p.inInitialSystem()) {
1424            p.printVarDecls(getDelay(), str, indent);
1425        }
1426    }
1427
1428    @Override
1429    public void FDelayIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1430        if (!p.inInitialSystem()) {
1431            p.printPreSteps(getDelay(), str, indent);
1432        }
1433    }
1434
1435    @Override
1436    public void FDelayIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1437        if (!p.inInitialSystem()) {
1438            p.printPostSteps(getDelay(), str, indent);
1439        }
1440    }
1441
1442    @Override
1443    public void FDelayIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1444        if (p.inInitialSystem()) {
1445            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1446        } else {
1447            str.format("%s(jmi, %d, ", jmiDelayFunction_C(), myDelayIndex());
1448            p.print(getDelay(), str, indent);
1449            str.print(")");
1450        }
1451    }
1452
1453    syn String FDelayIndicator.jmiDelayFunction_C();
1454    eq FFirstDelayIndicator.jmiDelayFunction_C()  = "jmi_delay_first_event_indicator_exp";
1455    eq FSecondDelayIndicator.jmiDelayFunction_C() = "jmi_delay_second_event_indicator_exp";
1456
1457    syn nta FExp FDelayIndicator.getDelay() = myDelayExp().getDelay().copySymbolic();
1458
1459    /**
1460     * Generate temp declarations for the initialization of spatialDistribution blocks.
1461     */
1462    public void FSpatialDistExp.genInitVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1463        getX().genTempArg(p.DeclStep, str, indent);
1464        getInitialPoints().genTempArg(p.DeclStep, str, indent);
1465        getInitialValues().genTempArg(p.DeclStep, str, indent);
1466    }
1467
1468    /**
1469     * Generate the initialization of spatialDistribution blocks.
1470     */
1471    public void FSpatialDistExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1472       
1473        //int jmi_spatialdist_init(jmi_t *jmi, int index, jmi_boolean no_event,
1474        // jmi_real_t x0, jmi_real_t *x_init, jmi_real_t *y_init, int n_init);
1475       
1476        getX().genTempArg(p.PreStep, str, indent);
1477        getInitialPoints().genTempArg(p.PreStep, str, indent);
1478        getInitialValues().genTempArg(p.PreStep, str, indent);
1479       
1480        str.format("%sjmi_spatialdist_init(jmi, %d, ", indent, mySpatialDistIndex());
1481        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1482        str.print(", "); 
1483        p.print(getX(), str, indent); // jmi_real_t x0,
1484        str.print(", "); 
1485        getInitialPoints().genTempArg(p.ExecStep, str, indent); // jmi_real_t *x_init
1486        str.print(", ");
1487        getInitialValues().genTempArg(p.ExecStep, str, indent); // jmi_real_t *y_init
1488        str.println(");");
1489       
1490        getX().genTempArg(p.PostStep, str, indent);
1491        getInitialPoints().genTempArg(p.PostStep, str, indent);
1492        getInitialValues().genTempArg(p.PostStep, str, indent);
1493    }
1494
1495    /**
1496     * Generate temp declarations for the sampling of spatialDistribution blocks.
1497     */
1498    public void FSpatialDistExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1499        p.printVarDecls(getIn0(), str, indent);
1500        p.printVarDecls(getIn1(), str, indent);
1501        p.printVarDecls(getX(), str, indent);
1502        p.printVarDecls(getPositiveVelocity(), str, indent);
1503    }
1504
1505    /**
1506     * Generate the sampling of spatialDistribution blocks.
1507     */
1508    public void FSpatialDistExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1509//        int jmi_spatialdist_record_sample(jmi_t *jmi, int index, jmi_real_t in0,
1510//              jmi_real_t in1, jmi_real_t x, jmi_boolean positiveVelocity);
1511       
1512        p.printPreSteps(getIn0(), str, indent);
1513        p.printPreSteps(getIn1(), str, indent);
1514        p.printPreSteps(getX(), str, indent);
1515        p.printPreSteps(getPositiveVelocity(), str, indent);
1516           
1517        str.format("%sjmi_spatialdist_record_sample(jmi, %d, ", indent, mySpatialDistIndex());
1518        p.print(getIn0(), str, indent);
1519        str.print(", ");
1520        p.print(getIn1(), str, indent);
1521        str.print(", ");
1522        p.print(getX(), str, indent);
1523        str.print(", ");
1524        p.print(getPositiveVelocity(), str, indent);
1525        str.println(");");
1526       
1527        p.printPostSteps(getIn0(), str, indent);
1528        p.printPostSteps(getIn1(), str, indent);
1529        p.printPostSteps(getX(), str, indent);
1530        p.printPostSteps(getPositiveVelocity(), str, indent);
1531    }
1532
1533    @Override
1534    public void FSpatialDistExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1535        p.printVarDecls(getIn0(), str, indent);
1536        p.printVarDecls(getIn1(), str, indent);
1537        p.printVarDecls(getX(), str, indent);
1538        p.printVarDecls(getPositiveVelocity(), str, indent);
1539    }
1540
1541    @Override
1542    public void FSpatialDistExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1543        p.printPreSteps(getIn0(), str, indent);
1544        p.printPreSteps(getIn1(), str, indent);
1545        p.printPreSteps(getX(), str, indent);
1546        p.printPreSteps(getPositiveVelocity(), str, indent);
1547        if (!functionCallIsExp()) {// printed later if part of expression
1548            p.print(this, str, indent);
1549        }
1550    }
1551
1552    @Override
1553    public void FSpatialDistExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1554//        int jmi_spatialdist_evaluate(jmi_t *jmi, int index, jmi_real_t *out0,
1555//            jmi_real_t *out1, jmi_real_t in0, jmi_real_t in1, jmi_real_t x,
1556//            jmi_boolean positiveVelocity);
1557       
1558        boolean exp = functionCallIsExp();
1559        if (!exp) {
1560            str.print(indent);
1561        }
1562        str.format("jmi_spatialdist_evaluate(jmi, %d, ", mySpatialDistIndex());
1563        if (exp) {
1564            str.print("NULL, NULL");
1565        } else {
1566            prettyPrintCallOutputs_C(p, str, indent, 2, "");
1567        }
1568        str.print(", ");
1569        p.print(getIn0(), str, indent);
1570        str.print(", ");
1571        p.print(getIn1(), str, indent);
1572        str.print(", ");
1573        p.print(getX(), str, indent);
1574        str.print(", ");
1575        p.print(getPositiveVelocity(), str, indent);
1576        str.print(")");
1577       
1578        if (!exp) {
1579            str.println(";");
1580        }
1581    }
1582
1583    @Override
1584    public void FSpatialDistExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1585        p.printPostSteps(getIn0(), str, indent);
1586        p.printPostSteps(getIn1(), str, indent);
1587        p.printPostSteps(getX(), str, indent);
1588        p.printPostSteps(getPositiveVelocity(), str, indent);
1589    }
1590
1591    @Override
1592    public void FSpatialDistIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1593        if (!p.inInitialSystem()) {
1594            p.printVarDecls(getX(), str, indent);
1595            p.printVarDecls(getPositiveVelocity(), str, indent);
1596        }
1597    }
1598
1599    @Override
1600    public void FSpatialDistIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1601        if (!p.inInitialSystem()) {
1602            p.printPreSteps(getX(), str, indent);
1603            p.printPreSteps(getPositiveVelocity(), str, indent);
1604        }
1605    }
1606
1607    @Override
1608    public void FSpatialDistIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1609        if (!p.inInitialSystem()) {
1610            p.printPostSteps(getX(), str, indent);
1611            p.printPostSteps(getPositiveVelocity(), str, indent);
1612        }
1613    }
1614
1615
1616    @Override
1617    public void FSpatialDistIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1618        if (p.inInitialSystem()) {
1619            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1620        } else {
1621            str.format("jmi_spatialdist_event_indicator_exp(jmi, %d, ", mySpatialDistIndex());
1622            p.print(getX(), str, indent);
1623            str.print(", ");
1624            p.print(getPositiveVelocity(), str, indent);
1625            str.print(")");
1626        }
1627    }
1628    syn nta FExp FSpatialDistIndicator.getX()                = mySpatialDistExp().getX().copySymbolic();
1629    syn nta FExp FSpatialDistIndicator.getPositiveVelocity() = mySpatialDistExp().getPositiveVelocity().copySymbolic();
1630
1631    /*=========================================================================
1632     * Subscripted Expression
1633     ========================================================================*/
1634   
1635    @Override
1636    public void FSubscriptedExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1637        super.genVarDecls_C(p, str, indent);
1638        if (needsTemp()) {
1639            p.printIODecl(getFExp(), str, indent);
1640        }
1641    }
1642
1643    @Override
1644    public void FSubscriptedExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1645        super.genTempVars_C(p, str, indent);
1646        if (needsTemp()) {
1647            p.printIOPre(getFExp(), str, indent);
1648        }
1649    }
1650
1651    @Override
1652    public void FSubscriptedExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1653        prettyPrint_C(p.ExecStep, str, indent);
1654    }
1655
1656    @Override
1657    public void FSubscriptedExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1658        super.genTempFree_C(p, str, indent);
1659        if (needsTemp() && isAssignedTo()) {
1660            p.printWriteBackAssignment(str, indent, this, null);
1661        }
1662    }
1663
1664    public void FSubscriptedExp.prettyPrint_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
1665        if (needsTemp()) {
1666            str.print(getFArraySubscripts().genFunctionArrayUse_C(p.codePrinter(), p.name(getFExp()), C_ARRAY_VALUE));
1667        } else {
1668            getFExp().first().genDirectSubscriptedUse_C(p, str, indent, getFArraySubscripts());
1669        }
1670    }
1671
1672    syn FAccessExp FExp.first() = null;
1673    eq FArray.first()          = getFExp(0).first();
1674    eq FAccessExp.first()       = this;
1675   
1676    syn lazy boolean FSubscriptedExp.needsTemp() = (getFExp().consecutiveArray(null) == null);
1677   
1678    syn FAbstractVariable FExp.consecutiveArray(FAbstractVariable last) = null;
1679    eq FArray.consecutiveArray(FAbstractVariable last) {
1680        for (FExp exp : getFExps()) {
1681            last = exp.consecutiveArray(last);
1682            if (last == null) {
1683                break;
1684            }
1685        }
1686        return last;
1687    }
1688    eq FAccessExp.consecutiveArray(FAbstractVariable last) {
1689        if (last == null || last.isConsecutiveInZ(myFV())) {
1690            return myFV();
1691        }
1692        return null;
1693    }
1694
1695    public void FAccessExp.genDirectSubscriptedUse_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent,
1696            FArraySubscripts fas) {
1697        str.print("(&");
1698        p.print(this, str, indent);
1699        str.print(")");
1700        str.print("[(int)(");
1701        Size s = fas.mySize();
1702        for (int i = fas.numSubscript() - 1; i >= 0; i--) {
1703            fas.subscript(i).prettyPrint(p.codePrinter(), str, indent);
1704            str.print(" - 1");
1705            if (i > 0) {
1706                str.print(" + ");
1707                str.print(s.get(i));
1708                str.print(" * (");
1709            }
1710        }
1711        for (int i = 0; i < fas.numSubscript() - 1; i++) {
1712            str.print(")");
1713        }
1714        str.print(")]");
1715    }
1716}
Note: See TracBrowser for help on using the repository browser.