Skip to content

Commit

Permalink
Port API changes to 1.22 (#11572)
Browse files Browse the repository at this point in the history
* Improve InteractiveUtil.mergeElementArgs

- Remove empty submodifiers recursively after merging modifiers in
  mergeElementArgs.

* Filter more empty modifiers in mergeElementArgs

- Also filter out empty modifiers in new modifiers in
  InteractiveUtil.mergeElementArgs.

* Don't fail on invalid each usage in getModelInstance

* Dump redeclares as structures in getModelInstance (#11518)

- Dump redeclare modifiers as JSON structures in getModelInstance
  instead of just strings when `-d=structuredRedeclare` is set.
  • Loading branch information
perost committed Nov 14, 2023
1 parent dff6443 commit 9a45285
Show file tree
Hide file tree
Showing 15 changed files with 516 additions and 96 deletions.
5 changes: 4 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFTypeCheck.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2862,7 +2862,10 @@ algorithm
if not isValidAssignmentMatch(ty_match) then
binding.bindingExp := Expression.expandSplitIndices(exp);
printBindingTypeError(name, binding, comp_ty, bind_ty, component, context);
fail();

if not InstContext.inInstanceAPI(context) then
fail();
end if;
elseif isCastMatch(ty_match) then
binding := Binding.TYPED_BINDING(exp, ty, binding.variability, binding.eachType,
binding.evalState, binding.isFlattened, binding.source, binding.info);
Expand Down
30 changes: 28 additions & 2 deletions OMCompiler/Compiler/Script/InteractiveUtil.mo
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ protected
Boolean found;
algorithm
if listEmpty(inOldArgs) then
outArgs := inNewArgs;
outArgs := removeEmptySubMods(inNewArgs);
elseif listEmpty(inNewArgs) then
outArgs := inOldArgs;
else
Expand All @@ -616,10 +616,36 @@ algorithm
end if;
end for;

outArgs := list(arg for arg guard not AbsynUtil.isEmptySubMod(arg) in outArgs);
outArgs := removeEmptySubMods(outArgs);
end if;
end mergeElementArgs;

function removeEmptySubMods
input list<Absyn.ElementArg> subMods;
output list<Absyn.ElementArg> outSubMods = {};
protected
Absyn.Modification mod;
algorithm
for m in subMods loop
() := match m
case Absyn.ElementArg.MODIFICATION(modification = SOME(mod))
algorithm
mod.elementArgLst := removeEmptySubMods(mod.elementArgLst);
m.modification := if AbsynUtil.isEmptyMod(mod) then NONE() else SOME(mod);
then
();

else ();
end match;

if not AbsynUtil.isEmptySubMod(m) then
outSubMods := m :: outSubMods;
end if;
end for;

outSubMods := Dangerous.listReverseInPlace(outSubMods);
end removeEmptySubMods;

protected function propagateMod2
input Absyn.Path inComponentName;
input list<Absyn.ElementArg> inSubMods;
Expand Down
178 changes: 124 additions & 54 deletions OMCompiler/Compiler/Script/NFApi.mo
Original file line number Diff line number Diff line change
Expand Up @@ -1284,44 +1284,7 @@ protected
algorithm
node := InstNode.getRedeclaredNode(cls);
elem := InstNode.definition(node);

json := JSON.addPair("$kind", JSON.makeString("class"), json);
json := JSON.addPair("name", JSON.makeString(InstNode.name(node)), json);
json := JSON.addPair("restriction",
JSON.makeString(SCodeDump.restrictionStringPP(SCodeUtil.getClassRestriction(elem))), json);
json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(elem, scope), json);

SCode.Element.CLASS(classDef = cdef, cmt = cmt) := elem;

() := match cdef
case SCode.ClassDef.DERIVED(typeSpec = Absyn.TypeSpec.TPATH(path = path, arrayDim = odims))
algorithm
try
derivedNode := Lookup.lookupName(path, scope, NFInstContext.RELAXED, false);
json := JSON.addPair("baseClass", dumpJSONNodeEnclosingPath(derivedNode), json);
else
end try;

if isSome(odims) then
json := JSON.addPairNotNull("dims", dumpJSONDims(Util.getOption(odims), {}), json);
end if;

json := dumpJSONSCodeMod(cdef.modifications, scope, json);
then
();

case SCode.ClassDef.CLASS_EXTENDS()
algorithm
json := dumpJSONSCodeMod(cdef.modifications, scope, json);
then
();

else ();
end match;

json := dumpJSONCommentOpt(SOME(cmt), scope, json);
json := dumpJSONCommentAnnotation(SOME(cmt), scope, json,
{"Dialog", "choices", "choicesAllMatching"});
json := dumpJSONSCodeClass(elem, scope, true, json);
json := JSON.addPair("source", dumpJSONSourceInfo(InstNode.info(node)), json);
end dumpJSONReplaceableClass;

Expand Down Expand Up @@ -1365,7 +1328,7 @@ algorithm
();

case (Component.COMPONENT(), SCode.Element.COMPONENT())
algorithm
algorithm
json := JSON.addPair("$kind", JSON.makeString("component"), json);
json := JSON.addPair("name", JSON.makeString(InstNode.name(node)), json);
json := JSON.addPair("type", dumpJSONComponentType(cls, node, comp.ty), json);
Expand Down Expand Up @@ -1548,21 +1511,25 @@ function dumpJSONDims
protected
JSON ty_json, absyn_json;
algorithm
absyn_json := JSON.emptyArray();
for d in absynDims loop
absyn_json := JSON.addElement(JSON.makeString(Dump.printSubscriptStr(d)), absyn_json);
end for;
json := JSON.addPairNotNull("absyn", dumpJSONAbsynDims(absynDims), json);

json := JSON.addPairNotNull("absyn", absyn_json, json);

ty_json := JSON.emptyArray();
ty_json := JSON.makeNull();
for d in typedDims loop
ty_json := JSON.addElement(JSON.makeString(Dimension.toString(d)), ty_json);
end for;

json := JSON.addPairNotNull("typed", ty_json, json);
end dumpJSONDims;

function dumpJSONAbsynDims
input list<Absyn.Subscript> dims;
output JSON json = JSON.makeNull();
algorithm
for d in dims loop
json := JSON.addElement(JSON.makeString(Dump.printSubscriptStr(d)), json);
end for;
end dumpJSONAbsynDims;

function dumpJSONAttributes
input SCode.Attributes attrs;
input SCode.Prefixes prefs;
Expand Down Expand Up @@ -2125,17 +2092,21 @@ algorithm
json := JSON.addPair("each", JSON.makeBoolean(true), json);
end if;

json := JSON.addPair("redeclare", JSON.makeBoolean(true), json);
if Flags.isSet(Flags.STRUCTURED_REDECLARE) then
json := JSON.addPair("$value", dumpJSONSCodeElement(mod.element, scope), json);
else
json := JSON.addPair("redeclare", JSON.makeBoolean(true), json);

if SCodeUtil.isElementReplaceable(mod.element) then
json := JSON.addPair("replaceable", JSON.makeBoolean(true), json);
end if;
if SCodeUtil.isElementReplaceable(mod.element) then
json := JSON.addPair("replaceable", JSON.makeBoolean(true), json);
end if;

binding_json := JSON.makeString(SCodeDump.unparseElementStr(mod.element));
json := JSON.addPair("$value", binding_json, json);
binding_json := JSON.makeString(SCodeDump.unparseElementStr(mod.element));
json := JSON.addPair("$value", binding_json, json);

if isChoices then
json := dumpJSONRedeclareType(mod.element, scope, json);
if isChoices then
json := dumpJSONRedeclareType(mod.element, scope, json);
end if;
end if;
then
();
Expand Down Expand Up @@ -2167,6 +2138,105 @@ algorithm
end matchcontinue;
end dumpJSONRedeclareType;

function dumpJSONSCodeElement
input SCode.Element element;
input InstNode scope;
input output JSON json = JSON.makeNull();
algorithm
json := match element
case SCode.Element.COMPONENT()
algorithm
json := JSON.addPair("$kind", JSON.makeString("component"), json);
json := JSON.addPair("name", JSON.makeString(element.name), json);
json := JSON.addPair("type", dumpJSONPath(AbsynUtil.typeSpecPath(element.typeSpec)), json);
json := JSON.addPairNotNull("dims", dumpJSONDims(element.attributes.arrayDims, {}), json);
json := dumpJSONSCodeMod(element.modifications, scope, json);
json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(element.attributes, element.prefixes, scope), json);

