package CodegenJava

import interface SimCodeTV;


template translateModel(SimCode simCode)
 "Generates Java code and Makefile for compiling and running a simulation of a
  Modelica model."
::=
match simCode
case SIMCODE(modelInfo=modelInfo as MODELINFO(__)) then
  let()= textFile(simulationFile(simCode), '<%fileNamePrefix%>.java')
  let()= textFile(simulationFunctionsFile(fileNamePrefix, modelInfo.functions, literals), '<%fileNamePrefix%>_functions.java')
  let()= textFile(simulationMakefile(simCode), '<%fileNamePrefix%>.makefile')
  if simulationSettingsOpt then //tests the Option<> for SOME()
     let()= textFile(simulationInitFile(simCode), '<%fileNamePrefix%>_init.txt')
     "" //empty result for true case
  //else "" //the else is automatically empty, too
  //this top-level template always returns an empty result
  //since generated texts are written to files directly
end translateModel;

template translateFunctions(FunctionCode functionCode)
 "Generates Java code and Makefile for compiling and calling Modelica and
  MetaModelica functions."
::=
match functionCode

case FUNCTIONCODE(__) then
  let filePrefix = name
  //let()= textFile(functionsFile(filePrefix, mainFunction, functions, literals), '<%filePrefix%>.java')
  //let _= (if mainFunction then textFile(functionsMakefile(functionCode), '<%filePrefix%>.makefile'))
  "" // Return empty result since result written to files directly
end translateFunctions;

template simulationFile(SimCode simCode)
 "Generates code for main Java file for simulation target."
::=
match simCode
case SIMCODE(__) then
  <<

  <%simulationFileHeader(simCode)%>
  <%modelClassName(simCode)%>
  <%globalData(modelInfo)%>
  <%mainFunction(simCode)%>
  <%functionModelConstructor(simCode)%>
  <%functionInitializeDataStruc()%>
  <%functionDeInitializeDataStruc(extObjInfo)%>
  <%functionInput(modelInfo)%>
  <%functionOutput(modelInfo)%>
  <%functionDaeRes()%>
  <%functionStoreDelayed(delayedExps)%>
  <%/*functionODE(odeEquations,modelInfo)*/%>

  >>
end simulationFile;

template simulationFileHeader(SimCode simCode)
 "Generates header part of simulation file."
::=
match simCode
case SIMCODE(modelInfo=MODELINFO(__), extObjInfo=EXTOBJINFO(__)) then
  <<
  package simCodeJava; // solver package name

  import java.io.IOException;
  import java.math.*;

  >>
end simulationFileHeader;

template modelClassName(SimCode simCode)
 "Generates model class name of simulation file."
