diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index bdc7d1af..b66f451d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -71,7 +71,7 @@ jobs: # run: mvn test -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn - name: upload test reports win - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ failure() && matrix.os == env.WINDOWS_VERSION}} with: @@ -83,7 +83,7 @@ jobs: retention-days: 1 - name: upload test reports ubuntu - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: ${{ failure() && matrix.os == 'ubuntu-22.04' }} with: name: surfire-ubuntu diff --git a/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java b/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java index ee3df3ad..9fdab6d2 100644 --- a/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java +++ b/ast/src/main/java/org/intocps/maestro/ast/MableAstFactory.java @@ -370,6 +370,11 @@ public static ARealLiteralExp newARealLiteralExp(Double value) { return exp; } + public static AFloatLiteralExp newAFloatLiteralExp(Float value) { + AFloatLiteralExp exp = new AFloatLiteralExp(); + exp.setValue(value); + return exp; + } public static AIntLiteralExp newAIntLiteralExp(Integer value) { AIntLiteralExp exp = new AIntLiteralExp(); exp.setValue(value); @@ -416,6 +421,10 @@ public static ARealNumericPrimitiveType newARealNumericPrimitiveType() { ARealNumericPrimitiveType type = new ARealNumericPrimitiveType(); return type; } + public static AFloatNumericPrimitiveType newAFloatNumericPrimitiveType() { + AFloatNumericPrimitiveType type = new AFloatNumericPrimitiveType(); + return type; + } public static ARealNumericPrimitiveType newRealType() { diff --git a/ast/src/main/resources/mabl.astv2 b/ast/src/main/resources/mabl.astv2 index ecb10d78..cdad5450 100644 --- a/ast/src/main/resources/mabl.astv2 +++ b/ast/src/main/resources/mabl.astv2 @@ -15,6 +15,7 @@ Tokens java_Boolean = 'java:java.lang.Boolean'; java_Integer = 'java:java.lang.Integer'; java_Double = 'java:java.lang.Double'; + java_Float = 'java:java.lang.Float'; java_Long = 'java:java.lang.Long'; lex_identifier='java:org.intocps.maestro.ast.LexIdentifier'; @@ -92,6 +93,8 @@ exp | {int} [value]:java_Integer | {uInt} [value]:java_Long | {real} [value]:java_Double + | {long} [value]:java_Long + | {float} [value]:java_Float ; #binary {-> package='org.intocps.maestro.ast' diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt index 07a0156a..893a2861 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3ModelDescription.kt @@ -614,10 +614,10 @@ class Fmi3ModelDescription : ModelDescription { ?: typeDefinition?.canBeDeactivated){true->true;false,null->false}, node.attributes.getNamedItem("priority")?.nodeValue?.toUInt() ?: typeDefinition?.priority, if (interval == null) typeDefinition!!.interval else valueOf(interval), - node.attributes.getNamedItem("intervalDecimal")?.nodeValue?.toFloat() + node.attributes.getNamedItem("intervalDecimal")?.nodeValue?.toDouble() ?: typeDefinition?.intervalDecimal, - node.attributes.getNamedItem("shiftDecimal")?.nodeValue?.toFloat() ?: typeDefinition?.shiftDecimal - ?: (0).toFloat(), + node.attributes.getNamedItem("shiftDecimal")?.nodeValue?.toDouble() ?: typeDefinition?.shiftDecimal + ?: (0).toDouble(), node.attributes.getNamedItem("supportsFraction")?.nodeValue?.toBoolean() ?: typeDefinition?.supportsFraction ?: false, node.attributes.getNamedItem("resolution")?.nodeValue?.toULong() ?: typeDefinition?.resolution, @@ -665,8 +665,8 @@ class Fmi3ModelDescription : ModelDescription { node.attributes.getNamedItem("canBeDeactivated")?.nodeValue?.toBoolean(), node.attributes.getNamedItem("priority")?.nodeValue?.toUInt(), valueOf(node.attributes.getNamedItem("interval")!!.nodeValue), - node.attributes.getNamedItem("intervalDecimal")?.nodeValue?.toFloat(), - node.attributes.getNamedItem("shiftDecimal")?.nodeValue?.toFloat(), + node.attributes.getNamedItem("intervalDecimal")?.nodeValue?.toDouble(), + node.attributes.getNamedItem("shiftDecimal")?.nodeValue?.toDouble(), node.attributes.getNamedItem("supportsFraction")?.nodeValue?.toBoolean(), node.attributes.getNamedItem("resolution")?.nodeValue?.toULong(), node.attributes.getNamedItem("intervalCounter")?.nodeValue?.toULong(), diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt index 122f4d5f..0bc2b0b7 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3TypeDefinitions.kt @@ -66,8 +66,8 @@ data class ClockTypeDefinition( val canBeDeactivated: Boolean? = false, val priority: UInt?, val interval: Fmi3ClockInterval, - val intervalDecimal: Float?, - val shiftDecimal: Float? = (0).toFloat(), + val intervalDecimal: Double?, + val shiftDecimal: Double? = (0).toDouble(), val supportsFraction: Boolean? = false, val resolution: ULong?, val intervalCounter: ULong?, diff --git a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt index 5a91d591..1a31dca7 100644 --- a/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt +++ b/fmi/src/main/kotlin/org/intocps/maestro/fmi/fmi3/Fmi3Variables.kt @@ -284,8 +284,8 @@ class ClockVariable( val canBeDeactivated: Boolean? = false, val priority: UInt? = null, val interval: Fmi3ClockInterval, - val intervalDecimal: Float? = null, - val shiftDecimal: Float? = (0).toFloat(), + val intervalDecimal: Double? = null, + val shiftDecimal: Double? = (0).toDouble(), val supportsFraction: Boolean? = false, val resolution: ULong? = null, val intervalCounter: ULong? = null, diff --git a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java index c666f586..c641ffa7 100644 --- a/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java +++ b/frameworks/builder/src/main/java/org/intocps/maestro/framework/fmi2/api/FmiBuilder.java @@ -234,12 +234,13 @@ interface Scope extends Scoping { * @return */ DoubleVariable store(double value); - + FloatVariable store(float value); StringVariable store(String value); BoolVariable store(boolean value); IntVariable store(int value); + UIntVariable storeUInt(long value); /** * Store a given value with a prefix name @@ -248,16 +249,19 @@ interface Scope extends Scoping { * @return */ DoubleVariable store(String name, double value); + FloatVariable store(String name, float value); StringVariable store(String name, String value); BoolVariable store(String name, boolean value); IntVariable store(String name, int value); + UIntVariable storeUInt(String name, long value); ArrayVariable store(String name, CV[] value); ArrayVariable createArray(String name,Class type, IntVariable...sizes ) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException; + ArrayVariable createArray(String name,Class type, UIntVariable...sizes ) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException; /** * Store the given value and get a tag for it. Copy @@ -477,6 +481,10 @@ interface DoubleVariable extends Variable, Prov void set(Double value); } + interface FloatVariable extends Variable, ProvidesTypedReferenceExp, NumericTypedReferenceExp { + + void set(Float value); + } interface BoolVariable extends Variable, ProvidesTypedReferenceExp { Predicate toPredicate(); @@ -882,10 +890,15 @@ interface BooleanExpressionValue extends FmiBuilder.ExpressionValue { interface DoubleExpressionValue extends NumericExpressionValue { } + interface FloatExpressionValue extends NumericExpressionValue { + } interface IntExpressionValue extends NumericExpressionValue { } + interface LongExpressionValue extends NumericExpressionValue { + } + interface UIntExpressionValue extends IntExpressionValue { } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java index b6f16cc9..45b0a60a 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/DynamicActiveBuilderScope.java @@ -136,6 +136,11 @@ public DoubleVariableFmi2Api store(double value) { return activeScope.store(value); } + @Override + public FloatVariableFmi2Api store(float value) { + return activeScope.store(value); + } + @Override public StringVariableFmi2Api store(String value) { return activeScope.store(value); @@ -147,12 +152,24 @@ public IntVariableFmi2Api store(int value) { } + @Override + public UIntVariableFmi2Api storeUInt(long value) { + return activeScope.storeUInt(value); + + } + + @Override public DoubleVariableFmi2Api store(String name, double value) { return activeScope.store(name, value); } + @Override + public FloatVariableFmi2Api store(String name, float value) { + return activeScope.store(name,value); + } + @Override public StringVariableFmi2Api store(String name, String value) { return activeScope.store(name, value); @@ -169,6 +186,13 @@ public IntVariableFmi2Api store(String name, int value) { return activeScope.store(name, value); } + @Override + public UIntVariableFmi2Api storeUInt(String name, long value) { + return activeScope.storeUInt(name, value); + } + + + /* @Override public , Var extends Fmi2Builder.Variable> Var store(String name, Var value) { return activeScope.store(name, value); @@ -192,6 +216,12 @@ public ArrayVariableFmi2Api createArray(String name, Class t return activeScope.createArray(name,type,sizes); } + @Override + public ArrayVariableFmi2Api createArray(String name, Class type, + FmiBuilder.UIntVariable... sizes) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + return activeScope.createArray(name,type,sizes); + } + @Override public FmiBuilder.Variable store(FmiBuilder.Value tag) { return activeScope.store(tag); @@ -207,6 +237,11 @@ public DoubleVariableFmi2Api store(String namePrefix, DoubleVariableFmi2Api vari return activeScope.store(namePrefix, variable); } + @Override + public FloatVariableFmi2Api store(String namePrefix, FloatVariableFmi2Api variable) { + return activeScope.store(namePrefix,variable); + } + @Override public ArrayVariableFmi2Api storeInArray(String name, VariableFmi2Api[] variables) { return activeScope.storeInArray(name, variables); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java index c0dcec9d..e619fed2 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/IMablScope.java @@ -64,22 +64,33 @@ public interface IMablScope extends FmiBuilder.Scope { @Override DoubleVariableFmi2Api store(double value); + @Override + FloatVariableFmi2Api store(float value); @Override IntVariableFmi2Api store(int value); + @Override + UIntVariableFmi2Api storeUInt(long value); + @Override StringVariableFmi2Api store(String value); @Override DoubleVariableFmi2Api store(String name, double value); + @Override + FloatVariableFmi2Api store(String name, float value); + @Override BooleanVariableFmi2Api store(String name, boolean value); @Override IntVariableFmi2Api store(String name, int value); + @Override + UIntVariableFmi2Api storeUInt(String name, long value); + @Override StringVariableFmi2Api store(String name, String value); @@ -88,6 +99,7 @@ public interface IMablScope extends FmiBuilder.Scope { @Override ArrayVariableFmi2Api createArray(String name,Class type, FmiBuilder.IntVariable... sizes ) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException; + ArrayVariableFmi2Api createArray(String name,Class type, FmiBuilder.UIntVariable... sizes ) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException; @Override FmiBuilder.Variable store(FmiBuilder.Value tag); @@ -96,6 +108,7 @@ public interface IMablScope extends FmiBuilder.Scope { DoubleVariableFmi2Api store(String namePrefix, DoubleVariableFmi2Api variable); + FloatVariableFmi2Api store(String namePrefix, FloatVariableFmi2Api variable); ArrayVariableFmi2Api storeInArray(String name, VariableFmi2Api[] variables); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java index 28f56b3d..7a5ae4f7 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/scoping/ScopeFmi2Api.java @@ -190,6 +190,11 @@ public DoubleVariableFmi2Api store(double value) { return store(() -> builder.getNameGenerator().getName(), value); } + @Override + public FloatVariableFmi2Api store(float value) { + return store(() -> builder.getNameGenerator().getName(), value); + } + @Override public StringVariableFmi2Api store(String value) { return store(() -> builder.getNameGenerator().getName(), value); @@ -205,11 +210,25 @@ public IntVariableFmi2Api store(int value) { return store(() -> builder.getNameGenerator().getName(), value); } + @Override + public UIntVariableFmi2Api storeUInt(long value) { + return storeUInt(() -> builder.getNameGenerator().getName(), value); + } + + + + @Override public DoubleVariableFmi2Api store(String prefix, double value) { return store(() -> builder.getNameGenerator().getName(prefix), value); } + + @Override + public FloatVariableFmi2Api store(String prefix, float value) { + return store(() -> builder.getNameGenerator().getName(prefix), value); + } + @Override public StringVariableFmi2Api store(String prefix, String value) { return store(() -> builder.getNameGenerator().getName(prefix), value); @@ -224,6 +243,10 @@ public BooleanVariableFmi2Api store(String name, boolean value) { public IntVariableFmi2Api store(String name, int value) { return store(() -> builder.getNameGenerator().getName(name), value); } + @Override + public UIntVariableFmi2Api storeUInt(String name, long value) { + return storeUInt(() -> builder.getNameGenerator().getName(name), value); + } @Override public ArrayVariableFmi2Api store(String name, V[] value) { @@ -236,6 +259,12 @@ public ArrayVariableFmi2Api createArray(String name, Class t return newArray(() -> builder.getNameGenerator().getName(name), type, sizes); } + @Override + public ArrayVariableFmi2Api createArray(String name, Class type, + FmiBuilder.UIntVariable... sizes) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + return newArray(() -> builder.getNameGenerator().getName(name), type, sizes); + } + public DoubleVariableFmi2Api store(Supplier nameProvider, double value) { String name = nameProvider.get(); @@ -246,6 +275,15 @@ public DoubleVariableFmi2Api store(Supplier nameProvider, double value) newAIdentifierExp(name)); } + public FloatVariableFmi2Api store(Supplier nameProvider, float value) { + String name = nameProvider.get(); + AFloatLiteralExp initial = newAFloatLiteralExp(value); + PStm var = newVariable(name, newAFloatNumericPrimitiveType(), initial); + add(var); + return new FloatVariableFmi2Api(var, this, builder.getDynamicScope(), newAIdentifierStateDesignator(newAIdentifier(name)), + newAIdentifierExp(name)); + } + public BooleanVariableFmi2Api store(Supplier nameProvider, boolean value) { String name = nameProvider.get(); ABoolLiteralExp initial = newABoolLiteralExp(value); @@ -264,6 +302,17 @@ public IntVariableFmi2Api store(Supplier nameProvider, int value) { newAIdentifierExp(name)); } + public UIntVariableFmi2Api storeUInt(Supplier nameProvider, long value) { + String name = nameProvider.get(); + AUIntLiteralExp initial = newAUIntLiteralExp(value); + PStm var = newVariable(name, newAIntNumericPrimitiveType(), initial); + add(var); + return new UIntVariableFmi2Api(var, this, builder.getDynamicScope(), newAIdentifierStateDesignator(newAIdentifier(name)), + newAIdentifierExp(name)); + } + + + public StringVariableFmi2Api store(Supplier nameProvider, String value) { String name = nameProvider.get(); AStringLiteralExp initial = newAStringLiteralExp(value); @@ -273,8 +322,15 @@ public StringVariableFmi2Api store(Supplier nameProvider, String value) newAIdentifierExp(name)); } - private ArrayVariableFmi2Api newArray(Supplier nameProvider, Class type, - FmiBuilder.IntVariable... sizes) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + + private ArrayVariableFmi2Api newArray(Supplier nameProvider, Class type, + S... sizes) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + for (FmiBuilder.Variable v : sizes) { + if (!(v instanceof FmiBuilder.IntVariable || v instanceof FmiBuilder.UIntVariable)) { + throw new IllegalArgumentException("only int and uint variables allowed"); + } + } + PType type_ = null; @@ -490,6 +546,15 @@ public DoubleVariableFmi2Api store(String namePrefix, DoubleVariableFmi2Api vari newAIdentifierExp(name)); } + @Override + public FloatVariableFmi2Api store(String namePrefix, FloatVariableFmi2Api variable) { + String name = getName(namePrefix); + PStm var = newVariable(name, newAFloatNumericPrimitiveType(), variable.getReferenceExp()); + add(var); + return new FloatVariableFmi2Api(var, this, builder.getDynamicScope(), newAIdentifierStateDesignator(newAIdentifier(name)), + newAIdentifierExp(name)); + } + @Override public ArrayVariableFmi2Api storeInArray(String namePrefix, VariableFmi2Api[] variables) { String name = getName(namePrefix); @@ -589,8 +654,7 @@ public void addTransferAs(String... names) { @Override public Var copy(String name, Var variable) { - if (variable instanceof BooleanVariableFmi2Api || variable instanceof DoubleVariableFmi2Api || variable instanceof IntVariableFmi2Api || - variable instanceof StringVariableFmi2Api) { + if (!(variable instanceof ArrayVariableFmi2Api) && variable instanceof VariableFmi2Api) { String varName = builder.getNameGenerator().getName(name); PStm variableDeclaration = newVariable(varName, variable.getType(), variable.getReferenceExp().clone()); add(variableDeclaration); diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/FloatExpressionValue.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/FloatExpressionValue.java new file mode 100644 index 00000000..0549a546 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/values/FloatExpressionValue.java @@ -0,0 +1,106 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.values; + +import org.intocps.maestro.ast.node.AFloatNumericPrimitiveType; +import org.intocps.maestro.ast.node.ARealNumericPrimitiveType; +import org.intocps.maestro.ast.node.PExp; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.NumericExpressionValueFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.PredicateFmi2Api; + +import static org.intocps.maestro.ast.MableAstFactory.*; + + +public class FloatExpressionValue extends NumericExpressionValueFmi2Api implements FmiBuilder.FloatExpressionValue { + + final PType type = new AFloatNumericPrimitiveType(); + final PExp exp; + + public FloatExpressionValue(float value) { + this.exp = newAFloatLiteralExp(value); + } + + public FloatExpressionValue(PExp exp) { + this.exp = exp; + } + + public static FloatExpressionValue of(float value) { + return new FloatExpressionValue(value); + } + + @Override + public PExp getExp() { + return this.exp.clone(); + } + + @Override + public PType getType() { + return this.type; + } + + @Override + public FloatExpressionValue subtraction(int v) { + return new FloatExpressionValue(newMinusExp(getExp(), newAIntLiteralExp(v))); + } + + @Override + public FloatExpressionValue addition(int v) { + return new FloatExpressionValue(newPlusExp(getExp(), newAIntLiteralExp(v))); + } + + @Override + public FloatExpressionValue divide(int v) { + return new FloatExpressionValue(newDivideExp(getExp(), newAIntLiteralExp(v))); + } + + @Override + public FloatExpressionValue multiply(int v) { + return new FloatExpressionValue(newMultiplyExp(getExp(), newAIntLiteralExp(v))); + } + + + @Override + public FloatExpressionValue subtraction(double v) { + return new FloatExpressionValue(newMinusExp(getExp(), newARealLiteralExp(v))); + } + + @Override + public FloatExpressionValue addition(double v) { + return new FloatExpressionValue(newPlusExp(getExp(), newARealLiteralExp(v))); + } + + @Override + public FloatExpressionValue divide(double v) { + return new FloatExpressionValue(newDivideExp(getExp(), newARealLiteralExp(v))); + } + + @Override + public FloatExpressionValue multiply(double v) { + return new FloatExpressionValue(newMultiplyExp(getExp(), newARealLiteralExp(v))); + } + + @Override + public FloatExpressionValue addition(FmiBuilder.NumericTypedReferenceExp v) { + return new FloatExpressionValue(newPlusExp(getExp(), v.getExp())); + } + + @Override + public FloatExpressionValue divide(FmiBuilder.NumericTypedReferenceExp v) { + return new FloatExpressionValue(newDivideExp(getExp(), v.getExp())); + } + + @Override + public FloatExpressionValue subtraction(FmiBuilder.NumericTypedReferenceExp v) { + return new FloatExpressionValue(newMinusExp(getExp(), v.getExp())); + } + + @Override + public FloatExpressionValue multiply(FmiBuilder.NumericTypedReferenceExp v) { + return new FloatExpressionValue(newMultiplyExp(getExp(), v.getExp())); + } + + @Override + public PredicateFmi2Api lessThan(FmiBuilder.NumericTypedReferenceExp endTimeVar) { + return new PredicateFmi2Api(newALessBinaryExp(getExp(), endTimeVar.getExp())); + } +} diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FloatVariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FloatVariableFmi2Api.java new file mode 100644 index 00000000..64f530a9 --- /dev/null +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/FloatVariableFmi2Api.java @@ -0,0 +1,47 @@ +package org.intocps.maestro.framework.fmi2.api.mabl.variables; + +import org.intocps.maestro.ast.node.PExp; +import org.intocps.maestro.ast.node.PStateDesignator; +import org.intocps.maestro.ast.node.PStm; +import org.intocps.maestro.ast.node.PType; +import org.intocps.maestro.framework.fmi2.api.FmiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IMablScope; +import org.intocps.maestro.framework.fmi2.api.mabl.values.FloatExpressionValue; + +import static org.intocps.maestro.ast.MableAstFactory.newAFloatNumericPrimitiveType; + +public class FloatVariableFmi2Api extends VariableFmi2Api implements FmiBuilder.FloatVariable { + public FloatVariableFmi2Api(PStm declaration, IMablScope declaredScope, FmiBuilder.DynamicActiveScope dynamicScope, + PStateDesignator designator, PExp referenceExp) { + super(declaration, newAFloatNumericPrimitiveType(), declaredScope, dynamicScope, designator, referenceExp); + } + + + @Override + public void set(Float value) { + super.setValue(FloatExpressionValue.of(value)); + } + + + @Override + public void setValue(FmiBuilder.FloatExpressionValue value) { + super.setValue(value.getExp()); + } + + + @Override + public FloatExpressionValue toMath() { + return new FloatExpressionValue(this.getExp()); + } + + + @Override + public PType getType() { + return newAFloatNumericPrimitiveType(); + } + + @Override + public FloatVariableFmi2Api clone(PStm declaration, IMablScope declaredScope, PStateDesignator designator, PExp referenceExp) { + return new FloatVariableFmi2Api(declaration, declaredScope, dynamicScope, designator, referenceExp); + } +} diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java index df0df89b..90b746b4 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/InstanceVariableFmi3Api.java @@ -268,7 +268,7 @@ public void setDebugLogging(List categories, boolean enableLogging) { ALocalVariableStm callStm = newALocalVariableStm(newAVariableDeclaration(statusIdentifier, newAIntNumericPrimitiveType(), newAExpInitializer( newACallExp(newAIdentifierExp(name), newAIdentifier(method), - Arrays.asList(newABoolLiteralExp(enableLogging), MableAstFactory.newAIntLiteralExp(categories.size()), + Arrays.asList(newABoolLiteralExp(enableLogging), MableAstFactory.newAIdentifierExp(arrayName)))))); scope.add(arrayContent, callStm); @@ -363,13 +363,13 @@ public void enterStepMode(FmiBuilder.Scope scope) { } public void getEventIndicators(FmiBuilder.Scope scope, FmiBuilder.ArrayVariable> eventIndicators, - FmiBuilder.IntVariable nEventIndicators) { + FmiBuilder.UIntVariable nEventIndicators) { fmiCall(scope, "getEventIndicators", new ARefExp(eventIndicators.getExp().clone()), nEventIndicators.getExp().clone()); } - public void getNumberOfEventIndicators(FmiBuilder.Scope scope, FmiBuilder.IntVariable nEventIndicators) { + public void getNumberOfEventIndicators(FmiBuilder.Scope scope, FmiBuilder.UIntVariable nEventIndicators) { fmiCall(scope, "getNumberOfEventIndicators", new ARefExp(nEventIndicators.getExp().clone())); } diff --git a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java index fac53805..2a337b47 100644 --- a/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java +++ b/frameworks/fmi2api/src/main/java/org/intocps/maestro/framework/fmi2/api/mabl/variables/VariableFmi2Api.java @@ -75,11 +75,11 @@ public void setValue(FmiBuilder.Scope scope, FmiBuilder.Variable @Override public void setValue(FmiBuilder.Scope scope, V value) { - if (!(value instanceof DoubleExpressionValue)) { + if (!(value instanceof FmiBuilder.ProvidesTypedReferenceExp)) { throw new IllegalArgumentException(); } - scope.add(MableAstFactory.newAAssignmentStm(this.designator.clone(), ((DoubleExpressionValue) value).getExp())); + scope.add(MableAstFactory.newAAssignmentStm(this.designator.clone(), ((FmiBuilder.ProvidesTypedReferenceExp) value).getExp())); } @Override diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java index 4b77b814..77f3cdd8 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/Interpreter.java @@ -282,17 +282,17 @@ public Value caseAVariableDeclaration(AVariableDeclaration node, Context questio Value initialValue = node.getInitializer() == null ? new UndefinedValue() : node.getInitializer().apply(this, question); - if (initialValue.isNumeric()) { + if (initialValue.deref().isNumeric()) { Class targetValueType = typeValueMappings.get(node.getType().getClass()); if (targetValueType != null) { //we need to upcast all values explicitly here - NumericValue upcasted = ((NumericValue) initialValue).upCast((Class) targetValueType); + NumericValue upcasted = ((NumericValue) initialValue.deref()).upCast((Class) targetValueType); if (upcasted == null) { throw new InterpreterException( - String.format("Initializer value could not be upcasted. In ", initialValue.toString()) + "initializer is " + + String.format("Initializer value could not be upcasted. In ", initialValue.deref().toString()) + "initializer is " + "specified: " + node.getName() + " in " + node); } initialValue = upcasted; @@ -548,6 +548,11 @@ public Value caseARealLiteralExp(ARealLiteralExp node, Context question) throws return NumericValue.valueOf(node.getValue()); } + @Override + public Value caseAFloatLiteralExp(AFloatLiteralExp node, Context question) throws AnalysisException { + return NumericValue.valueOf(node.getValue()); + } + @Override public Value caseABoolLiteralExp(ABoolLiteralExp node, Context question) throws AnalysisException { return new BooleanValue(node.getValue()); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java index 5e606862..5743b9d6 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/extensions/fmi3/Fmi3Interpreter.java @@ -78,6 +78,10 @@ public class Fmi3Interpreter { static final ExternalReflectCallHelper.ArgMapping intArrayOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Int, 2, ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping boolOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Bool, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + static final ExternalReflectCallHelper.ArgMapping doubleOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Real, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); final static Logger logger = LoggerFactory.getLogger(Interpreter.class); private final File workingDirectory; @@ -529,18 +533,19 @@ private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream })); functions.put("updateDiscreteStates", new FunctionValue.ExternalFunctionValue(fcargs -> { -// int updateDiscreteStates(out bool[] discreteStatesNeedUpdate, out bool[] terminateSimulation, -// out bool[] nominalsOfContinuousStatesChanged, out bool[] valuesOfContinuousStatesChanged, out bool[] nextEventTimeDefined, -// out real[] nextEventTime); +// int updateDiscreteStates(out bool discreteStatesNeedUpdate, out bool terminateSimulation, +// out bool nominalsOfContinuousStatesChanged, out bool valuesOfContinuousStatesChanged, out bool nextEventTimeDefined, +// out real nextEventTime); checkArgLength(fcargs, 6); try { FmuResult res = instance.updateDiscreteStates(); - boolArrayOutArgMapper.mapOut(fcargs.get(0), new boolean[]{res.result.isDiscreteStatesNeedUpdate()}); - boolArrayOutArgMapper.mapOut(fcargs.get(1), new boolean[]{res.result.isTerminateSimulation()}); - boolArrayOutArgMapper.mapOut(fcargs.get(2), new boolean[]{res.result.isNominalsOfContinuousStatesChanged()}); - boolArrayOutArgMapper.mapOut(fcargs.get(3), new boolean[]{res.result.isValuesOfContinuousStatesChanged()}); - boolArrayOutArgMapper.mapOut(fcargs.get(4), new boolean[]{res.result.isNextEventTimeDefined()}); - doubleArrayOutArgMapper.mapOut(fcargs.get(5), new double[]{res.result.getNextEventTime()}); + + boolOutArgMapper.mapOut(fcargs.get(0), res.result.isDiscreteStatesNeedUpdate()); + boolOutArgMapper.mapOut(fcargs.get(1), res.result.isTerminateSimulation()); + boolOutArgMapper.mapOut(fcargs.get(2), res.result.isNominalsOfContinuousStatesChanged()); + boolOutArgMapper.mapOut(fcargs.get(3), res.result.isValuesOfContinuousStatesChanged()); + boolOutArgMapper.mapOut(fcargs.get(4), res.result.isNextEventTimeDefined()); + doubleOutArgMapper.mapOut(fcargs.get(5), res.result.getNextEventTime()); return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); @@ -691,7 +696,11 @@ private static Value getFmuInstanceValue(BufferedOutputStream fmuLogOutputStream checkArgLength(fcargs, 1); try { FmuResult res = instance.getNumberOfEventIndicators(); - intArrayOutArgMapper.mapOut(fcargs.get(0), res.result); + final ExternalReflectCallHelper.ArgMapping uintOutArgMapper = new ExternalReflectCallHelper.ArgMapping(TP.Long, 1, + ExternalReflectCallHelper.ArgMapping.InOut.Output, null); + uintOutArgMapper.mapOut(fcargs.get(0), res.result); + UpdatableValue v= (UpdatableValue) fcargs.get(0); + v.setValue(new UnsignedIntegerValue(((LongValue)v.deref()).getValue())); return status2IntValue(res.status); } catch (FmuInvocationException e) { throw new InterpreterException(e); diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java index 82c2b116..a4aa89d7 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/external/ExternalReflectCallHelper.java @@ -365,7 +365,7 @@ public Object map(Value v) { } case Float: { var n = ((NumericValue) v); - return Integer.valueOf(n.intValue()).floatValue(); + return n.floatValue();//Integer.valueOf(n.intValue()).floatValue(); } case Int: { var n = ((NumericValue) v); @@ -373,11 +373,11 @@ public Object map(Value v) { } case Long: { var n = ((NumericValue) v); - return Integer.valueOf(n.intValue()).longValue(); + return n.longValue();// Integer.valueOf(n.intValue()).longValue(); } case Real: { var n = ((NumericValue) v); - return Integer.valueOf(n.intValue()).doubleValue(); + return n.doubleValue();//Integer.valueOf(n.intValue()).doubleValue(); } case Short: { var n = ((NumericValue) v); @@ -469,6 +469,36 @@ public void mapOut(Value original, Object value) { break; } ref.setValue(new ArrayValue<>(values)); + }else if(dimension==1) + { + Value mappedValue = null; + switch (type){ + case Bool: + mappedValue=new BooleanValue(value.getClass().isPrimitive()?(boolean)value:(Boolean)value); + break; + case Byte: + mappedValue=new ByteValue(value.getClass().isPrimitive()?(byte)value:(Byte)value); + break; + case Float: + mappedValue=new FloatValue(value.getClass().isPrimitive()?(float)value:(Float)value); + break; + case Int: + mappedValue=new IntegerValue(value.getClass().isPrimitive()?(int)value:(Integer)value); + break; + case Long: + mappedValue=new LongValue(value.getClass().isPrimitive()?(long)value:(Long)value); + break; + case Real: + mappedValue=new RealValue(value.getClass().isPrimitive()?(double)value:(Double)value); + break; + case Short: + mappedValue=new ShortValue(value.getClass().isPrimitive()?(short)value:(Short)value); + break; + case String: + mappedValue=new StringValue((String)value); + break; + } + ref.setValue(mappedValue); } } diff --git a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java index 1fdcde66..3094f6c7 100644 --- a/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java +++ b/interpreter/src/main/java/org/intocps/maestro/interpreter/values/FloatValue.java @@ -68,6 +68,10 @@ public int compareTo(Value value) { FloatValue ro = (FloatValue) other; return (int) Math.round(Math.signum(this.value - ro.getValue())); + } if (other instanceof RealValue) { + RealValue ro = (RealValue) other; + return (int) Math.round(Math.signum(this.value - ro.getValue())); + } else if (other instanceof IntegerValue) { IntegerValue ro = (IntegerValue) other; return (int) Math.round(Math.signum(this.value - ro.getValue())); diff --git a/maestro/src/test/java/org/intocps/maestro/FloatDeclTest.java b/maestro/src/test/java/org/intocps/maestro/FloatDeclTest.java new file mode 100644 index 00000000..d962c16d --- /dev/null +++ b/maestro/src/test/java/org/intocps/maestro/FloatDeclTest.java @@ -0,0 +1,69 @@ +package org.intocps.maestro; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.intocps.maestro.ast.AVariableDeclaration; +import org.intocps.maestro.ast.LexIdentifier; +import org.intocps.maestro.ast.analysis.AnalysisException; +import org.intocps.maestro.ast.display.PrettyPrinter; +import org.intocps.maestro.ast.node.AExpInitializer; +import org.intocps.maestro.ast.node.AFloatNumericPrimitiveType; +import org.intocps.maestro.ast.node.AIdentifierExp; +import org.intocps.maestro.ast.node.ALocalVariableStm; +import org.intocps.maestro.framework.fmi2.api.mabl.BaseApiTest; +import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.BooleanVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.DoubleVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.FloatVariableFmi2Api; +import org.intocps.maestro.framework.fmi2.api.mabl.variables.VariableFmi2Api; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + + +public class FloatDeclTest extends BaseApiTest { + protected FloatDeclTest() { + super(Assertions::assertTrue, Assertions::assertFalse); + } + + @Test + public void test() throws AnalysisException, IOException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + MablApiBuilder.MablSettings settings = new MablApiBuilder.MablSettings(); + settings.fmiErrorHandlingEnabled = false; + MablApiBuilder builder = new MablApiBuilder(settings); + + MDebugAssert assertModule = MDebugAssert.create(builder); + + DynamicActiveBuilderScope dscope = builder.getDynamicScope(); + + DoubleVariableFmi2Api r = dscope.store(123.456); + FloatVariableFmi2Api f = dscope.store(123.456f); + + AExpInitializer aExpInitializer = new AExpInitializer(); + aExpInitializer.setExp(r.getReferenceExp().clone()); + AVariableDeclaration decl = new AVariableDeclaration(); + decl.setName(new LexIdentifier("fr", null)); + decl.setType(new AFloatNumericPrimitiveType()); + decl.setInitializer(aExpInitializer); + ALocalVariableStm stm = new ALocalVariableStm(); + stm + .setDeclaration(decl); + dscope.add(stm); + + + assertModule.assertEquals(f, new VariableFmi2Api<>(stm, decl.getType().clone(), dscope,dscope, null, new AIdentifierExp(new LexIdentifier("fr", null)))); + + + String spec = PrettyPrinter.print(builder.build()); + System.out.println(spec); + + + check(spec, ""); + + } +} diff --git a/maestro/src/test/java/org/intocps/maestro/fmi3/BuilderFmi3Test.java b/maestro/src/test/java/org/intocps/maestro/fmi3/BuilderFmi3Test.java index f088df72..9ad95cf1 100644 --- a/maestro/src/test/java/org/intocps/maestro/fmi3/BuilderFmi3Test.java +++ b/maestro/src/test/java/org/intocps/maestro/fmi3/BuilderFmi3Test.java @@ -3,7 +3,6 @@ import org.antlr.v4.runtime.CharStreams; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.intocps.fmi.FmuInvocationException; import org.intocps.fmi.jnifmuapi.fmi3.Fmu3; import org.intocps.maestro.Mabl; import org.intocps.maestro.ast.display.PrettyPrinter; @@ -11,15 +10,15 @@ import org.intocps.maestro.core.Framework; import org.intocps.maestro.core.messages.ErrorReporter; import org.intocps.maestro.core.messages.IErrorReporter; -import org.intocps.maestro.fmi.fmi3.Fmi3Causality; -import org.intocps.maestro.fmi.fmi3.Fmi3ModelDescription; -import org.intocps.maestro.fmi.fmi3.Fmi3TypeEnum; +import org.intocps.maestro.fmi.fmi3.*; import org.intocps.maestro.framework.fmi2.api.FmiBuilder; +import org.intocps.maestro.framework.fmi2.api.mabl.DataWriter; +import org.intocps.maestro.framework.fmi2.api.mabl.LoggerFmi2Api; import org.intocps.maestro.framework.fmi2.api.mabl.MablApiBuilder; import org.intocps.maestro.framework.fmi2.api.mabl.PortFmi3Api; import org.intocps.maestro.framework.fmi2.api.mabl.scoping.DynamicActiveBuilderScope; -import org.intocps.maestro.framework.fmi2.api.mabl.scoping.IfMaBlScope; import org.intocps.maestro.framework.fmi2.api.mabl.values.BooleanExpressionValue; +import org.intocps.maestro.framework.fmi2.api.mabl.values.DoubleExpressionValue; import org.intocps.maestro.framework.fmi2.api.mabl.values.IntExpressionValue; import org.intocps.maestro.framework.fmi2.api.mabl.variables.*; import org.intocps.maestro.interpreter.DefaultExternalValueFactory; @@ -28,8 +27,8 @@ import org.intocps.maestro.typechecker.TypeChecker; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; import java.io.File; import java.io.IOException; @@ -40,7 +39,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.condition.OS.LINUX; public class BuilderFmi3Test { @BeforeAll @@ -49,7 +52,7 @@ public static void before() throws IOException { } - public static InstanceVariableFmi3Api createInstance(MablApiBuilder builder, String name, URI uri) throws Exception { + public static InstanceVariableFmi3Api createInstance(MablApiBuilder builder, String name, URI uri, boolean eventModeUsed) throws Exception { Fmi3ModelDescription md = new Fmi3ModelDescription(new Fmu3(new File(uri)).getModelDescription()); @@ -57,7 +60,7 @@ public static InstanceVariableFmi3Api createInstance(MablApiBuilder builder, Str boolean visible = true; boolean loggingOn = true; - boolean eventModeUsed = true; + boolean earlyReturnAllowed = true; ArrayVariableFmi2Api requiredIntermediateVariables = builder.getDynamicScope().store("requiredIntermediateVariables", new Long[]{1L}); InstanceVariableFmi3Api instance = @@ -66,14 +69,163 @@ public static InstanceVariableFmi3Api createInstance(MablApiBuilder builder, Str return instance; } + @Test + public void bouncingBallTest() throws Exception { + MablApiBuilder builder = new MablApiBuilder(); + + InstanceVariableFmi3Api instance = createInstance(builder, "ball", + new File("target/Fmi3ModuleReferenceFmusTest/cache/BouncingBall.fmu").getAbsoluteFile().toURI(), true); + + + + + DynamicActiveBuilderScope scope = builder.getDynamicScope(); +// DoubleVariableFmi2Api stepSize = scope.store("stepSize", instance.getModelDescription().getDefaultExperiment().getStepSize()); +// stepSize.setValue(stepSize.toMath().multiply(10d)); + DoubleVariableFmi2Api stepSize = scope.store("stepSize",0.1*10d); + + + instance.setDebugLogging(instance.getModelDescription().getLogCategories().stream().map(lc -> lc.getName()).collect(Collectors.toList()), true); + + +// instance.set(instance.getPort("v_min"),DoubleExpressionValue.of(0.1d)); + //initialize + instance.enterInitializationMode(false, 0.0, 0.0, true,instance.getModelDescription().getDefaultExperiment().getStopTime() ); + + instance.set( instance.getPort("g"),DoubleExpressionValue.of(-9.81)); + instance.set( instance.getPort("e"),DoubleExpressionValue.of(0.7d)); + instance.exitInitializationMode(); + + DataWriter dw = builder.getDataWriter(); + DataWriter.DataWriterInstance csv = dw.createDataWriterInstance(); + List outputs = instance.getPorts().stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output).collect( + Collectors.toList()); + instance.get(outputs.toArray(PortFmi3Api[]::new)); + csv.initialize( + outputs.stream() + .map(p -> new DataWriter.DataWriterInstance.LogEntry(p.getName(), () -> + + scope.copy(p.getName(),instance.get(p).values().iterator().next()).getReferenceExp().clone() + + + + )).collect( + Collectors.toList())); + + + //prepare for event handling + BooleanVariableFmi2Api stopSimulation = scope.store(false); + + BooleanVariableFmi2Api discreteStatesNeedUpdate = scope.store("discreteStatesNeedUpdate", true); + BooleanVariableFmi2Api terminateSimulation = scope.store("terminateSimulation", false); + BooleanVariableFmi2Api nominalsOfContinuousStatesChanged = scope.store("nominalsOfContinuousStatesChanged", false); + BooleanVariableFmi2Api valuesOfContinuousStatesChanged = scope.store("valuesOfContinuousStatesChanged", false); + BooleanVariableFmi2Api nextEventTimeDefined = scope.store("nextEventTimeDefined", false); + DoubleVariableFmi2Api nextEventTime = scope.store("nextEventTime", 0d); + + Supplier updateDiscreteStates = () -> { + + scope.enterWhile(discreteStatesNeedUpdate.toPredicate()); + instance.updateDiscreteStates(scope, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, + valuesOfContinuousStatesChanged, + nextEventTimeDefined, nextEventTime); + + scope.enterIf(terminateSimulation.toPredicate()); + stopSimulation.setValue(scope, BooleanExpressionValue.of(true)); + scope.add(new ABreakStm()); + scope.leave(); + scope.leave(); + return scope; + + }; + + //handle initial events + updateDiscreteStates.get(); + + //switch to step mode + instance.enterStepMode(); + + + DoubleVariableFmi2Api currentCommunicationPoint = scope.store("time", 0d); + DoubleVariableFmi2Api endTime = scope.store(3d); + + csv.log(currentCommunicationPoint); + + //loop for co-simulation + scope.enterWhile(terminateSimulation.toPredicate().not().and(currentCommunicationPoint.toMath().lessThan(endTime))); + + //determine a step size +// DoubleVariableFmi2Api stepSize = scope.store("stepSize", Collections.min(periodicConstInClocksInterval)); + + +// //step the instance + Map.Entry, InstanceVariableFmi3Api.StepResult> stepRes = instance.step(scope, currentCommunicationPoint, + stepSize, new ABoolLiteralExp(false)); + + currentCommunicationPoint.setValue(currentCommunicationPoint.toMath().addition(stepSize)); + csv.log(currentCommunicationPoint); + + + //handle events of required + scope.enterIf( + stepRes.getValue().getEventHandlingNeeded().toPredicate()); + instance.enterEventMode(); + updateDiscreteStates.get(); + + //exit to step mode + instance.enterStepMode(); + + + ASimulationSpecificationCompilationUnit program = builder.build(); + +// String test = PrettyPrinter.print(program); + + checkAndRunProgram(program); + } + + private void checkAndRunProgram(ASimulationSpecificationCompilationUnit program) throws Exception { + System.out.println(PrettyPrinter.printLineNumbers(program)); + + File workingDirectory = new File(getWorkingDirectory(null, this.getClass()),Thread.currentThread().getStackTrace()[2].getMethodName()); + workingDirectory.mkdirs(); + File specFile = new File(workingDirectory, "spec.mabl"); + FileUtils.write(specFile, PrettyPrinter.print(program), StandardCharsets.UTF_8); + + IErrorReporter reporter = new ErrorReporter(); + Mabl mabl = new Mabl(workingDirectory, workingDirectory); + mabl.setReporter(reporter); +// mabl.setVerbose(getMablVerbose()); + mabl.parse(Collections.singletonList(specFile)); + mabl.expand(); + var tcRes = mabl.typeCheck(); + mabl.verify(Framework.FMI2); + + + + if (mabl.getReporter().getErrorCount() > 0) { + mabl.getReporter().printErrors(new PrintWriter(System.err, true)); + Assertions.fail(); + } + if (mabl.getReporter().getWarningCount() > 0) { + mabl.getReporter().printWarnings(new PrintWriter(System.out, true)); + } + + mabl.dump(workingDirectory); + Map types = tcRes.getValue(); + + new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(types, name), + IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute( + MablParserUtil.parse(CharStreams.fromString(PrettyPrinter.print(program)))); + } + @Test public void test() throws Exception { MablApiBuilder builder = new MablApiBuilder(); InstanceVariableFmi3Api fd = createInstance(builder, "fd", - new File("target/Fmi3ModuleReferenceFmusTest/cache/Feedthrough.fmu").getAbsoluteFile().toURI()); + new File("target/Fmi3ModuleReferenceFmusTest/cache/Feedthrough.fmu").getAbsoluteFile().toURI(), false); InstanceVariableFmi3Api sg = createInstance(builder, "sg", - new File("src/test/resources/fmi3/reference/siggen-feedthrough/SignalGenerator.fmu").getAbsoluteFile().toURI()); + new File("src/test/resources/fmi3/reference/siggen-feedthrough/SignalGenerator.fmu").getAbsoluteFile().toURI(), false); // fd.enterInitializationMode(false, 0.0, 0.0, true, 10.0); @@ -114,8 +266,9 @@ public void testClocks() throws Exception { DynamicActiveBuilderScope scope = builder.getDynamicScope(); InstanceVariableFmi3Api instance = createInstance(builder, "clocks", - new File("target/Fmi3ModuleReferenceFmusTest/cache/Clocks.fmu").getAbsoluteFile().toURI()); + new File("src/test/resources/fmi3/sinewave_array.fmu").getAbsoluteFile().toURI(), true); + //we are not in event mode as eventModeUsed was true // fd.enterInitializationMode(false, 0.0, 0.0, true, 10.0); // sg.enterInitializationMode(false, 0.0, 0.0, true, 10.0); @@ -130,7 +283,7 @@ public void testClocks() throws Exception { instance.enterEventMode(); - FmiBuilder.IntVariable nEventIndicators = builder.getDynamicScope().store(0); + FmiBuilder.UIntVariable nEventIndicators = builder.getDynamicScope().storeUInt(0); instance.getNumberOfEventIndicators(builder.getDynamicScope(), nEventIndicators); @@ -199,14 +352,17 @@ public void testClocks() throws Exception { } @Test - @Disabled + @EnabledOnOs({LINUX}) public void testSimulateClocks() throws Exception { MablApiBuilder builder = new MablApiBuilder(); DynamicActiveBuilderScope scope = builder.getDynamicScope(); + var log = builder.getLogger(); - InstanceVariableFmi3Api instance = createInstance(builder, "clocks", - new File("src/test/resources/fmi3/sinewave_array.fmu").getAbsoluteFile().toURI()); + InstanceVariableFmi3Api instance = createInstance(builder, "i", + new File("src/test/resources/fmi3/periodic_clock.fmu").getAbsoluteFile().toURI(), true); + //we are not in event mode as eventModeUsed was true + log.log(LoggerFmi2Api.Level.INFO, "Instantiated"); // fd.enterInitializationMode(false, 0.0, 0.0, true, 10.0); // sg.enterInitializationMode(false, 0.0, 0.0, true, 10.0); @@ -219,17 +375,22 @@ public void testSimulateClocks() throws Exception { sgOutputs.stream().map(PortFmi3Api::getName).forEach(System.out::println); - instance.enterEventMode(); +// log.log(LoggerFmi2Api.Level.INFO,"Enter event mode again"); +// instance.enterEventMode(); - FmiBuilder.IntVariable nEventIndicators = builder.getDynamicScope().store(0); - instance.getNumberOfEventIndicators(builder.getDynamicScope(), nEventIndicators); - - ArrayVariableFmi2Api eventIndicators = builder.getDynamicScope() - .createArray("eventIndicators", UIntVariableFmi2Api.class, nEventIndicators); - -// FmiBuilder.ArrayVariable eventIndicators=builder.getDynamicScope().store(builder.n).storeInArray(); - instance.getEventIndicators(scope, eventIndicators, nEventIndicators); +// FmiBuilder.UIntVariable nEventIndicators = builder.getDynamicScope().storeUInt(0L); +// +// log.log(LoggerFmi2Api.Level.INFO,"getNumberOfEventIndicators"); +// instance.getNumberOfEventIndicators(builder.getDynamicScope(), nEventIndicators); +// +// +// ArrayVariableFmi2Api eventIndicators = builder.getDynamicScope() +// .createArray("eventIndicators", UIntVariableFmi2Api.class, nEventIndicators); +// +//// FmiBuilder.ArrayVariable eventIndicators=builder.getDynamicScope().store(builder.n).storeInArray(); +// log.log(LoggerFmi2Api.Level.INFO,"getEventIndicators"); +// instance.getEventIndicators(scope, eventIndicators, nEventIndicators); List outClocks = clocks.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Output) @@ -240,14 +401,16 @@ public void testSimulateClocks() throws Exception { vrs.setValue(new IntExpressionValue(i), new IntExpressionValue((int) outClocks.get(i).scalarVariable.getVariable().getValueReferenceAsLong())); } ArrayVariableFmi2Api triggeredClocks = scope.createArray("clock_get_vrs", BooleanVariableFmi2Api.class, nvr); + //this shows us the clock state of the output clocks + log.log(LoggerFmi2Api.Level.INFO, "getClock"); instance.getClock(vrs, nvr, triggeredClocks); List inClocks = clocks.stream().filter(p -> p.scalarVariable.getVariable().getCausality() == Fmi3Causality.Input) .collect(Collectors.toList()); FmiBuilder.IntVariable clock_set_nvr = scope.store("clock_in_nvr", inClocks.size()); - ArrayVariableFmi2Api clock_set_vrs = scope.createArray("clock_in_vrs", UIntVariableFmi2Api.class, nvr); - ArrayVariableFmi2Api clock_set_Clocks = scope.createArray("clock_in_vrs", BooleanVariableFmi2Api.class, nvr); + ArrayVariableFmi2Api clock_set_vrs = scope.createArray("clock_in_vrs", UIntVariableFmi2Api.class, clock_set_nvr); + ArrayVariableFmi2Api clock_set_Clocks = scope.createArray("clock_in_vrs_values", BooleanVariableFmi2Api.class, clock_set_nvr); for (int i = 0; i < inClocks.size(); i++) { clock_set_vrs.setValue(new IntExpressionValue(i), new IntExpressionValue((int) inClocks.get(i).scalarVariable.getVariable().getValueReferenceAsLong())); @@ -255,88 +418,94 @@ public void testSimulateClocks() throws Exception { } instance.setClock(clock_set_vrs, clock_set_nvr, clock_set_Clocks); + instance.setDebugLogging(instance.getModelDescription().getLogCategories().stream().map(lc -> lc.getName()).collect(Collectors.toList()), true); - FmiBuilder.DoubleVariable currentCommunicationPoint = scope.store("time", 0d); - FmiBuilder.DoubleVariable stepSize = scope.store("step", 0.1d); - Map.Entry, InstanceVariableFmi3Api.StepResult> stepRes = instance.step(scope, currentCommunicationPoint, - stepSize, new ABoolLiteralExp(false)); + //initialize + instance.enterInitializationMode(false, 0.0, 0.0, true, 10d); - IfMaBlScope eventHandlingScope = scope.enterIf( - stepRes.getValue().getEventHandlingNeeded().toPredicate()); + instance.exitInitializationMode(); - instance.enterEventMode(); + //prepare for event handling + BooleanVariableFmi2Api stopSimulation = scope.store(false); + + BooleanVariableFmi2Api discreteStatesNeedUpdate = scope.store("discreteStatesNeedUpdate", true); + BooleanVariableFmi2Api terminateSimulation = scope.store("terminateSimulation", false); + BooleanVariableFmi2Api nominalsOfContinuousStatesChanged = scope.store("nominalsOfContinuousStatesChanged", false); + BooleanVariableFmi2Api valuesOfContinuousStatesChanged = scope.store("valuesOfContinuousStatesChanged", false); + BooleanVariableFmi2Api nextEventTimeDefined = scope.store("nextEventTimeDefined", false); + DoubleVariableFmi2Api nextEventTime = scope.store("nextEventTime", 0d); + + Supplier updateDiscreteStates = () -> { + + scope.enterWhile(discreteStatesNeedUpdate.toPredicate()); + instance.updateDiscreteStates(scope, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, + valuesOfContinuousStatesChanged, + nextEventTimeDefined, nextEventTime); + + scope.enterIf(terminateSimulation.toPredicate()); + stopSimulation.setValue(scope, BooleanExpressionValue.of(true)); + scope.add(new ABreakStm()); + scope.leave(); + scope.leave(); + return scope; + }; -//handle events - BooleanVariableFmi2Api discreteStatesNeedUpdate = scope.store("discreteStatesNeedUpdate",false); - BooleanVariableFmi2Api terminateSimulation = scope.store("terminateSimulation",false); - BooleanVariableFmi2Api nominalsOfContinuousStatesChanged = scope.store("nominalsOfContinuousStatesChanged",false); - BooleanVariableFmi2Api valuesOfContinuousStatesChanged = scope.store("valuesOfContinuousStatesChanged",false); - BooleanVariableFmi2Api nextEventTimeDefined = scope.store("nextEventTimeDefined",false); - DoubleVariableFmi2Api nextEventTime = scope.store("nextEventTime",0d); - instance.updateDiscreteStates(scope, discreteStatesNeedUpdate, terminateSimulation, nominalsOfContinuousStatesChanged, valuesOfContinuousStatesChanged, - nextEventTimeDefined, nextEventTime); + //handle initial events + updateDiscreteStates.get(); + //switch to step mode instance.enterStepMode(); + List periodicConstInClocks = clocks.stream().filter(p -> p.scalarVariable.getVariable() + .getCausality() == Fmi3Causality.Input && p.scalarVariable.getVariable() instanceof ClockVariable && ((ClockVariable) p.scalarVariable.getVariable()).getInterval() == Fmi3ClockInterval.Constant) + .collect(Collectors.toList()); + List periodicConstInClocksInterval = clocks.stream().filter(p -> p.scalarVariable.getVariable() + .getCausality() == Fmi3Causality.Input && p.scalarVariable.getVariable() instanceof ClockVariable && ((ClockVariable) p.scalarVariable.getVariable()).getInterval() == Fmi3ClockInterval.Constant) + .map(p -> ((ClockVariable) p.scalarVariable.getVariable()).getIntervalDecimal()).collect(Collectors.toList()); -// stepRes.getValue().getLastSuccessfulTime() + List constantPeriodicClocks = clocks.stream().filter(p -> p.scalarVariable.getVariable() + .getCausality() == Fmi3Causality.Input && p.scalarVariable.getVariable() instanceof ClockVariable && ((ClockVariable) p.scalarVariable.getVariable()).getInterval() == Fmi3ClockInterval.Constant) + .collect( + Collectors.toList()); -// instance.g -// for (PortFmi3Api o : sgOutputs) { -// sg.get(o); -// } + DoubleVariableFmi2Api currentCommunicationPoint = scope.store("time", 0d); + DoubleVariableFmi2Api endTime = scope.store(4d); -// System.out.println("Linked ports"); -// sg.getPorts().stream().filter(PortFmi3Api::isLinked).forEach(System.out::println); -// System.out.println("---Linked ports"); -// sg.getPort("Int8_output").linkTo(fd.getPort("Int8_input")); -// sg.getPort("UInt8_output").linkTo(fd.getPort("UInt8_input")); -// System.out.println("Linked ports"); -// sg.getPorts().stream().filter(PortFmi3Api::isLinked).forEach(System.out::println); -// System.out.println("---Linked ports"); -// sg.getAndShare(); -// fd.setLinked(); + //loop for co-simulation + scope.enterWhile(terminateSimulation.toPredicate().not().and(currentCommunicationPoint.toMath().lessThan(endTime))); -// fd.exitInitializationMode(); + //determine a step size + DoubleVariableFmi2Api stepSize = scope.store("stepSize", Collections.min(periodicConstInClocksInterval)); - ASimulationSpecificationCompilationUnit program = builder.build(); -// String test = PrettyPrinter.print(program); +// //step the instance + Map.Entry, InstanceVariableFmi3Api.StepResult> stepRes = instance.step(scope, currentCommunicationPoint, + stepSize, new ABoolLiteralExp(false)); - System.out.println(PrettyPrinter.printLineNumbers(program)); + currentCommunicationPoint.setValue(currentCommunicationPoint.toMath().addition(stepSize)); - File workingDirectory=getWorkingDirectory(null,this.getClass()); - File specFile = new File(workingDirectory, "spec.mabl"); - FileUtils.write(specFile,PrettyPrinter.print(program),StandardCharsets.UTF_8); + //handle events of required + scope.enterIf( + stepRes.getValue().getEventHandlingNeeded().toPredicate()); + instance.enterEventMode(); + updateDiscreteStates.get(); - IErrorReporter reporter = new ErrorReporter(); - Mabl mabl = new Mabl(workingDirectory, workingDirectory); - mabl.setReporter(reporter); -// mabl.setVerbose(getMablVerbose()); -mabl.parse(Collections.singletonList(specFile)); - mabl.expand(); - var tcRes = mabl.typeCheck(); - mabl.verify(Framework.FMI2); + //exit to step mode + instance.enterStepMode(); + //program done; - if (mabl.getReporter().getErrorCount() > 0) { - mabl.getReporter().printErrors(new PrintWriter(System.err, true)); - Assertions.fail(); - } - if (mabl.getReporter().getWarningCount() > 0) { - mabl.getReporter().printWarnings(new PrintWriter(System.out, true)); - } + ASimulationSpecificationCompilationUnit program = builder.build(); - mabl.dump(workingDirectory); - Map types = tcRes.getValue(); +// String test = PrettyPrinter.print(program); - new MableInterpreter(new DefaultExternalValueFactory(workingDirectory, name -> TypeChecker.findModule(types, name), - IOUtils.toInputStream(mabl.getRuntimeDataAsJsonString(), StandardCharsets.UTF_8))).execute(MablParserUtil.parse(CharStreams.fromString(PrettyPrinter.print(program)))); + checkAndRunProgram(program); } + static File getWorkingDirectory(File base, Class cls) throws IOException { - String s = Paths.get("target", cls.getSimpleName()).toString() + File.separatorChar + (base==null?"":base.getAbsolutePath().substring( + String s = Paths.get("target", cls.getSimpleName()).toString() + File.separatorChar + (base == null ? "" : base.getAbsolutePath().substring( base.getAbsolutePath().replace(File.separatorChar, '/').indexOf("src/test/resources/") + ("src" + "/test" + "/resources/").length())); File workingDir = new File(s.replace('/', File.separatorChar)); diff --git a/maestro/src/test/resources/fmi3/periodic_clock.fmu b/maestro/src/test/resources/fmi3/periodic_clock.fmu new file mode 100644 index 00000000..b71c3c94 Binary files /dev/null and b/maestro/src/test/resources/fmi3/periodic_clock.fmu differ diff --git a/maestro/src/test/resources/fmi3/sinewave_array.fmu b/maestro/src/test/resources/fmi3/sinewave_array.fmu new file mode 100644 index 00000000..0d91d667 Binary files /dev/null and b/maestro/src/test/resources/fmi3/sinewave_array.fmu differ diff --git a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java index 4f84d36f..f7d6ea17 100644 --- a/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java +++ b/typechecker/src/main/java/org/intocps/maestro/typechecker/TypeCheckVisitor.java @@ -14,6 +14,7 @@ import org.intocps.maestro.typechecker.context.ModulesContext; import java.util.*; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.stream.Collectors; @@ -490,7 +491,11 @@ public PType caseAVariableDeclaration(AVariableDeclaration node, Context ctxt) t } else if (node.getInitializer() != null) { PType initType = node.getInitializer().apply(this, ctxt); - if (!typeComparator.compatible(type, initType)) { + + BiFunction isDoubleToFloatAssignment = (declType, assignType)-> + typeComparator.compatible(declType,new AFloatNumericPrimitiveType())&&typeComparator.compatible(assignType,new ARealNumericPrimitiveType()); + + if (!typeComparator.compatible(type, initType) && !isDoubleToFloatAssignment.apply(type,initType)) { errorReporter.report(0, type + " cannot be initialized with type: " + initType, node.getName().getSymbol()); } @@ -717,22 +722,11 @@ public PType caseAStringLiteralExp(AStringLiteralExp node, Context ctxt) throws @Override public PType caseARealLiteralExp(ARealLiteralExp node, Context ctxt) throws AnalysisException { + return store(node, detectType(node.getValue())); + } - // double value = node.getValue(); - // if (Math.round(value) == value) { - // if (value < 0) { - // return store(node, MableAstFactory.newIntType()); - // } else if (value == 0) { - // - // //nat - // return store(node, MableAstFactory.newIntType()); - // } else { - // //natone - // return store(node, MableAstFactory.newIntType()); - // } - // } else { - // return store(node, MableAstFactory.newRealType()); // Note, "1.234" is really "1234/1000" (a rat) - // } + @Override + public PType caseAFloatLiteralExp(AFloatLiteralExp node, Context ctxt) throws AnalysisException { return store(node, detectType(node.getValue())); } diff --git a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl index 339599ae..de41c33e 100644 --- a/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl +++ b/typechecker/src/main/resources/org/intocps/maestro/typechecker/FMI3.mabl @@ -252,7 +252,7 @@ module FMI3Instance /* end::getDerivatives[] */ /* tag::getEventIndicators[] */ - int getEventIndicators(out uint[] eventIndicators, int nEventIndicators); + int getEventIndicators(out uint[] eventIndicators, uint nEventIndicators); /* end::getEventIndicators[] */ /* tag::getContinuousStates[] */