if isSome(element.condition) then
json := JSON.addPair("condition", dumpJSONAbsynExpression(Util.getOption(element.condition)), json);
end if;

json := dumpJSONCommentOpt(SOME(element.comment), scope, json);
then
json;

case SCode.Element.CLASS()
then dumpJSONSCodeClass(element, scope, false, json);

else json;
end match;
end dumpJSONSCodeElement;

function dumpJSONSCodeClass
input SCode.Element element;
input InstNode scope;
input Boolean isRedeclare;
input output JSON json = JSON.makeNull();
protected
Option<list<Absyn.Subscript>> odims;
algorithm
() := match element
case SCode.CLASS()
algorithm
json := JSON.addPair("$kind", JSON.makeString("class"), json);
json := JSON.addPair("name", JSON.makeString(element.name), json);
json := JSON.addPair("restriction",
JSON.makeString(SCodeDump.restrictionStringPP(element.restriction)), json);
json := JSON.addPairNotNull("prefixes", dumpJSONClassPrefixes(element, scope), json);
json := dumpJSONSCodeClassDef(element.classDef, scope, isRedeclare, json);
json := dumpJSONCommentOpt(SOME(element.cmt), scope, json, dumpAnnotation = not isRedeclare);

if isRedeclare then
json := dumpJSONCommentAnnotation(SOME(element.cmt), scope, json,
{"Dialog", "choices", "choicesAllMatching"});
end if;
then
();
end match;
end dumpJSONSCodeClass;

