source: branches/dev-mj-5835/Compiler/ModelicaCBackEnd/src/jastadd/CCodeGen/CCodeGenExpressions.jrag @ 13871

Last change on this file since 13871 was 13871, checked in by Jesper Mattsson, 6 weeks ago

Updates after review. (#5835)

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