::=
match simCode
case SIMCODE(modelInfo=MODELINFO(__), extObjInfo=EXTOBJINFO(__)) then
  <<
  // Simulation code for <%dotPath(modelInfo.name)%> generated by the OpenModelica Compiler <%getVersionNr()%>.
  @SuppressWarnings("unused")
  public class <%dotPath(modelInfo.name)%> extends SuperModel // name of the given model
  {
  >>
end modelClassName;

template dotPath(Path path)
 "Generates paths with components separated by dots."
::=
  match path
  case QUALIFIED(__)      then '<%name%>.<%dotPath(path)%>'

  case IDENT(__)          then name
  case FULLYQUALIFIED(__) then dotPath(path)
end dotPath;

template globalData(ModelInfo modelInfo)
 "Generates global data in simulation file."
::=
match modelInfo
case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
  <<

  <%\t%>private static DATA localData = new DATA();
  <%\t%>//final time localData.timeValue = 0;

  <%\t%>//final double $P$old$Ptime = localData.oldTime;
  <%\t%>//final double $P$current_step_size = globalData.current_stepsize;

  <%\t%><%addGlobalInitialization(modelInfo)%>

  >>
end globalData;

template addGlobalInitialization(ModelInfo modelInfo)
 "Generates global data in simulation file."
::=
match modelInfo
case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
  <<

  <%vars.stateVars |> var =>
    globalDataInitialization(var, "states")
  ;separator="\n"%>
  <%vars.derivativeVars |> var =>
    globalDataInitialization(var, "statesDerivatives")
  ;separator="\n"%>
  <%vars.algVars |> var =>
    globalDataInitialization(var, "algebraics")
  ;separator="\n"%>
  <%vars.paramVars |> var =>
    globalDataInitialization(var, "parameters")
  ;separator="\n"%>

  >>
end addGlobalInitialization;

template addGlobalDefinition(ModelInfo modelInfo)
 "Generates global data in simulation file."
::=
match modelInfo
case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
  <<

  <%vars.stateVars |> var =>
    globalDataVarDefine(var, "states")
  ;separator="\n"%>
  <%vars.derivativeVars |> var =>
    globalDataVarDefine(var, "statesDerivatives")
  ;separator="\n"%>
  <%vars.algVars |> var =>
    globalDataVarDefine(var, "algebraics")
  ;separator="\n"%>
  <%vars.paramVars |> var =>
    globalDataVarDefine(var, "parameters")
  ;separator="\n"%>

  >>
end addGlobalDefinition;

template addVarReverseDefinition(ModelInfo modelInfo)
 "Generates global data in simulation file."
::=
match modelInfo
case MODELINFO(varInfo=VARINFO(__), vars=SIMVARS(__)) then
  <<

  <%vars.stateVars |> var =>
    globalDataVarReverseDefine(var, "states")
  ;separator="\n"%>
  <%vars.derivativeVars |> var =>
    globalDataVarReverseDefine(var, "statesDerivatives")
  ;separator="\n"%>
  <%vars.algVars |> var =>
    globalDataVarReverseDefine(var, "algebraics")
  ;separator="\n"%>
  <%vars.paramVars |> var =>
    globalDataVarReverseDefine(var, "parameters")
  ;separator="\n"%>

  >>
end addVarReverseDefinition;

template globalDataInitialization(SimVar simVar, String arrayName)
 "Generates a define statement for a variable in the global data section."
::=
  match simVar
  case SIMVAR(__) then
  <<
  <%\t%>private double <%cref(name)%>;
  >>
  end match
end globalDataInitialization;

template globalDataVarDefine(SimVar simVar, String arrayName)
 "Generates a define statement for a variable in the global data section."
::=
match simVar
case SIMVAR(__) then
    <<
    <%cref(name)%> = localData.<%arrayName%>[<%index%>];
    >>
  end match
end globalDataVarDefine;

template globalDataVarReverseDefine(SimVar simVar, String arrayName)
 "Generates a assignment statement for a variable in the global data section."
::=
match simVar
case SIMVAR(__) then
    <<
    localData.<%arrayName%>[<%index%>] = <%cref(name)%>;
    >>
  end match
end globalDataVarReverseDefine;

template mainFunction(SimCode simCode) ::=
match simCode
case SIMCODE(modelInfo = MODELINFO(__)) then
  <<
  <%\t%>static SuperModel temp = new <%dotPath(modelInfo.name)%>();

  <%\t%>public static void main(String[] args) throws IOException
  <%\t%>{
  <%\t%><%\t%>JavaSolver.solver_main(temp, localData);
  <%\t%>}
  >>
end mainFunction;

template functionModelConstructor(SimCode simCode) ::=
match simCode
case SIMCODE(modelInfo = MODELINFO(__)) then
  <<
  <%\t%>public <%dotPath(modelInfo.name)%>()
  <%\t%>{
  <%\t%><%\t%>//localData = data;

  <%\t%><%\t%>//$Px = localData.states[0];
  <%\t%>//$P$DER$Px = localData.statesDerivatives[0];
  <%\t%>}

  >>
end functionModelConstructor;

template functionInitializeDataStruc()
 "Generates function in simulation file."
::=
  <<
    // Used to initialize the data structure
    /*
    public DATA initializeDataStruc(DATA_FLAGS flags)
    {
      DATA returnData = new DATA(fortran_integer, fortran_integer, fortran_integer, long, long,
        fortran_integer, long, long, long, long, long);

      return returnData;
    }
    */

  >>
end functionInitializeDataStruc;

template functionDeInitializeDataStruc(ExtObjInfo extObjInfo)
 "Generates function in simulation file."
::=
match extObjInfo
case EXTOBJINFO(__) then
  <<
    protected void finalize ()
    {
      System.out.println("memsucker %d destroyed...\n");
    }

    // used to deinitialize the data structure
    public void deInitializeDataStruc(DATA data, DATA_FLAGS flags)
    {
      /* In java, memory deallocation is automatically handled. so no need to free the memory explicitly. */
    }

  >>
end functionDeInitializeDataStruc;

template functionInput(ModelInfo modelInfo)
 "Generates function in simulation file."
::=
match modelInfo
case MODELINFO(vars=SIMVARS(__)) then
  <<
    public int input_function()
    {
      <%vars.inputVars |> SIMVAR(__) hasindex i0 =>
      '<%cref(name)%> = localData.inputVars[<%i0%>];'
      ;separator="\n"%>
      return 0;
    }

  >>
end functionInput;

template functionOutput(ModelInfo modelInfo)
 "Generates function in simulation file."
::=
match modelInfo
case MODELINFO(vars=SIMVARS(__)) then
  <<
    public int output_function()
    {
      <%vars.outputVars |> SIMVAR(__) hasindex i0 =>
      'localData.outputVars[<%i0%>] = <%cref(name)%>;'
      ;separator="\n"%>
      return 0;
    }

  >>
end functionOutput;

template functionDaeRes()
  "Generates function in simulation file."
::=
  <<
      @SuppressWarnings("null") // To avoid  "null" warnings in Java
    public int functionDAE_res(double t, double[] x, double[] xd, double[] delta, double ires, double rpar, double ipar)
    {
      int i;
      double[] temp_xd = null;
      double[] statesBackup;
      double[] statesDerivativesBackup;
      double timeBackup;

      statesBackup = localData.states;
      statesDerivativesBackup = localData.statesDerivatives;
      timeBackup = localData.timeValue;
      localData.states = x;

      for (i = 0; i < localData.nStates; i++) {
        temp_xd[i] = localData.statesDerivatives[i];
      }

      localData.statesDerivatives = temp_xd;
      localData.timeValue = t;

      functionODE();

      /* get the difference between the temp_xd(=localData->statesDerivatives)
        and xd(=statesDerivativesBackup) */
      for (i = 0; i < localData.nStates; i++) {
        delta[i] = localData.statesDerivatives[i] - statesDerivativesBackup[i];
      }

      localData.states = statesBackup;
      localData.statesDerivatives = statesDerivativesBackup;
      localData.timeValue = timeBackup;

      return 0;
    }

  >>
end functionDaeRes;

template functionStoreDelayed(DelayedExpression delayed)
  "Generates function in simulation file."
::=
  let &varDecls = buffer "" /*BUFD*/
  let storePart = (match delayed case DELAYED_EXPRESSIONS(__) then (delayedExps |> (id, (e,_,_)) =>
      let &preExp = buffer "" /*BUFD*/
      let eRes = daeExp(e, contextSimulationNonDiscrete,
                      &preExp /*BUFC*/, &varDecls /*BUFC*/)
      <<
      <%preExp%>
      storeDelayedExpression(<%id%>, <%eRes%>);
      >>
    ))
  <<
    /*
     * extern int const numDelayExpressionIndex = <%match delayed case DELAYED_EXPRESSIONS(__) then maxDelayedIndex%>;
    */
    public int function_storeDelayed()
    {
      <%varDecls%>

      <%storePart%>

      return 0;
    }

  >>
end functionStoreDelayed;

template functionODE(list<SimEqSystem> derivativEquations, ModelInfo modelInfo)
 "Generates function in simulation file."
::=
  let &varDecls = buffer "" /*BUFD*/
  let odeEquations = (derivativEquations |> eq =>
      equation_(eq, contextSimulationNonDiscrete, &varDecls /*BUFC*/)
    ;separator="\n")
  <<
      public int functionODE(DATA localData)
      {
        <%addGlobalDefinition(modelInfo)%>

      <%varDecls%>

      <%odeEquations%>

      <%addVarReverseDefinition(modelInfo)%>

        return 0;
      }

  }// end main class

  >>