function dumpJSONSCodeClassDef
input SCode.ClassDef classDef;
input InstNode scope;
input Boolean qualifyPath;
input output JSON json;
protected
Absyn.Path path;
Option<list<Absyn.Subscript>> odims;
InstNode derivedNode;
algorithm
() := match classDef
case SCode.ClassDef.DERIVED(typeSpec = Absyn.TypeSpec.TPATH(path = path, arrayDim = odims))
algorithm
if qualifyPath then
try
derivedNode := Lookup.lookupName(path, scope, NFInstContext.RELAXED, false);
json := JSON.addPair("baseClass", dumpJSONNodeEnclosingPath(derivedNode), json);
else
end try;
else
json := JSON.addPair("baseClass", dumpJSONPath(path), json);
end if;

if isSome(odims) then
json := JSON.addPairNotNull("dims", dumpJSONDims(Util.getOption(odims), {}), json);
end if;

json := dumpJSONSCodeMod(classDef.modifications, scope, json);
then
();

case SCode.ClassDef.CLASS_EXTENDS()
algorithm
json := dumpJSONSCodeMod(classDef.modifications, scope, json);
then
();

else ();
end match;
end dumpJSONSCodeClassDef;

function dumpJSONChoicesAnnotation
input list<SCode.SubMod> mods;
input InstNode scope;
Expand Down
2 changes: 2 additions & 0 deletions OMCompiler/Compiler/Util/Flags.mo
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@ constant DebugFlag DUMP_EVENTS = DEBUG_FLAG(193, "dumpEvents", false,
Gettext.gettext("Dumps information about the detected event functions."));
constant DebugFlag DUMP_BINDINGS = DEBUG_FLAG(194, "dumpBindings", false,
Gettext.gettext("Dumps information about the equations created from bindings."));
constant DebugFlag STRUCTURED_REDECLARE = DEBUG_FLAG(195, "structuredRedeclare", false,
Gettext.gettext("Dumps redeclares as structures in getModelInstance."));

public
// CONFIGURATION FLAGS
Expand Down
3 changes: 2 additions & 1 deletion OMCompiler/Compiler/Util/FlagsUtil.mo
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ constant list<Flags.DebugFlag> allDebugFlags = {
Flags.DUMP_SLICE,
Flags.VECTORIZE_BINDINGS,
Flags.DUMP_EVENTS,
Flags.DUMP_BINDINGS
Flags.DUMP_BINDINGS,
Flags.STRUCTURED_REDECLARE
};

protected
Expand Down
39 changes: 26 additions & 13 deletions doc/instanceAPI/getModelInstance.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@
"$ref": "#"
},
{
"description": "Builtin type",
"description": "A builtin or Absyn type",
"type": "string"
},
{
Expand Down Expand Up @@ -424,6 +424,19 @@
},
"required": ["binding"]
},
"scodeElement": {
"description": "An SCode element",
"oneOf": [
{
"description": "A component declaration",
"$ref": "#/definitions/component"
},
{
"description": "A class declaration",
"$ref": "#/definitions/replaceableClass"
}
]
},
"scodeModifier": {
"description": "An SCode modifier",
"oneOf": [
Expand All @@ -435,13 +448,9 @@
"type": "object",
"description": "A modifier with submodifiers",
"properties": {
"$value": {
"type": "string",
"description": "The string representation of the binding equation"
},
"$type": {
"type": "string",
"description": "The fully qualified type name of a redeclare element"
"description": "The fully qualified type name of a redeclare element in a choices annotation"
}
"final": {
"type": "boolean",
Expand All @@ -451,13 +460,17 @@
"type": "boolean",
"description": "Whether the modifier is each or not"
},
"redeclare": {
"type": "boolean",
"description": "Whether the modifier is a redeclare or not"
},
"replaceable": {
"type": "boolean",
"description": "Whether the modifier is a replaceable or not"
"$value": {
"oneOf": [
{
"type": "string",
"description": "The binding equation of a modifier"
},
{
"description": "The element declaration of a redeclare",
"$ref": "#/definitions/scodeElement"
}
]
}
},
"additionalProperties": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ getErrorString();
// \"name\": \"x\",
// \"type\": \"Real\",
// \"modifiers\": \"\\\"s\\\"\",
// \"value\": {
// \"binding\": \"s\"
// },
// \"prefixes\": {
// \"variability\": \"parameter\"
// }
Expand All @@ -38,5 +41,6 @@ getErrorString();
// \"columnEnd\": 8
// }
// }"
// ""
// "[<interactive>:3:5-3:27:writable] Error: Type mismatch in binding x = \"s\", expected subtype of Real, got type String.
// "
// endResult

0 comments on commit 9a45285

Please sign in to comment.