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

Last change on this file since 13702 was 13702, checked in by Jesper Mattsson, 2 months ago

#5835:

  • Added formalized parsing of format strings to allow error checking and required casts.
  • Fixed errors in C code gen for String() operator.
  • Made format string structural parameter.
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;
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    protected 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 && format.expectedType.isUnsigned()) {
1026                str.print("(unsigned int) ");
1027            } else if ((format == null) ? t.isInteger() : format.expectedType.isInteger()) {
1028                str.print("(int) ");
1029            }
1030            p.print(this, str, indent);
1031        }
1032    }
1033
1034    @Override
1035    public void FStringExp.genStringParts_C(
1036            CodePrinter p, CodeStream str, String indent, CFormatSpecifier format) {
1037        try {
1038            // This depends on non-parameters being evaluatable.
1039            format = formatSpecifier();
1040        } catch (ConstantEvaluationException e) {
1041            // Assume that we don't have a format that converts real -> integer.
1042        }
1043        getValue().genStringParts_C(p, str, indent, format);
1044    }
1045
1046    /**
1047     * Check if this string concatenation or String operator is the top node in an expression consisting of
1048     * one or more string concatenations, i.e. returns true if parent is not an FStringAddExp.
1049     */
1050    inh boolean FExp.isTopStringOp();
1051    eq FStringAddExp.getChild().isTopStringOp() = false;
1052    eq BaseNode.getChild().isTopStringOp()      = true;
1053   
1054    /**
1055     * The value of this string, encoded as UTF-8.
1056     *
1057     * All line breaks are encoded as LF.
1058     */
1059    syn lazy byte[] FStringLitExp.stringUtf8() = getString().replaceAll("\r\n|\r", "\n").getBytes(UTF8);
1060   
1061    /**
1062     * The C representation of this string literal.
1063     */
1064    syn String FStringLitExp.string_C() {
1065        // TODO: Use CStringCodeStream instead?
1066        StringBuffer buf = new StringBuffer();
1067        byte[] str = stringUtf8();
1068        for (int i = 0; i < str.length; i++) {
1069            byte c = str[i];
1070            if (c == '\n') {
1071                buf.append("\\n");
1072            } else if (c > 31 && c < 127) {
1073                buf.append((char) c);
1074            } else if (c != 0) {
1075                int c2 = (c < 0) ? 256 + c : c;
1076                buf.append((c2 < 16) ? "\\x0" : "\\x");
1077                buf.append(Integer.toHexString(c2));
1078                if (i + 1 < str.length && (str[i + 1] >= '0' && str[i + 1] <= '9' || 
1079                        str[i + 1] >= 'a' && str[i + 1] <= 'f' || str[i + 1] >= 'A' && str[i + 1] <= 'F')) {
1080                    buf.append("\"\"");
1081                }
1082            }
1083        }
1084        return buf.toString();
1085    }
1086   
1087    syn boolean FExp.isKnownStringLength() = variability().knownParameterOrLess();
1088    eq FFunctionCall.isKnownStringLength() = false;
1089    eq FStringAddExp.isKnownStringLength() = getLeft().isKnownStringLength() && getRight().isKnownStringLength();
1090    eq FStringExp.isKnownStringLength() = (!hasSignificantDigits() || getSignificantDigits().variability().knownParameterOrLess())
1091            && (!hasMinimumLength() || getMinimumLength().variability().knownParameterOrLess());
1092   
1093    /**
1094     * The maximum length string the representation of the value of this expression can have in C.
1095     */
1096    syn int FExp.maxStringLength_C() { 
1097        if (type().isString())
1098            return MAX_STRING_LENGTH_C;
1099        else
1100            throw new IllegalArgumentException("Trying to use expression '" + toString() + "' in string type expression!");
1101    }
1102    syn lazy int FStringAddExp.maxStringLength_C() = Math.min(getLeft().maxStringLength_C() + getRight().maxStringLength_C(), MAX_STRING_LENGTH_C);
1103    eq FStringLitExp.maxStringLength_C()           = stringUtf8().length;
1104    eq FStringExp.maxStringLength_C() {
1105        // TODO: if there is a format arg, there is no significantDigits
1106        // TODO: handle case where arguments are variables (use MAX_STRING_LENGTH_C?)
1107        VariableEvaluator ev = defaultVariableEvaluator();
1108        if (hasFormat()) {
1109            return type().maxNumericStringLength_C(significantDigits(ev));
1110        } else {
1111            return Math.max(getValue().type().maxStringLength_C(significantDigits(ev)), minimumLength(ev));
1112        }
1113    }
1114   
1115    /**
1116     * The maximum length string representations of values of this type can have in C.
1117     */
1118    syn int FType.maxStringLength_C(int precision) {
1119        throw new UnsupportedOperationException();
1120    }
1121    eq FRealType.maxStringLength_C(int precision)    = 7 + precision;
1122    eq FIntegerType.maxStringLength_C(int precision) = 10;
1123    eq FBooleanType.maxStringLength_C(int precision) = 5;
1124    eq FEnumType.maxStringLength_C(int precision) {
1125        int res = 0;
1126        for (FEnumLiteralType lit : getFEnumLiteralTypes())
1127            res = Math.max(res, lit.getName().length());
1128        return res;
1129    }
1130   
1131    syn int FType.maxNumericStringLength_C(int precision) {
1132        return 10 + precision;
1133    }
1134   
1135    public static final int FExp.MAX_STRING_LENGTH_C = 16 * 1024 - 1;
1136
1137    /*=========================================================================
1138     * Relational Expressions
1139     ========================================================================*/
1140   
1141    @Override
1142    public void FRelExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1143        if (myOptions().getBooleanOption("generate_dae") || !generatesEvent(p.inInitialSystem())) {
1144            super.genVarDecls_C(p, str, indent);
1145        }
1146    }
1147   
1148    @Override
1149    public void FRelExp.genTempVars_C(CodePrinter p, CodeStream str, String outerIndent) {
1150        if (myOptions().getBooleanOption("generate_dae") || !generatesEvent(p.inInitialSystem())) {
1151            super.genTempVars_C(p, str, outerIndent);
1152        } else if (p.writeSwitches()) {
1153            str.print(outerIndent, "if (");
1154            if (p.inBlock())
1155                str.print("evaluation_mode & JMI_BLOCK_EVALUATE_NON_REALS");
1156            else
1157                str.print("jmi->atInitial || jmi->atEvent");
1158            str.println(") {");
1159           
1160            String indent = p.indent(outerIndent);
1161            printIndicator(p.DeclStep, str, indent, false);
1162            printIndicator(p.PreStep, str, indent, false);
1163            str.print(indent);
1164            printSwitchMacro_C(p, str, indent);
1165            boolean time = isTimeEventGenerating();
1166            if (time) {
1167                str.print(" = jmi_turn_switch_time(");
1168            } else {
1169                str.print(" = jmi_turn_switch(");
1170            }
1171            str.print("jmi");
1172            str.print(", ");
1173            printIndicator(p.ExecStep, str, indent, false);
1174            str.print(", ");
1175            printSwitchMacro_C(p, str, indent);
1176            str.print(", ");
1177            boolean phased = isPhased();
1178            if (phased) {
1179                str.print("jmi->eventPhase ? (");
1180                genRelExpKindPhased(str);
1181                str.print(") : (");
1182            }
1183            genRelExpKind(str);
1184            if (phased) {
1185                str.print(")");
1186            }
1187           
1188            str.print(");\n");
1189            printIndicator(p.PostStep, str, indent, false);
1190            str.print(outerIndent, "}\n");
1191        }
1192    }
1193   
1194    @Override
1195    public void FRelExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1196        if (cevalType().isString()) {
1197            str.print("strcmp(");
1198            p.print(getLeft(), str, indent);
1199            str.print(", ");
1200            p.print(getRight(), str, indent);
1201            str.print(")");
1202            str.print(op_C());
1203            str.print("0");
1204        } else if (!generatesEvent(p.inInitialSystem())) {
1205            str.print(macro_C()+"(");
1206            p.print(getLeft(), str, indent);
1207            str.print(", ");
1208            p.print(getRight(), str, indent);
1209            str.print(relIsInverted_C() ? ", JMI_FALSE, JMI_TRUE)" : ", JMI_TRUE, JMI_FALSE)");
1210        } else {
1211            printSwitchMacro_C(p, str, indent);
1212        }
1213    }
1214   
1215    /**
1216     * JMI macro to use for this relational expression
1217     */
1218    syn String FBoolBinExp.macro_C();
1219    eq FEqExp.macro_C()  = FEqExp.macro_C;
1220    eq FNeqExp.macro_C() = FEqExp.macro_C;
1221    eq FLtExp.macro_C()  = "COND_EXP_LT";
1222    eq FLeqExp.macro_C() = "COND_EXP_LE";
1223    eq FGtExp.macro_C()  = "COND_EXP_GT";
1224    eq FGeqExp.macro_C() = "COND_EXP_GE";
1225    eq FAndExp.macro_C() = FAndExp.macro_C;
1226    eq FOrExp.macro_C()  = "LOG_EXP_OR";
1227
1228    public static String FEqExp.macro_C = "COND_EXP_EQ";
1229    public static String FAndExp.macro_C = "LOG_EXP_AND";
1230
1231    public static String FNotExp.macro_C = "LOG_EXP_NOT";
1232
1233    /**
1234     * If the relational expression is negated
1235     */
1236    syn boolean FRelExp.relIsInverted_C() = false;
1237    eq FNeqExp.relIsInverted_C() = true;
1238   
1239
1240    /**
1241     * Helper, prints the appropiate jmi switch macro
1242     */
1243    private void FRelExp.printSwitchMacro_C(CodePrinter p, CodeStream str, String indent) {
1244        if (originalFExp().generatesEventInDAE()) {
1245            str.print("_sw(", mySwitchIndex(), ")");
1246        } else {
1247            str.print("_sw_init(", relExpInInitialEquationsIndex(), ")");
1248        }
1249    }
1250
1251    /**
1252     * Helper, gets the relational c operator
1253     */
1254    syn String FRelExp.op_C() = op();
1255    eq FNeqExp.op_C() = " != ";
1256   
1257
1258    /**
1259     * Helper, check if the relational expression generates phased events
1260     */
1261    syn boolean FRelExp.isPhased() = isTimeEventGenerating() && isPhased_sub();
1262   
1263    /**
1264     * Helper, subcall for isPhased()
1265     */
1266    syn boolean FRelExp.isPhased_sub() { throw new UnsupportedOperationException(); }
1267    eq FGtExp.isPhased_sub()  = getLeft() instanceof FTimeExp;
1268    eq FGeqExp.isPhased_sub() = getRight() instanceof FTimeExp;
1269    eq FLtExp.isPhased_sub()  = getRight() instanceof FTimeExp;
1270    eq FLeqExp.isPhased_sub() = getLeft() instanceof FTimeExp;
1271   
1272    /*=========================================================================
1273     * Function calls
1274     ========================================================================*/
1275
1276    class CodePrinter {
1277        public abstract boolean needsTemp(Named_C exp);
1278        public abstract boolean needsStatement(FFunctionCall call);
1279        public abstract void printCall(FFunctionCall call, CodeStream str, String indent);
1280        public abstract void print(TypePrintable_C n, String indent, FType type, TypePrinter_C tp);
1281    }
1282
1283    class CPrettyPrinter {
1284        @Override
1285        public boolean needsTemp(Named_C exp) {
1286            return exp.needsTemp_C();
1287        }
1288       
1289        @Override
1290        public boolean needsStatement(FFunctionCall call) {
1291            return call.needsStatement_C(this);
1292        }
1293       
1294        @Override
1295        public void printCall(FFunctionCall call, CodeStream str, String indent) {
1296            call.myFCallable().prettyPrintCall(this, str, indent, call);
1297        }
1298       
1299        @Override
1300        public void print(TypePrintable_C n, String indent, FType type, TypePrinter_C tp) {
1301            type.print(tp, indent, ExecStep, n, false);
1302        }
1303       
1304    }
1305
1306    interface Named_C {
1307        public boolean needsTemp_C();
1308    }
1309   
1310    syn boolean FExp.needsTemp_C() = isComposite();
1311    eq     FDSDerExp.needsTemp_C() = true;
1312    eq FFunctionCall.needsTemp_C() =
1313            (!isFunctionCallClause() && isComposite()) || isStringExp() ||
1314            (!functionCallIsExp() && myFCallable().isPartialFunction() && !isPartialFunctionCall());
1315    eq FAccessExp.needsTemp_C() = isSlice() || (isFunctionCallLeft() && (!inFunction() || alsoInRHS() || type().isString()));
1316
1317    syn boolean FFunctionCallLeft.needsTemp_C() = hasFExp() && getFExp().needsTemp_C();
1318    syn boolean FAbstractVariable.needsTemp_C() { return false; }
1319
1320    syn boolean FFunctionCall.needsStatement_C(CodePrinter p) = 
1321            (functionCallIsExp() && isComposite()) || isStringExp() || !functionCallIsExp();
1322
1323    @Override
1324    public void FFunctionCall.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1325        getArgs().genTempArg(p.DeclStep, str, indent);
1326        if (p.needsTemp(this)) {
1327            if (myFCallable().isPartialFunction()) {
1328                str.formatln("%s%s %s;", indent, p.funcNameUnderscore(myFCallable().actualFFunctionDecl(), C_SUFFIX_FPOUT), tempName_C());
1329                if (p.needsOutputVarArgs()) {
1330                    p.print(this, indent, type(), p.createDeclPrinter(str));
1331                }
1332            } else {
1333                p.print(this, indent, type(), p.createDeclPrinter(str));
1334            }
1335        }
1336    }
1337   
1338    @Override
1339    public void FFunctionCall.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1340        getArgs().genTempArg(p.PreStep, str, indent);
1341        if (p.needsTemp(this)) {
1342            p.print(this, indent, type(), p.createInitPrinter(str));
1343        }
1344        if (p.needsStatement(this)) {
1345            p.printCall(this, str, indent);
1346            getArgs().genTempArg(p.PostStep, str, indent);
1347        }
1348    }
1349
1350    @Override
1351    public void FFunctionCall.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1352        if (p.needsStatement(this)) {
1353            str.print(tempName_C());
1354        } else if (impureCodeGen(p)) {
1355            str.print("JMI_CACHED(", tempName_C(), ", ");
1356            p.printCall(this, str, indent);
1357            str.print(")");
1358        } else {
1359            p.printCall(this, str, indent);
1360        }
1361    }
1362
1363    @Override
1364    public void FFunctionCall.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1365        if (!p.needsStatement(this)) {
1366            getArgs().genTempArg(p.PostStep, str, indent);
1367        }
1368    }
1369
1370    syn boolean FFunctionCall.isStringExp() = functionCallIsExp() && type().isString();
1371   
1372    /*=========================================================================
1373     * Delay and Spacial Distribution Expressions
1374     ========================================================================*/
1375   
1376    /**
1377     * Generate temp declarations for the initialization of delay blocks.
1378     */
1379    public void FDelayExp.genInitVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1380        p.printVarDecls(getFExp(), str, indent);
1381        p.printVarDecls(myMaxDelayExp(), str, indent);
1382    }
1383   
1384    /**
1385     * Generate the initialization of delay blocks.
1386     */
1387    public void FDelayExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1388        FExp maxDelayExp = myMaxDelayExp();
1389        boolean fixed = isTimeEventGenerating();
1390        p.printPreSteps(getFExp(), str, indent);
1391        p.printPreSteps(maxDelayExp, str, indent);
1392       
1393        str.format("%sjmi_delay_init(jmi, %d, ", indent, myDelayIndex());
1394        str.print(boolValue_C(fixed)); // jmi_boolean fixed
1395        str.print(", "); 
1396        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1397        str.print(", "); 
1398        p.print(fixed ? getDelay() : maxDelayExp, str, indent); // jmi_real_t max_delay
1399        str.print(", "); 
1400        p.print(getFExp(), str, indent); // jmi_real_t y0
1401        str.println(");");
1402       
1403        p.printPostSteps(getFExp(), str, indent);
1404        p.printPostSteps(maxDelayExp, str, indent);
1405    }
1406    syn FExp FDelayExp.myMaxDelayExp() = hasMax() ? getMax() : getDelay();
1407
1408    /**
1409     *
1410     */
1411    public static String ASTNode.boolValue_C(boolean value) {
1412        return value ? "JMI_TRUE" : "JMI_FALSE";
1413    }
1414
1415    /**
1416     * Generate temp declarations for the sampling of delay blocks.
1417     */
1418    public void FDelayExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1419        p.printVarDecls(getFExp(), str, indent);
1420    }
1421
1422    /**
1423     * Generate the sampling of delay blocks.
1424     */
1425    public void FDelayExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1426        p.printPreSteps(getFExp(), str, indent);
1427        str.format("%sjmi_delay_record_sample(jmi, %d, ", indent, myDelayIndex());
1428        p.print(getFExp(), str, indent);
1429        str.println(");");
1430        p.printPostSteps(getFExp(), str, indent);
1431    }
1432
1433    @Override
1434    public void FDelayExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1435        str.format("jmi_delay_evaluate(jmi, %d, ", myDelayIndex());
1436        p.print(getFExp(), str, indent);
1437        str.print(", ");
1438        p.print(getDelay(), str, indent);
1439        str.print(")");
1440    }
1441
1442    @Override
1443    public void FDelayIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1444        if (!p.inInitialSystem()) {
1445            p.printVarDecls(getDelay(), str, indent);
1446        }
1447    }
1448
1449    @Override
1450    public void FDelayIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1451        if (!p.inInitialSystem()) {
1452            p.printPreSteps(getDelay(), str, indent);
1453        }
1454    }
1455
1456    @Override
1457    public void FDelayIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1458        if (!p.inInitialSystem()) {
1459            p.printPostSteps(getDelay(), str, indent);
1460        }
1461    }
1462
1463    @Override
1464    public void FDelayIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1465        if (p.inInitialSystem()) {
1466            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1467        } else {
1468            str.format("%s(jmi, %d, ", jmiDelayFunction_C(), myDelayIndex());
1469            p.print(getDelay(), str, indent);
1470            str.print(")");
1471        }
1472    }
1473
1474    syn String FDelayIndicator.jmiDelayFunction_C();
1475    eq FFirstDelayIndicator.jmiDelayFunction_C()  = "jmi_delay_first_event_indicator_exp";
1476    eq FSecondDelayIndicator.jmiDelayFunction_C() = "jmi_delay_second_event_indicator_exp";
1477
1478    syn nta FExp FDelayIndicator.getDelay() = myDelayExp().getDelay().copySymbolic();
1479
1480    /**
1481     * Generate temp declarations for the initialization of spatialDistribution blocks.
1482     */
1483    public void FSpatialDistExp.genInitVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1484        getX().genTempArg(p.DeclStep, str, indent);
1485        getInitialPoints().genTempArg(p.DeclStep, str, indent);
1486        getInitialValues().genTempArg(p.DeclStep, str, indent);
1487    }
1488
1489    /**
1490     * Generate the initialization of spatialDistribution blocks.
1491     */
1492    public void FSpatialDistExp.genInit_C(CodePrinter p, CodeStream str, String indent) {
1493       
1494        //int jmi_spatialdist_init(jmi_t *jmi, int index, jmi_boolean no_event,
1495        // jmi_real_t x0, jmi_real_t *x_init, jmi_real_t *y_init, int n_init);
1496       
1497        getX().genTempArg(p.PreStep, str, indent);
1498        getInitialPoints().genTempArg(p.PreStep, str, indent);
1499        getInitialValues().genTempArg(p.PreStep, str, indent);
1500       
1501        str.format("%sjmi_spatialdist_init(jmi, %d, ", indent, mySpatialDistIndex());
1502        str.print(boolValue_C(!generatesEventInDAE())); // jmi_boolean no_event
1503        str.print(", "); 
1504        p.print(getX(), str, indent); // jmi_real_t x0,
1505        str.print(", "); 
1506        getInitialPoints().genTempArg(p.ExecStep, str, indent); // jmi_real_t *x_init
1507        str.print(", ");
1508        getInitialValues().genTempArg(p.ExecStep, str, indent); // jmi_real_t *y_init
1509        str.println(");");
1510       
1511        getX().genTempArg(p.PostStep, str, indent);
1512        getInitialPoints().genTempArg(p.PostStep, str, indent);
1513        getInitialValues().genTempArg(p.PostStep, str, indent);
1514    }
1515
1516    /**
1517     * Generate temp declarations for the sampling of spatialDistribution blocks.
1518     */
1519    public void FSpatialDistExp.genSampleVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1520        p.printVarDecls(getIn0(), str, indent);
1521        p.printVarDecls(getIn1(), str, indent);
1522        p.printVarDecls(getX(), str, indent);
1523        p.printVarDecls(getPositiveVelocity(), str, indent);
1524    }
1525
1526    /**
1527     * Generate the sampling of spatialDistribution blocks.
1528     */
1529    public void FSpatialDistExp.genSample_C(CodePrinter p, CodeStream str, String indent) {
1530//        int jmi_spatialdist_record_sample(jmi_t *jmi, int index, jmi_real_t in0,
1531//              jmi_real_t in1, jmi_real_t x, jmi_boolean positiveVelocity);
1532       
1533        p.printPreSteps(getIn0(), str, indent);
1534        p.printPreSteps(getIn1(), str, indent);
1535        p.printPreSteps(getX(), str, indent);
1536        p.printPreSteps(getPositiveVelocity(), str, indent);
1537           
1538        str.format("%sjmi_spatialdist_record_sample(jmi, %d, ", indent, mySpatialDistIndex());
1539        p.print(getIn0(), str, indent);
1540        str.print(", ");
1541        p.print(getIn1(), str, indent);
1542        str.print(", ");
1543        p.print(getX(), str, indent);
1544        str.print(", ");
1545        p.print(getPositiveVelocity(), str, indent);
1546        str.println(");");
1547       
1548        p.printPostSteps(getIn0(), str, indent);
1549        p.printPostSteps(getIn1(), str, indent);
1550        p.printPostSteps(getX(), str, indent);
1551        p.printPostSteps(getPositiveVelocity(), str, indent);
1552    }
1553
1554    @Override
1555    public void FSpatialDistExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1556        p.printVarDecls(getIn0(), str, indent);
1557        p.printVarDecls(getIn1(), str, indent);
1558        p.printVarDecls(getX(), str, indent);
1559        p.printVarDecls(getPositiveVelocity(), str, indent);
1560    }
1561
1562    @Override
1563    public void FSpatialDistExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1564        p.printPreSteps(getIn0(), str, indent);
1565        p.printPreSteps(getIn1(), str, indent);
1566        p.printPreSteps(getX(), str, indent);
1567        p.printPreSteps(getPositiveVelocity(), str, indent);
1568        if (!functionCallIsExp()) {// printed later if part of expression
1569            p.print(this, str, indent);
1570        }
1571    }
1572
1573    @Override
1574    public void FSpatialDistExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1575//        int jmi_spatialdist_evaluate(jmi_t *jmi, int index, jmi_real_t *out0,
1576//            jmi_real_t *out1, jmi_real_t in0, jmi_real_t in1, jmi_real_t x,
1577//            jmi_boolean positiveVelocity);
1578       
1579        boolean exp = functionCallIsExp();
1580        if (!exp) {
1581            str.print(indent);
1582        }
1583        str.format("jmi_spatialdist_evaluate(jmi, %d, ", mySpatialDistIndex());
1584        if (exp) {
1585            str.print("NULL, NULL");
1586        } else {
1587            prettyPrintCallOutputs_C(p, str, indent, 2, "");
1588        }
1589        str.print(", ");
1590        p.print(getIn0(), str, indent);
1591        str.print(", ");
1592        p.print(getIn1(), str, indent);
1593        str.print(", ");
1594        p.print(getX(), str, indent);
1595        str.print(", ");
1596        p.print(getPositiveVelocity(), str, indent);
1597        str.print(")");
1598       
1599        if (!exp) {
1600            str.println(";");
1601        }
1602    }
1603
1604    @Override
1605    public void FSpatialDistExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1606        p.printPostSteps(getIn0(), str, indent);
1607        p.printPostSteps(getIn1(), str, indent);
1608        p.printPostSteps(getX(), str, indent);
1609        p.printPostSteps(getPositiveVelocity(), str, indent);
1610    }
1611
1612    @Override
1613    public void FSpatialDistIndicator.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1614        if (!p.inInitialSystem()) {
1615            p.printVarDecls(getX(), str, indent);
1616            p.printVarDecls(getPositiveVelocity(), str, indent);
1617        }
1618    }
1619
1620    @Override
1621    public void FSpatialDistIndicator.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1622        if (!p.inInitialSystem()) {
1623            p.printPreSteps(getX(), str, indent);
1624            p.printPreSteps(getPositiveVelocity(), str, indent);
1625        }
1626    }
1627
1628    @Override
1629    public void FSpatialDistIndicator.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1630        if (!p.inInitialSystem()) {
1631            p.printPostSteps(getX(), str, indent);
1632            p.printPostSteps(getPositiveVelocity(), str, indent);
1633        }
1634    }
1635
1636
1637    @Override
1638    public void FSpatialDistIndicator.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1639        if (p.inInitialSystem()) {
1640            str.format("JMI_DELAY_INITIAL_EVENT_RES");
1641        } else {
1642            str.format("jmi_spatialdist_event_indicator_exp(jmi, %d, ", mySpatialDistIndex());
1643            p.print(getX(), str, indent);
1644            str.print(", ");
1645            p.print(getPositiveVelocity(), str, indent);
1646            str.print(")");
1647        }
1648    }
1649    syn nta FExp FSpatialDistIndicator.getX()                = mySpatialDistExp().getX().copySymbolic();
1650    syn nta FExp FSpatialDistIndicator.getPositiveVelocity() = mySpatialDistExp().getPositiveVelocity().copySymbolic();
1651
1652    /*=========================================================================
1653     * Subscripted Expression
1654     ========================================================================*/
1655   
1656    @Override
1657    public void FSubscriptedExp.genVarDecls_C(CodePrinter p, CodeStream str, String indent) {
1658        super.genVarDecls_C(p, str, indent);
1659        if (needsTemp()) {
1660            p.printIODecl(getFExp(), str, indent);
1661        }
1662    }
1663
1664    @Override
1665    public void FSubscriptedExp.genTempVars_C(CodePrinter p, CodeStream str, String indent) {
1666        super.genTempVars_C(p, str, indent);
1667        if (needsTemp()) {
1668            p.printIOPre(getFExp(), str, indent);
1669        }
1670    }
1671
1672    @Override
1673    public void FSubscriptedExp.prettyPrint_C(CodePrinter p, CodeStream str, String indent) {
1674        prettyPrint_C(p.ExecStep, str, indent);
1675    }
1676
1677    @Override
1678    public void FSubscriptedExp.genTempFree_C(CodePrinter p, CodeStream str, String indent) {
1679        super.genTempFree_C(p, str, indent);
1680        if (needsTemp() && isAssignedTo()) {
1681            p.printWriteBackAssignment(str, indent, this, null);
1682        }
1683    }
1684
1685    public void FSubscriptedExp.prettyPrint_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent) {
1686        if (needsTemp()) {
1687            str.print(getFArraySubscripts().genFunctionArrayUse_C(p.codePrinter(), p.name(getFExp()), C_ARRAY_VALUE));
1688        } else {
1689            getFExp().first().genDirectSubscriptedUse_C(p, str, indent, getFArraySubscripts());
1690        }
1691    }
1692
1693    syn FAccessExp FExp.first() = null;
1694    eq FArray.first()          = getFExp(0).first();
1695    eq FAccessExp.first()       = this;
1696   
1697    syn lazy boolean FSubscriptedExp.needsTemp() = (getFExp().consecutiveArray(null) == null);
1698   
1699    syn FAbstractVariable FExp.consecutiveArray(FAbstractVariable last) = null;
1700    eq FArray.consecutiveArray(FAbstractVariable last) {
1701        for (FExp exp : getFExps()) {
1702            last = exp.consecutiveArray(last);
1703            if (last == null) {
1704                break;
1705            }
1706        }
1707        return last;
1708    }
1709    eq FAccessExp.consecutiveArray(FAbstractVariable last) {
1710        if (last == null || last.isConsecutiveInZ(myFV())) {
1711            return myFV();
1712        }
1713        return null;
1714    }
1715
1716    public void FAccessExp.genDirectSubscriptedUse_C(CodePrinter.ExecuteCodePrinter p, CodeStream str, String indent,
1717            FArraySubscripts fas) {
1718        str.print("(&");
1719        p.print(this, str, indent);
1720        str.print(")");
1721        str.print("[(int)(");
1722        Size s = fas.mySize();
1723        for (int i = fas.numSubscript() - 1; i >= 0; i--) {
1724            fas.subscript(i).prettyPrint(p.codePrinter(), str, indent);
1725            str.print(" - 1");
1726            if (i > 0) {
1727                str.print(" + ");
1728                str.print(s.get(i));
1729                str.print(" * (");
1730            }
1731        }
1732        for (int i = 0; i < fas.numSubscript() - 1; i++) {
1733            str.print(")");
1734        }
1735        str.print(")]");
1736    }
1737}
Note: See TracBrowser for help on using the repository browser.