end functionODE;









template equation_(SimEqSystem eq, Context context, Text &varDecls /*BUFP*/)
 "Generates an equation.
  This template should not be used for a SES_RESIDUAL.
  Residual equations are handled differently."
::=
  match eq
  case e as SES_SIMPLE_ASSIGN(__)
    then equationSimpleAssign(e, context, &varDecls /*BUFD*/)
  else
    "" //NOT IMPLEMENTED EQUATION
end equation_;

template equationSimpleAssign(SimEqSystem eq, Context context,
                              Text &varDecls /*BUFP*/)
 "Generates an equation that is just a simple assignment."
::=
match eq
case SES_SIMPLE_ASSIGN(__) then
  let &preExp = buffer "" /*BUFD*/
  let expPart = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
  <<
  <%preExp%>
  <%cref(cref)%> = <%expPart%>;
  >>
end equationSimpleAssign;

template daeExp(Exp exp, Context context, Text &preExp /*BUFP*/, Text &varDecls /*BUFP*/)
 "Generates code for an expression."
::=
  match exp
  case e as ICONST(__)         then integer
  case e as RCONST(__)         then real
  case e as BCONST(__)         then if bool then "(1)" else "(0)"
  case e as CREF(__)           then cref(componentRef)
  case e as BINARY(__)         then daeExpBinary(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  case e as UNARY(__)          then daeExpUnary(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  case e as LBINARY(__)        then daeExpLbinary(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  case e as LUNARY(__)         then daeExpLunary(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  case e as RELATION(__)       then daeExpRelation(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  case e as IFEXP(__)          then daeExpIf(e, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
  //case e as CALL(__)         then daeExpCall(e, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
  else "UNKNOWN_EXP"
end daeExp;

template daeExpBinary(Exp exp, Context context, Text &preExp /*BUFP*/,
                      Text &varDecls /*BUFP*/)
 "Generates code for a binary expression."
::=

match exp
case BINARY(__) then
  let e1 = daeExp(exp1, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  let e2 = daeExp(exp2, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  match operator
  case ADD(__) then '(<%e1%> + <%e2%>)'
  case SUB(__) then '(<%e1%> - <%e2%>)'
  case MUL(__) then '(<%e1%> * <%e2%>)'
  case DIV(__) then '(<%e1%> / <%e2%>)'
  case POW(__) then 'Math.pow(<%e1%>, <%e2%>)'
  case UMINUS(__) then daeExpUnary(exp, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  else "daeExpBinary:ERR"
end daeExpBinary;

template daeExpUnary(Exp exp, Context context, Text &preExp /*BUFP*/,
                     Text &varDecls /*BUFP*/)
 "Generates code for a unary expression."
::=
match exp
case UNARY(__) then
  let e = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  match operator
  case UMINUS(__)     then '(-<%e%>)'
  //case UPLUS(__)      then '(<%e%>)' alachew
  else "daeExpUnary:ERR"
end daeExpUnary;

template daeExpLbinary(Exp exp, Context context, Text &preExp /*BUFP*/,
                       Text &varDecls /*BUFP*/)
 "Generates code for a logical binary expression."
::=
match exp
case LBINARY(__) then
  let e1 = daeExp(exp1, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  let e2 = daeExp(exp2, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  match operator
  case AND(__) then '(<%e1%> && <%e2%>)'
  case OR(__)  then '(<%e1%> || <%e2%>)'
  else "daeExpLbinary:ERR"
end daeExpLbinary;


template daeExpLunary(Exp exp, Context context, Text &preExp /*BUFP*/,
                      Text &varDecls /*BUFP*/)
 "Generates code for a logical unary expression."
::=
match exp
case LUNARY(__) then
  let e = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
  match operator
  case NOT(__) then '(!<%e%>)'
end daeExpLunary;

template daeExpRelation(Exp exp, Context context, Text &preExp /*BUFP*/,
                        Text &varDecls /*BUFP*/)
 "Generates code for a relation expression."
::=
match exp
case rel as RELATION(__) then
    let e1 = daeExp(rel.exp1, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    let e2 = daeExp(rel.exp2, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    match rel.operator
    case LESS(ty = T_BOOL(__))        then '(!<%e1%> && <%e2%>)'
    case LESS(ty = T_STRING(__))      then "# string comparison not supported\n"
    case LESS(ty = T_INTEGER(__))         then '(<%e1%> < <%e2%>)'
    case LESS(ty = T_REAL(__))        then '(<%e1%> < <%e2%>)'
    case GREATER(ty = T_BOOL(__))     then '(<%e1%> && !<%e2%>)'
    case GREATER(ty = T_STRING(__))   then "# string comparison not supported\n"
    case GREATER(ty = T_INTEGER(__))      then '(<%e1%> > <%e2%>)'
    case GREATER(ty = T_REAL(__))     then '(<%e1%> > <%e2%>)'
    case LESSEQ(ty = T_BOOL(__))      then '(!<%e1%> || <%e2%>)'
    case LESSEQ(ty = T_STRING(__))    then "# string comparison not supported\n"
    case LESSEQ(ty = T_INTEGER(__))       then '(<%e1%> <= <%e2%>)'
    case LESSEQ(ty = T_REAL(__))      then '(<%e1%> <= <%e2%>)'
    case GREATEREQ(ty = T_BOOL(__))   then '(<%e1%> || !<%e2%>)'
    case GREATEREQ(ty = T_STRING(__)) then "# string comparison not supported\n"
    case GREATEREQ(ty = T_INTEGER(__))    then '(<%e1%> >= <%e2%>)'
    case GREATEREQ(ty = T_REAL(__))   then '(<%e1%> >= <%e2%>)'
    case EQUAL(ty = T_BOOL(__))       then '((!<%e1%> && !<%e2%>) || (<%e1%> && <%e2%>))'
    case EQUAL(ty = T_STRING(__))     then '(<%e1%>.equals(<%e2%>))'
    case EQUAL(ty = T_INTEGER(__))        then '(<%e1%> == <%e2%>)'
    case EQUAL(ty = T_REAL(__))       then '(<%e1%> == <%e2%>)'
    case EQUAL(ty = T_ENUMERATION(__))then '(<%e1%> == <%e2%>)'
    case NEQUAL(ty = T_BOOL(__))      then '((!<%e1%> && <%e2%>) || (<%e1%> && !<%e2%>))'
    case NEQUAL(ty = T_STRING(__))    then '(!<%e1%>.equals(<%e2%>))'
    case NEQUAL(ty = T_INTEGER(__))       then '(<%e1%> != <%e2%>)'
    case NEQUAL(ty = T_REAL(__))      then '(<%e1%> != <%e2%>)'
    else "daeExpRelation:ERR"
end daeExpRelation;



/* IF and CALL start */

template daeExpIf(Exp exp, Context context, Text &preExp /*BUFP*/,
                  Text &varDecls /*BUFP*/)
 "Generates code for an if expression."
::=
match exp
case IFEXP(__) then
  let condExp = daeExp(expCond, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
  let &preExpThen = buffer "" /*BUFD*/
  let eThen = daeExp(expThen, context, &preExpThen /*BUFC*/, &varDecls /*BUFD*/)
  let &preExpElse = buffer "" /*BUFD*/
  let eElse = daeExp(expElse, context, &preExpElse /*BUFC*/, &varDecls /*BUFD*/)
  let shortIfExp = if preExpThen then "" else if preExpElse then "" else "x"
  (if shortIfExp
    then
      // Safe to do if eThen and eElse don't emit pre-expressions
      '(<%condExp%>?<%eThen%>:<%eElse%>)'
    else
      let condVar = tempDecl("modelica_boolean", &varDecls /*BUFD*/)
      let resVarType = expTypeFromExpArrayIf(expThen)
      let resVar = tempDecl(resVarType, &varDecls /*BUFD*/)
      let &preExp +=
      <<
      <%condVar%> = (modelica_boolean)<%condExp%>;
      if (<%condVar%>) {
        <%preExpThen%>
        <%resVar%> = (<%resVarType%>)<%eThen%>;
      } else {
        <%preExpElse%>
        <%resVar%> = (<%resVarType%>)<%eElse%>;
      }<%\n%>
      >>
      resVar)
end daeExpIf;

// template daeExpCall(Exp call, Context context, Text &preExp /*BUFP*/,
                    // Text &varDecls /*BUFP*/)
 // "Generates code for a function call."
// ::=
  // match call
  //special builtins
  // case CALL(path=IDENT(name="DIVISION"),
            // expLst={e1, e2, DAE.SCONST(string=string)}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // let var3 = Util.escapeModelicaStringToCString(string)
    // 'DIVISION(<%var1%>,<%var2%>,"<%var3%>")'

  // case CALL(attr=CALL_ATTR(ty=ty),
            // path=IDENT(name="DIVISION_ARRAY_SCALAR"),
            // expLst={e1, e2, DAE.SCONST(string=string)}) then
    // let type = match ty case T_ARRAY(ty=T_INTEGER(__)) then "integer_array"
                        // case T_ARRAY(ty=T_ENUMERATION(__)) then "integer_array"
                        // else "real_array"
    // let var = tempDecl(type, &varDecls)
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // let var3 = Util.escapeModelicaStringToCString(string)
    // let &preExp += 'division_alloc_<%type%>_scalar(&<%var1%>, <%var2%>, &<%var%>,"<%var3%>");<%\n%>'
    // '<%var%>'

  // case CALL(path=IDENT(name="der"), expLst={arg as CREF(__)}) then
    // '$P$DER<%cref(arg.componentRef)%>'

  // case CALL(
            // path=IDENT(name="max"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'std::max(<%var1%>,<%var2%>)'

  // case CALL(ty = T_INTEGER(),
            // path=IDENT(name="min"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'std::min((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)'

  // case CALL(ty = T_ENUMERATION(__),
            // path=IDENT(name="min"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'std::min((modelica_integer)<%var1%>,(modelica_integer)<%var2%>)'

  // case CALL( ty = T_REAL(),
            // path=IDENT(name="min"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'std::min(<%var1%>,<%var2%>)'

  // case CALL(
            // path=IDENT(name="abs"), expLst={e1}, ty = T_INTEGER()) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // 'std::abs(<%var1%>)'

  // case CALL(
            // path=IDENT(name="abs"), expLst={e1}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // 'fabs(<%var1%>)'

   // sqrt
  // case CALL(
            // path=IDENT(name="sqrt"),
            // expLst={e1}) then
   // relation = DAE.LBINARY(e1,DAE.GREATEREQ(T_REAL()),DAE.RCONST(0))
   // string = DAE.SCONST('Model error: Argument of sqrt should  >= 0')
    //let retPre = assertCommon(relation,s, context, &varDecls)
    // let retPre = assertCommon(createAssertforSqrt(e1),createDAEString("Model error: Argument of sqrt should be >= 0"), context, &varDecls, dummyInfo)
    // let argStr = (expLst |> exp => '<%daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)%>' ;separator=", ")
    // let funName = '<%underscorePath(path)%>'
    // let retType = '<%funName%>_rettype'
    // let &preExp += '<%retPre%>'
    // let retVar = tempDecl(retType, &varDecls /*BUFD*/)
    // let &preExp += '<%retVar%> = <%daeExpCallBuiltinPrefix(builtin)%><%funName%>(<%argStr%>);<%\n%>'
    // if builtin then '<%retVar%>' else '<%retVar%>.<%retType%>_1'

  // case CALL(
            // path=IDENT(name="div"), expLst={e1,e2}, ty = T_INTEGER()) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'ldiv(<%var1%>,<%var2%>).quot'

  // case CALL(
            // path=IDENT(name="div"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'trunc(<%var1%>/<%var2%>)'

  // case CALL(
            // path=IDENT(name="mod"), expLst={e1,e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // 'modelica_mod_<%expTypeShort(ty)%>(<%var1%>,<%var2%>)'


  //some expression type Arrays are missed


  // case CALL(
            // path=IDENT(name="rem"),
            // expLst={e1, e2}) then
    // let var1 = daeExp(e1, context, &preExp, &varDecls)
    // let var2 = daeExp(e2, context, &preExp, &varDecls)
    // let typeStr = expTypeFromExpShort(e1)
    // 'modelica_rem_<%typeStr%>(<%var1%>,<%var2%>)'

  // case CALL(
            // path=IDENT(name="String"),
            // expLst={s, format}) then
    // let tvar = tempDecl("modelica_string", &varDecls /*BUFD*/)
    // let sExp = daeExp(s, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let formatExp = daeExp(format, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let typeStr = expTypeFromExpModelica(s)
    // let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string_format(<%sExp%>, <%formatExp%>);<%\n%>'
    // '<%tvar%>'


  // case CALL(
            // path=IDENT(name="String"),
            // expLst={s, minlen, leftjust}) then
    // let tvar = tempDecl("modelica_string", &varDecls /*BUFD*/)
    // let sExp = daeExp(s, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let minlenExp = daeExp(minlen, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let leftjustExp = daeExp(leftjust, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let typeStr = expTypeFromExpModelica(s)
    // let &preExp += '<%tvar%> = <%typeStr%>_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>);<%\n%>'
    // '<%tvar%>'

  // case CALL(
            // path=IDENT(name="String"),
            // expLst={s, minlen, leftjust, signdig}) then
    // let tvar = tempDecl("modelica_string", &varDecls /*BUFD*/)
    // let sExp = daeExp(s, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let minlenExp = daeExp(minlen, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let leftjustExp = daeExp(leftjust, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let signdigExp = daeExp(signdig, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let &preExp += '<%tvar%> = modelica_real_to_modelica_string(<%sExp%>, <%minlenExp%>, <%leftjustExp%>, <%signdigExp%>);<%\n%>'
    // '<%tvar%>'

  // case CALL(
            // path=IDENT(name="delay"),
            // expLst={ICONST(integer=index), e, d, delayMax}) then
    // let tvar = tempDecl("modelica_real", &varDecls /*BUFD*/)
    // let var1 = daeExp(e, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let var2 = daeExp(d, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let var3 = daeExp(delayMax, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let &preExp += '<%tvar%> = delayImpl(<%index%>, <%var1%>, time, <%var2%>, <%var3%>);<%\n%>'
    // '<%tvar%>'

  // case CALL(
            // path=IDENT(name="integer"),
            // expLst={toBeCasted}) then
    // let castedVar = daeExp(toBeCasted, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // '((modelica_integer)<%castedVar%>)'

  // case CALL(
            // path=IDENT(name="Integer"),
            // expLst={toBeCasted}) then
    // let castedVar = daeExp(toBeCasted, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // '((modelica_integer)<%castedVar%>)'

  // case CALL(path=IDENT(name="clock"), expLst={}) then
    // 'mmc_clock()'

  // case CALL(
            // path=IDENT(name="noEvent"),
            // expLst={e1}) then
    // daeExp(e1, context, &preExp, &varDecls)

  // case CALL(
            // path=IDENT(name="anyString"),
            // expLst={e1}) then
    // 'mmc_anyString(<%daeExp(e1, context, &preExp, &varDecls)%>)'

  // case CALL(
            // path=IDENT(name="mmc_get_field"),
            // expLst={s1, ICONST(integer=i)}) then
    // let tvar = tempDecl("modelica_metatype", &varDecls /*BUFD*/)
    // let expPart = daeExp(s1, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)
    // let &preExp += '<%tvar%> = MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%expPart%>), <%i%>));<%\n%>'
    // '<%tvar%>'

  // case CALL( path=IDENT(name = "mmc_unbox_record"),
            // expLst={s1}, ty=ty) then
    // let argStr = daeExp(s1, context, &preExp, &varDecls)
    // unboxRecord(argStr, ty, &preExp, &varDecls)

  // case exp as CALL(__) then
    // let argStr = (expLst |> exp => '<%daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFD*/)%>' ;separator=", ")
    // let funName = '<%underscorePath(path)%>'
    // let retType = '<%funName%>_rettype'
    // let retVar = match exp
      // case CALL(ty=T_NORETCALL(__)) then ""
      // else tempDecl(retType, &varDecls)
    // let &preExp += if not builtin then match context case SIMULATION(__) then
      // <<
      // #ifdef _OMC_MEASURE_TIME
      // SIM_PROF_TICK_FN(<%funName%>_index);
      // #endif<%\n%>
      // >>
    // let &preExp += '<%if retVar then '<%retVar%> = '%><%daeExpCallBuiltinPrefix(builtin)%><%funName%>(<%argStr%>);<%\n%>'
    // let &preExp += if not builtin then match context case SIMULATION(__) then
      // <<
      // #ifdef _OMC_MEASURE_TIME
      // SIM_PROF_ACC_FN(<%funName%>_index);
      // #endif<%\n%>
      // >>
    // match exp
     //no return calls
      // case CALL(attr=CALL_ATTR(ty=T_NORETCALL(__))) then '/* NORETCALL */'
      //non tuple calls (single return value)
      // case CALL(attr=CALL_ATTR(tuple_=false)) then
        // if attr.builtin then '<%retVar%>' else '<%retVar%>.c1'
      //tuple calls (multiple return values)
      // else
        // '<%retVar%>'
// end daeExpCall;


template daeExpCallBuiltinPrefix(Boolean builtin)
 "Helper to daeExpCall."
::=
  match builtin
  case true  then ""
  case false then "_"
end daeExpCallBuiltinPrefix;

template algStatement(DAE.Statement stmt, Context context, Text &varDecls /*BUFP*/)
 "Generates an algorithm statement."
::=
  match stmt
  case s as STMT_ASSIGN(__)       then algStmtAssign(s, context, &varDecls /*BUFC*/)
  else "NOT IMPLEMENTED ALG STATEMENT"
end algStatement;


template algStmtAssign(DAE.Statement stmt, Context context, Text &varDecls /*BUFP*/)
 "Generates an assigment algorithm statement."
::=
  match stmt
  case STMT_ASSIGN(exp1=CREF(componentRef=WILD(__)), exp=e) then
    let &preExp = buffer "" /*BUFD*/
    let expPart = daeExp(e, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    <<
    <%preExp%>
    >>
  case STMT_ASSIGN(exp1=CREF(__)) then
    let &preExp = buffer "" /*BUFD*/
    let varPart = scalarLhsCref(exp1, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    let expPart = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    <<
    <%preExp%>
    <%varPart%> = <%expPart%>;
    >>
  case STMT_ASSIGN(__) then
    let &preExp = buffer "" /*BUFD*/
    let expPart1 = daeExp(exp1, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    let expPart2 = daeExp(exp, context, &preExp /*BUFC*/, &varDecls /*BUFC*/)
    <<
    <%preExp%>
    <%expPart1%> = <%expPart2%>;
    >>
end algStmtAssign;

template scalarLhsCref(Exp ecr, Context context, Text &preExp, Text &varDecls)
 "Generates the left hand side (for use on left hand side) of a component
  reference."
::=
  match ecr
  case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then
    '*((modelica_fnptr*)&_<%functionName(cr)%>)'
  case ecr as CREF(componentRef=CREF_IDENT(__)) then
    if crefNoSub(ecr.componentRef) then
      contextCref(ecr.componentRef, context)
    else
      daeExpCrefRhs(ecr, context, &preExp, &varDecls)
  case ecr as CREF(componentRef=CREF_QUAL(__)) then
    contextCref(ecr.componentRef, context)
  else
    "ONLY_IDENT_OR_QUAL_CREF_SUPPORTED_SLHS"
end scalarLhsCref;

template functionName(ComponentRef cr)
::=
  match cr
  case CREF_IDENT(__) then
    System.stringReplace(ident, "_", "__")
  case CREF_QUAL(__) then
    '<%System.stringReplace(ident, "_", "__")%>_<%functionName(componentRef)%>'
end functionName;

template contextCref(ComponentRef cr, Context context)
  "Generates code for a component reference depending on which context we're in."
::=
  match context
  case FUNCTION_CONTEXT(__) then crefStr(cr)
  else cref(cr)
end contextCref;

template cref(ComponentRef cr)
 "Generates Java equivalent name for component reference."
::=
  match cr
  case CREF_IDENT(ident = "xloc") then crefStr(cr)
  case CREF_IDENT(ident = "time") then "time"
  else "$P" + crefToCStr(cr)
end cref;

template daeExpCrefRhs(Exp exp, Context context, Text &preExp /*BUFP*/,
                       Text &varDecls /*BUFP*/)
 "Generates code for a component reference."
::=
  match exp
  /*case CREF(componentRef=cr, ty=T_ENUMERATION(__)) then
    getEnumIndexfromCref(cr)*/
  case cref as CREF(componentRef=cr, ty=ty) then
     let cast = match ty case T_INTEGER(__) then "(int)" //else ""
      '<%cast%><%cref(cr)%>'

end daeExpCrefRhs;

template crefStr(ComponentRef cr)
 "Generates the name of a variable for variable name array."
::=
  match cr
  case CREF_IDENT(__) then '<%ident%><%subscriptsStr(subscriptLst)%>'
  case CREF_QUAL(ident = "$DER") then 'der(<%crefStr(componentRef)%>)'
  case CREF_QUAL(__) then '<%ident%><%subscriptsStr(subscriptLst)%>.<%crefStr(componentRef)%>'
  else "CREF_NOT_IDENT_OR_QUAL"
end crefStr;

template subscriptsStr(list<Subscript> subscripts)
 "Generares subscript part of the name."
::=
  if subscripts then
    '[<%subscripts |> s => subscriptStr(s) ;separator=","%>]'
end subscriptsStr;

template subscriptStr(Subscript subscript)
 "Generates a single subscript.
  Only works for constant integer indicies."

::=
  let &preExp = buffer ""
  let &varDecls = buffer ""
  match subscript
  case INDEX(__)
  case SLICE(__) then daeExp(exp, contextFunction, &preExp, &varDecls)
  case WHOLEDIM(__) then "WHOLEDIM"
  else "UNKNOWN_SUBSCRIPT"
end subscriptStr;

template crefToCStr(ComponentRef cr)
 "Helper function to cref."
::=
  match cr
  case CREF_IDENT(__) then '<%ident%><%subscriptsToCStr(subscriptLst)%>'
  case CREF_QUAL(__) then '<%ident%><%subscriptsToCStr(subscriptLst)%>$P<%crefToCStr(componentRef)%>'
  else "CREF_NOT_IDENT_OR_QUAL"
end crefToCStr;

template subscriptsToCStr(list<Subscript> subscripts)
::=
  if subscripts then
    '$lB<%subscripts |> s => subscriptToCStr(s) ;separator="$c"%>$rB'
end subscriptsToCStr;

template subscriptToCStr(Subscript subscript)
::=
  let &preExp = buffer ""
  let &varDecls = buffer ""
  match subscript
  case INDEX(__)
  case SLICE(__) then daeExp(exp, contextSimulationNonDiscrete, &preExp, &varDecls)
  case WHOLEDIM(__) then "WHOLEDIM"
  else "UNKNOWN_SUBSCRIPT"
end subscriptToCStr;

template expTypeFromExpArrayIf(Exp exp)
 "Generate type helper."
::=
  expTypeFromExpFlag(exp, 4)
end expTypeFromExpArrayIf;

template expTypeFlag(DAE.Type ty, Integer flag)
 "Generate type helper."
::=
  match flag
  case 1 then
    // we want the short type
    expTypeShort(ty)
  case 2 then
    // we want the "modelica type"
    match ty case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__)) then
      'modelica_<%expTypeShort(ty)%>'
    else match ty case T_COMPLEX(__) then
      'struct <%underscorePath(ClassInf.getStateName(complexClassType))%>' // alachew 'struct <%underscorePath(name)%>' //
    else
      'modelica_<%expTypeShort(ty)%>'
  case 3 then
    // we want the "array type"
    '<%expTypeShort(ty)%>_array'
  case 4 then
    // we want the "array type" only if type is array, otherwise "modelica type"
    match ty
    case T_ARRAY(__) then '<%expTypeShort(ty)%>_array'
    else expTypeFlag(ty, 2)
end expTypeFlag;

template tempDecl(String ty, Text &varDecls /*BUFP*/)
 "Declares a temporary variable in varDecls and returns the name."
::=
  let newVar = 'tmp<%System.tmpTick()%>'
  let &varDecls += '<%ty%> <%newVar%>;<%\n%>'
  newVar
end tempDecl;

template expTypeFromExpFlag(Exp exp, Integer flag)
 "Generate type helper."
::=
  match exp
  case ICONST(__)        then match flag case 8 then "int" case 1 then "integer" else "modelica_integer"
  case RCONST(__)        then match flag case 1 then "real" else "modelica_real"
  case SCONST(__)        then if acceptMetaModelicaGrammar() then
                                (match flag case 1 then "metatype" else "modelica_metatype")
                              else
                                (match flag case 1 then "string" else "modelica_string")
  case BCONST(__)        then match flag case 1 then "boolean" else "modelica_boolean"
  case ENUM_LITERAL(__)  then match flag case 8 then "int" case 1 then "integer" else "modelica_integer"
  case e as BINARY(__)
  case e as UNARY(__)
  case e as LBINARY(__)
  case e as LUNARY(__)
  case e as RELATION(__) then expTypeFromOpFlag(e.operator, flag)
  case IFEXP(__)         then expTypeFromExpFlag(expThen, flag)
  case CALL(attr=CALL_ATTR(__)) then expTypeFlag(attr.ty, flag) // alachew case CALL(__)          then expTypeFlag(ty, flag)
  else '#error "expTypeFromExpFlag:<%printExpStr(exp)%>"'
end expTypeFromExpFlag;

template expTypeShort(DAE.Type type)
 "Generate type helper."
::=
  match type
  case T_INTEGER(__)         then "integer"
  case T_REAL(__)        then "real"
  case T_STRING(__)      then if acceptMetaModelicaGrammar() then "metatype" else "string"
  case T_BOOL(__)        then "boolean"
  case T_ENUMERATION(__) then "integer"
  // alachew case T_OTHER(__)       then "complex"
  case T_ARRAY(__)       then expTypeShort(ty)
  case T_COMPLEX(complexClassType=EXTERNAL_OBJ(__))
                      then "complex"
  case T_COMPLEX(__)     then 'struct <%underscorePath(ClassInf.getStateName(complexClassType))%>' // alachew 'struct <%underscorePath(name)%>'
  case T_METATYPE(__) case T_METABOXED(__)    then "metatype"
  case T_FUNCTION_REFERENCE_VAR(__) then "fnptr"
  else "expTypeShort:ERROR"
end expTypeShort;

template replaceDotAndUnderscore(String str)
 "Replace _ with __ and dot in identifiers with _"
::=
  match str
  case name then
    let str_dots = System.stringReplace(name,".", "_")
    let str_underscores = System.stringReplace(str_dots, "_", "__")
    '<%str_underscores%>'
end replaceDotAndUnderscore;

template underscorePath(Path path)
 "Generate paths with components separated by underscores.
  Replaces also the . in identifiers with _.
  The dot might happen for world.gravityAccleration"
::=
  match path
  case QUALIFIED(__) then
    '<%replaceDotAndUnderscore(name)%>_<%underscorePath(path)%>'
  case IDENT(__) then
    replaceDotAndUnderscore(name)
  case FULLYQUALIFIED(__) then
    underscorePath(path)
end underscorePath;

template expTypeFromOpFlag(Operator op, Integer flag)
 "Generate type helper."
::=
  match op
  case o as ADD(__)
  case o as SUB(__)
  case o as MUL(__)
  case o as DIV(__)
  case o as POW(__)

  case o as UMINUS(__)
  // alachew case o as UPLUS(__)
  case o as LESS(__)
  case o as LESSEQ(__)
  case o as GREATER(__)
  case o as GREATEREQ(__)
  case o as EQUAL(__)
  case o as NEQUAL(__) then
    expTypeFlag(o.ty, flag)
  case o as AND(__)
  case o as OR(__)
  case o as NOT(__) then
    match flag case 1 then "boolean" else "modelica_boolean"
  else "expTypeFromOpFlag:ERROR"
end expTypeFromOpFlag;

template infoArgs(Info info)
::=
  match info
  case INFO(__) then '"<%fileName%>",<%lineNumberStart%>,<%columnNumberStart%>,<%lineNumberEnd%>,<%columnNumberEnd%>,<%isReadOnly%>'
end infoArgs;

template assertCommon(Exp condition, Exp message, Context context, Text &varDecls, Info info)
::=
  let &preExpCond = buffer ""
  let &preExpMsg = buffer ""
  let condVar = daeExp(condition, context, &preExpCond, &varDecls)
  let msgVar = daeExp(message, context, &preExpMsg, &varDecls)
  <<
  <%preExpCond%>
  if (!<%condVar%>) {
    <%preExpMsg%>
    omc_fileInfo info = {<%infoArgs(info)%>};
    MODELICA_ASSERT(info, <%msgVar%>);
  }
  >>
end assertCommon;

template expTypeFromExpShort(Exp exp)
 "Generate type helper."
::=
  expTypeFromExpFlag(exp, 1)
end expTypeFromExpShort;


template expTypeFromExpModelica(Exp exp)
 "Generate type helper."
::=
  expTypeFromExpFlag(exp, 2)
end expTypeFromExpModelica;

template unboxVariable(String varName, Type varType, Text &preExp, Text &varDecls)
::=
match varType
case T_STRING(__) case T_METATYPE(__) case T_METABOXED(__) then varName
case T_COMPLEX(complexClassType = RECORD(__)) then
  unboxRecord(varName, varType, &preExp, &varDecls)
else
  let shortType = mmcExpTypeShort(varType)
  let ty = 'modelica_<%shortType%>'
  let tmpVar = tempDecl(ty, &varDecls)
  let &preExp += '<%tmpVar%> = mmc_unbox_<%shortType%>(<%varName%>);<%\n%>'
  tmpVar
end unboxVariable;

template unboxRecord(String recordVar, Type ty, Text &preExp, Text &varDecls)
::=
match ty
case T_COMPLEX(complexClassType = RECORD(path = path), varLst = vars) then
  let tmpVar = tempDecl('struct <%underscorePath(path)%>', &varDecls)
  let &preExp += (vars |> TYPES_VAR(name = compname) hasindex offset fromindex 2 =>
    let varType = mmcExpTypeShort(ty)
    let untagTmp = tempDecl('modelica_metatype', &varDecls)
    //let offsetStr = incrementInt(i1, 1)
    let &unboxBuf = buffer ""
    let unboxStr = unboxVariable(untagTmp, ty, &unboxBuf, &varDecls)
    <<
    <%untagTmp%> = (MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(<%recordVar%>), <%offset%>)));
    <%unboxBuf%>
    <%tmpVar%>.<%compname%> = <%unboxStr%>;
    >>
    ;separator="\n")
  tmpVar
end unboxRecord;

template mmcExpTypeShort(DAE.Type type)
::=
  match type
  case T_INTEGER(__)                 then "integer"
  case T_REAL(__)                    then "real"
  case T_STRING(__)                  then "string"
  case T_BOOL(__)                    then "integer"
  case T_ENUMERATION(__)             then "integer"
  case T_ARRAY(__)                   then "array"
  case T_METATYPE(__) case T_METABOXED(__)                then "metatype"
  case T_FUNCTION_REFERENCE_VAR(__)  then "fnptr"
  else "mmcExpTypeShort:ERROR"
end mmcExpTypeShort;

/* IF and CALL ends */
















template simulationFunctionsFile(String filePrefix, list<Function> functions, list<Exp> literals)
 "Generates the content of the C file for functions in the simulation case."
::=
  <<


  >>
  /* adpro: leave a newline at the end of file to get rid of warnings! */
end simulationFunctionsFile;

template simulationMakefile(SimCode simCode)
 "Generates the contents of the makefile for the simulation case."
::=
match simCode
case SIMCODE(modelInfo=MODELINFO(__), makefileParams=MAKEFILE_PARAMS(__)) then
  let dirExtra = if modelInfo.directory then '-L"<%modelInfo.directory%>"' //else ""
  let libsStr = (makefileParams.libs |> lib => lib ;separator=" ")
  let libsPos1 = if not dirExtra then libsStr //else ""
  let libsPos2 = if dirExtra then libsStr // else ""
  <<
  # Makefile generated by OpenModelica

  #top_dir = /c/OpenModelica/java_runtime/
  #simulation_dir = $(top_dir)simCodeJava/

  #all: copy

  #copy:
  #<%\t%>cp TestModel.java $(simulation_dir)
  #<%\t%>cp TestModel_init.txt $(top_dir)
  #<%\t%>(cd $(top_dir); make -f Makefile)

  JFLAGS = -g
  JC = javac
  .SUFFIXES: .java .class
  .java.class:
  <%\t%>$(JC) $(JFLAGS) $*.java

  top_dir = ${OPENMODELICAHOME}/
  cRuntime = $(top_dir)c_runtime/
  Jar = $(top_dir)share/java/
  simcodejava = $(cRuntime)java_interface/src/org/openmodelica/
  simulation_dir = $(top_dir)java_runtime/simCodeJava/

  CLASSES = \
  <%\t%>simCodeJava/<%fileNamePrefix%>.java
  #<%\t%>$(simulation_dir)/JavaSolver.java \

  default: all

  classes: $(CLASSES:.java=.class)

  clean:
  <%\t%>$(RM) *.class

  all: classes
  <%\t%>java -cp .:java_runtime.jar <%fileNamePrefix%> <%fileNamePrefix%>
  >>
end simulationMakefile;

template simulationInitFile(SimCode simCode)
 "Generates the contents of the makefile for the simulation case."
::=
match simCode
case SIMCODE(modelInfo = MODELINFO(varInfo = vi as VARINFO(__), vars = vars as SIMVARS(__)),
             simulationSettingsOpt = SOME(s as SIMULATION_SETTINGS(__)))
  then
  <<
  <%s.startTime%> // start value
  <%s.stopTime%> // stop value
  <%s.stepSize%> // step value
  <%s.tolerance%> // tolerance
  "<%s.method%>" // method
  "<%s.outputFormat%>" // outputFormat
  <%vi.numStateVars%> // n states
  <%vi.numAlgVars%> // n alg vars
  <%vi.numParams%> //n parameters
  <%vi.numIntParams%> // n int parameters
  <%vi.numIntAlgVars%> // n int variables
  <%vi.numBoolParams%> // n bool parameters
  <%vi.numBoolAlgVars%> // n bool variables
  <%vi.numStringParamVars%> // n string-parameters
  <%vi.numStringAlgVars%> // n string variables
  <%initVals(vars.stateVars)%>
  <%initVals(vars.derivativeVars)%>
  <%initVals(vars.algVars)%>
  <%initVals(vars.paramVars)%>
  <%initVals(vars.intParamVars)%>
  <%initVals(vars.intAlgVars)%>
  <%initVals(vars.boolParamVars)%>
  <%initVals(vars.boolAlgVars)%>
  <%initVals(vars.stringParamVars)%>
  <%initVals(vars.stringAlgVars)%>
  >>
end simulationInitFile;

template initVals(list<SimVar> varsLst) ::=
  varsLst |> SIMVAR(__) =>
  <<
  <%match initialValue
      case SOME(v) then
        match v
        case ICONST(__) then integer
        case RCONST(__) then real
        case SCONST(__) then '"<%Util.escapeModelicaStringToCString(string)%>"'
        case BCONST(__) then if bool then "true" else "false"
        case ENUM_LITERAL(__) then '<%index%>'
        else "*ERROR* initial value of unknown type"
      else "0.0 //default"
    %>
    >>
  ;separator="\n"
end initVals;

template functionsFile(String filePrefix,
                       Option<Function> mainFunction,
                       list<Function> functions,
                       list<Exp> literals)
 "Generates the contents of the main C file for the function case."
::=
  <<

  >>
end functionsFile;

template externalFunctionIncludes(list<String> includes)
 "Generates external includes part in function files."
::=

  <<


  >>
end externalFunctionIncludes;

end CodegenJava;
