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

Last change on this file since 13773 was 13773, checked in by jwedin, 7 weeks ago

Refactored the code generation for initializing delay expression. #5852

File size: 62.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    private void FClass.genDelayInitVarDecls(CodePrinter p, CodeStream str, String indent) { // Hook to facilitate extensions
1356        for (FDelayExp d : myDelayExps()) {
1357            d.genInitVarDecls_C(p, str, indent);
1358        }
1359        for (FSpatialDistExp d : mySpatialDistExps()) {
1360            d.genInitVarDecls_C(p, str, indent);
1361        }
1362    }
1363
1364    private void FClass.genDelayInitAssignments(CodePrinter p, CodeStream str, String indent) { // Hook to facilitate extensions
1365        for (FDelayExp d : myDelayExps()) {
1366            d.genInit_C(p, str, indent);
1367        }
1368        for (FSpatialDistExp d : mySpatialDistExps()) {
1369            d.genInit_C(p, str, indent);
1370        }
1371    }
1372   
1373    public void FClass.genDelayInit_C(CodeStream genPrinter) { 
1374        CodePrinter p = ASTNode.printer_C;
1375        String indent = p.indent("");
1376        genDelayInitVarDecls(p, genPrinter, indent);
1377        genDelayInitAssignments(p, genPrinter, indent);
1378    }
1379
1380    private void FDelayExp.prepareInit_C(CodePrinter p, CodeStream str, String indent, int delayIndex) {
1381                FExp maxDelayExp = myMaxDelayExp();
1382        boolean fixed = isTimeEventGenerating();
1383                p.printPreSteps(getFExp(), str, indent);
1384        p.printPreSteps(maxDelayExp, str, indent);
1385        str.format("%sjmi_delay_init(jmi, %d, ", indent, delayIndex);
1386        str.print(boolValue_C(fixed)); // jmi_boolean fixed
1387        str.print(", "); 
1388        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1389        str.print(", "); 
1390        p.print(fixed ? getDelay() : maxDelayExp, str, indent); // jmi_real_t max_delay
1391        str.print(", ");
1392
1393    }
1394
1395    private void FDelayExp.finalizeInit_C(CodePrinter p, CodeStream str, String indent) {
1396                str.println(");");
1397        p.printPostSteps(getFExp(), str, indent);
1398        p.printPostSteps(myMaxDelayExp(), str, indent);
1399    }
1400   
1401    /**
1402     * Generate the initialization of delay blocks.
1403     */
1404    public void FDelayExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1405                prepareInit_C(p, str, indent, myDelayIndex());
1406                p.print(getFExp(), str, indent); // jmi_real_t y0
1407                finalizeInit_C(p, str, indent);
1408    }
1409    syn FExp FDelayExp.myMaxDelayExp() = hasMax() ? getMax() : getDelay();
1410
1411    /**
1412     *
1413     */
1414    public static String ASTNode.boolValue_C(boolean value) {
1415        return value ? "JMI_TRUE" : "JMI_FALSE";
1416    }
1417
1418    /**
1419     * Generate temp declarations for the sampling of delay blocks.
1420     */
1421    public void FDelayExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1422        p.printVarDecls(getFExp(), str, indent);
1423    }
1424
1425    /**
1426     * Generate the sampling of delay blocks.
1427     */
1428    public void FDelayExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1429        p.printPreSteps(getFExp(), str, indent);
1430        str.format("%sjmi_delay_record_sample(jmi, %d, ", indent, myDelayIndex());
1431        p.print(getFExp(), str, indent);
1432        str.println(");");
1433        p.printPostSteps(getFExp(), str, indent);
1434    }
1435
1436    @Override
1437    public void FDelayExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1438        str.format("jmi_delay_evaluate(jmi, %d, ", myDelayIndex());
1439        p.print(getFExp(), str, indent);
1440        str.print(", ");
1441        p.print(getDelay(), str, indent);
1442        str.print(")");
1443    }
1444
1445    @Override
1446    public void FDelayIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1447        if (!p.inInitialSystem()) {
1448            p.printVarDecls(getDelay(), str, indent);
1449        }
1450    }
1451
1452    @Override
1453    public void FDelayIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1454        if (!p.inInitialSystem()) {
1455            p.printPreSteps(getDelay(), str, indent);
1456        }
1457    }
1458
1459    @Override
1460    public void FDelayIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1461        if (!p.inInitialSystem()) {
1462            p.printPostSteps(getDelay(), str, indent);
1463        }
1464    }
1465
1466    @Override
1467    public void FDelayIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1468        if (p.inInitialSystem()) {
1469            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1470        } else {
1471            str.format("%s(jmi, %d, ", jmiDelayFunction_C(), myDelayIndex());
1472            p.print(getDelay(), str, indent);
1473            str.print(")");
1474        }
1475    }
1476
1477    syn String FDelayIndicator.jmiDelayFunction_C();
1478    eq FFirstDelayIndicator.jmiDelayFunction_C()  = "jmi_delay_first_event_indicator_exp";
1479    eq FSecondDelayIndicator.jmiDelayFunction_C() = "jmi_delay_second_event_indicator_exp";
1480
1481    syn nta FExp FDelayIndicator.getDelay() = myDelayExp().getDelay().copySymbolic();
1482
1483    /**
1484     * Generate temp declarations for the initialization of spatialDistribution blocks.
1485     */
1486    public void FSpatialDistExp.genInitVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1487        getX().genTempArg(p.DeclStep, str, indent);
1488        getInitialPoints().genTempArg(p.DeclStep, str, indent);
1489        getInitialValues().genTempArg(p.DeclStep, str, indent);
1490    }
1491
1492    /**
1493     * Generate the initialization of spatialDistribution blocks.
1494     */
1495    public void FSpatialDistExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1496       
1497        //int jmi_spatialdist_init(jmi_t *jmi, int index, jmi_boolean no_event,
1498        // jmi_real_t x0, jmi_real_t *x_init, jmi_real_t *y_init, int n_init);
1499       
1500        getX().genTempArg(p.PreStep, str, indent);
1501        getInitialPoints().genTempArg(p.PreStep, str, indent);
1502        getInitialValues().genTempArg(p.PreStep, str, indent);
1503       
1504        str.format("%sjmi_spatialdist_init(jmi, %d, ", indent, mySpatialDistIndex());
1505        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1506        str.print(", "); 
1507        p.print(getX(), str, indent); // jmi_real_t x0,
1508        str.print(", "); 
1509        getInitialPoints().genTempArg(p.ExecStep, str, indent); // jmi_real_t *x_init
1510        str.print(", ");
1511        getInitialValues().genTempArg(p.ExecStep, str, indent); // jmi_real_t *y_init
1512        str.println(");");
1513       
1514        getX().genTempArg(p.PostStep, str, indent);
1515        getInitialPoints().genTempArg(p.PostStep, str, indent);
1516        getInitialValues().genTempArg(p.PostStep, str, indent);
1517    }
1518
1519    /**
1520     * Generate temp declarations for the sampling of spatialDistribution blocks.
1521     */
1522    public void FSpatialDistExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1523        p.printVarDecls(getIn0(), str, indent);
1524        p.printVarDecls(getIn1(), str, indent);
1525        p.printVarDecls(getX(), str, indent);
1526        p.printVarDecls(getPositiveVelocity(), str, indent);
1527    }
1528
1529    /**
1530     * Generate the sampling of spatialDistribution blocks.
1531     */
1532    public void FSpatialDistExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1533//        int jmi_spatialdist_record_sample(jmi_t *jmi, int index, jmi_real_t in0,
1534//              jmi_real_t in1, jmi_real_t x, jmi_boolean positiveVelocity);
1535       
1536        p.printPreSteps(getIn0(), str, indent);
1537        p.printPreSteps(getIn1(), str, indent);
1538        p.printPreSteps(getX(), str, indent);
1539        p.printPreSteps(getPositiveVelocity(), str, indent);
1540           
1541        str.format("%sjmi_spatialdist_record_sample(jmi, %d, ", indent, mySpatialDistIndex());
1542        p.print(getIn0(), str, indent);
1543        str.print(", ");
1544        p.print(getIn1(), str, indent);
1545        str.print(", ");
1546        p.print(getX(), str, indent);
1547        str.print(", ");
1548        p.print(getPositiveVelocity(), str, indent);
1549        str.println(");");
1550       
1551        p.printPostSteps(getIn0(), str, indent);
1552        p.printPostSteps(getIn1(), str, indent);
1553        p.printPostSteps(getX(), str, indent);
1554        p.printPostSteps(getPositiveVelocity(), str, indent);
1555    }
1556
1557    @Override
1558    public void FSpatialDistExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1559        p.printVarDecls(getIn0(), str, indent);
1560        p.printVarDecls(getIn1(), str, indent);
1561        p.printVarDecls(getX(), str, indent);
1562        p.printVarDecls(getPositiveVelocity(), str, indent);
1563    }
1564
1565    @Override
1566    public void FSpatialDistExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1567        p.printPreSteps(getIn0(), str, indent);
1568        p.printPreSteps(getIn1(), str, indent);
1569        p.printPreSteps(getX(), str, indent);
1570        p.printPreSteps(getPositiveVelocity(), str, indent);
1571        if (!functionCallIsExp()) {// printed later if part of expression
1572            p.print(this, str, indent);
1573        }
1574    }
1575
1576    @Override
1577    public void FSpatialDistExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1578//        int jmi_spatialdist_evaluate(jmi_t *jmi, int index, jmi_real_t *out0,
1579//            jmi_real_t *out1, jmi_real_t in0, jmi_real_t in1, jmi_real_t x,
1580//            jmi_boolean positiveVelocity);
1581       
1582        boolean exp = functionCallIsExp();
1583        if (!exp) {
1584            str.print(indent);
1585        }
1586        str.format("jmi_spatialdist_evaluate(jmi, %d, ", mySpatialDistIndex());
1587        if (exp) {
1588            str.print("NULL, NULL");
1589        } else {
1590            prettyPrintCallOutputs_C(p, str, indent, 2, "");
1591        }
1592        str.print(", ");
1593        p.print(getIn0(), str, indent);
1594        str.print(", ");
1595        p.print(getIn1(), str, indent);
1596        str.print(", ");
1597        p.print(getX(), str, indent);
1598        str.print(", ");
1599        p.print(getPositiveVelocity(), str, indent);
1600        str.print(")");
1601       
1602        if (!exp) {
1603            str.println(";");
1604        }
1605    }
1606
1607    @Override
1608    public void FSpatialDistExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1609        p.printPostSteps(getIn0(), str, indent);
1610        p.printPostSteps(getIn1(), str, indent);
1611        p.printPostSteps(getX(), str, indent);
1612        p.printPostSteps(getPositiveVelocity(), str, indent);
1613    }
1614
1615    @Override
1616    public void FSpatialDistIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1617        if (!p.inInitialSystem()) {
1618            p.printVarDecls(getX(), str, indent);
1619            p.printVarDecls(getPositiveVelocity(), str, indent);
1620        }
1621    }
1622
1623    @Override
1624    public void FSpatialDistIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1625        if (!p.inInitialSystem()) {
1626            p.printPreSteps(getX(), str, indent);
1627            p.printPreSteps(getPositiveVelocity(), str, indent);
1628        }
1629    }
1630
1631    @Override
1632    public void FSpatialDistIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1633        if (!p.inInitialSystem()) {
1634            p.printPostSteps(getX(), str, indent);
1635            p.printPostSteps(getPositiveVelocity(), str, indent);
1636        }
1637    }
1638
1639
1640    @Override
1641    public void FSpatialDistIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1642        if (p.inInitialSystem()) {
1643            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1644        } else {
1645            str.format("jmi_spatialdist_event_indicator_exp(jmi, %d, ", mySpatialDistIndex());
1646            p.print(getX(), str, indent);
1647            str.print(", ");
1648            p.print(getPositiveVelocity(), str, indent);
1649            str.print(")");
1650        }
1651    }
1652    syn nta FExp FSpatialDistIndicator.getX()                = mySpatialDistExp().getX().copySymbolic();
1653    syn nta FExp FSpatialDistIndicator.getPositiveVelocity() = mySpatialDistExp().getPositiveVelocity().copySymbolic();
1654
1655    /*=========================================================================
1656     * Subscripted Expression
1657     ========================================================================*/
1658   
1659    @Override
1660    public void FSubscriptedExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1661        super.genVarDecls_C(p, str, indent);
1662        if (needsTemp()) {
1663            p.printIODecl(getFExp(), str, indent);
1664        }
1665    }
1666
1667    @Override
1668    public void FSubscriptedExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1669        super.genTempVars_C(p, str, indent);
1670        if (needsTemp()) {
1671            p.printIOPre(getFExp(), str, indent);
1672        }
1673    }
1674
1675    @Override
1676    public void FSubscriptedExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1677        prettyPrint_C(p.ExecStep, str, indent);
1678    }
1679
1680    @Override
1681    public void FSubscriptedExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1682        super.genTempFree_C(p, str, indent);
1683        if (needsTemp() && isAssignedTo()) {
1684            p.printWriteBackAssignment(str, indent, this, null);
1685        }
1686    }
1687
1688    public void FSubscriptedExp.prettyPrint_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
1689        if (needsTemp()) {
1690            str.print(getFArraySubscripts().genFunctionArrayUse_C(p.codePrinter(), p.name(getFExp()), C_ARRAY_VALUE));
1691        } else {
1692            getFExp().first().genDirectSubscriptedUse_C(p, str, indent, getFArraySubscripts());
1693        }
1694    }
1695
1696    syn FAccessExp FExp.first() = null;
1697    eq FArray.first()          = getFExp(0).first();
1698    eq FAccessExp.first()       = this;
1699   
1700    syn lazy boolean FSubscriptedExp.needsTemp() = (getFExp().consecutiveArray(null) == null);
1701   
1702    syn FAbstractVariable FExp.consecutiveArray(FAbstractVariable last) = null;
1703    eq FArray.consecutiveArray(FAbstractVariable last) {
1704        for (FExp exp : getFExps()) {
1705            last = exp.consecutiveArray(last);
1706            if (last == null) {
1707                break;
1708            }
1709        }
1710        return last;
1711    }
1712    eq FAccessExp.consecutiveArray(FAbstractVariable last) {
1713        if (last == null || last.isConsecutiveInZ(myFV())) {
1714            return myFV();
1715        }
1716        return null;
1717    }
1718
1719    public void FAccessExp.genDirectSubscriptedUse_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent,
1720            FArraySubscripts fas) {
1721        str.print("(&");
1722        p.print(this, str, indent);
1723        str.print(")");
1724        str.print("[(int)(");
1725        Size s = fas.mySize();
1726        for (int i = fas.numSubscript() - 1; i >= 0; i--) {
1727            fas.subscript(i).prettyPrint(p.codePrinter(), str, indent);
1728            str.print(" - 1");
1729            if (i > 0) {
1730                str.print(" + ");
1731                str.print(s.get(i));
1732                str.print(" * (");
1733            }
1734        }
1735        for (int i = 0; i < fas.numSubscript() - 1; i++) {
1736            str.print(")");
1737        }
1738        str.print(")]");
1739    }
1740}
Note: See TracBrowser for help on using the repository browser.