Skip to content

Commit

Permalink
Dump annotation array elements separately (#12325)
Browse files Browse the repository at this point in the history
- Dump elements of array expressions in annotations separately, to avoid
  e.g. an invalid graphical element invalidating the whole graphics
  arrays.
  • Loading branch information
perost committed Apr 26, 2024
1 parent 34180dc commit 2757559
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 33 deletions.
32 changes: 32 additions & 0 deletions OMCompiler/Compiler/FrontEnd/AbsynUtil.mo
Expand Up @@ -6608,5 +6608,37 @@ algorithm
end match;
end setClassDefType;

function isLiteralExp
input Absyn.Exp exp;
output Boolean literal;
algorithm
literal := match exp
case Absyn.Exp.INTEGER() then true;
case Absyn.Exp.REAL() then true;
case Absyn.Exp.STRING() then true;
case Absyn.Exp.BOOL() then true;
case Absyn.Exp.ARRAY() then List.all(exp.arrayExp, isLiteralExp);

case Absyn.Exp.MATRIX()
algorithm
literal := true;
for row in exp.matrix loop
literal := literal and List.all(row, isLiteralExp);
if not literal then
break;
end if;
end for;
then
literal;

case Absyn.Exp.RANGE()
then isLiteralExp(exp.start) and
Util.applyOptionOrDefault(exp.step, isLiteralExp, true) and
isLiteralExp(exp.stop);

else false;
end match;
end isLiteralExp;

annotation(__OpenModelica_Interface="frontend");
end AbsynUtil;
76 changes: 57 additions & 19 deletions OMCompiler/Compiler/Script/NFApi.mo
Expand Up @@ -1793,25 +1793,8 @@ algorithm

case (_, SCode.Mod.MOD(binding = SOME(absyn_binding)))
algorithm
ErrorExt.setCheckpoint(getInstanceName());

try
binding_exp := Inst.instExp(absyn_binding, scope, ANNOTATION_CONTEXT, mod.info);
binding_exp := Typing.typeExp(binding_exp, ANNOTATION_CONTEXT, mod.info);
binding_exp := SimplifyExp.simplify(binding_exp);
json := JSON.addPair(name, Expression.toJSON(binding_exp), json);
else
if failOnError then
fail();
end if;

j := JSON.makeNull();
j := JSON.addPair("$error", JSON.makeString(ErrorExt.printCheckpointMessagesStr()), j);
j := JSON.addPair("value", dumpJSONAbsynExpression(absyn_binding), j);
json := JSON.addPair(name, j, json);
end try;

ErrorExt.delCheckpoint(getInstanceName());
j := dumpJSONAnnotationExp(absyn_binding, scope, mod.info, failOnError);
json := JSON.addPair(name, j, json);
then
();

Expand All @@ -1825,6 +1808,61 @@ algorithm
end match;
end dumpJSONAnnotationSubMod;

function dumpJSONAnnotationExp
input Absyn.Exp absynExp;
input InstNode scope;
input SourceInfo info;
input Boolean failOnError;
output JSON json;
protected
JSON j;
algorithm
json := match absynExp
// For non-literal arrays, dump each element separately to avoid
// invalidating the whole array expression if any element contains invalid
// expressions.
case Absyn.Exp.ARRAY()
guard not AbsynUtil.isLiteralExp(absynExp)
algorithm
json := JSON.emptyArray(listLength(absynExp.arrayExp));
for e in absynExp.arrayExp loop
j := dumpJSONAnnotationExp2(e, scope, info, failOnError);
json := JSON.addElement(j, json);
end for;
then
json;

else dumpJSONAnnotationExp2(absynExp, scope, info, failOnError);
end match;
end dumpJSONAnnotationExp;

function dumpJSONAnnotationExp2
input Absyn.Exp absynExp;
input InstNode scope;
input SourceInfo info;
input Boolean failOnError;
output JSON json;
protected
Expression exp;
algorithm
ErrorExt.setCheckpoint(getInstanceName());
try
exp := Inst.instExp(absynExp, scope, ANNOTATION_CONTEXT, info);
exp := Typing.typeExp(exp, ANNOTATION_CONTEXT, info);
exp := SimplifyExp.simplify(exp);
json := Expression.toJSON(exp);
else
if failOnError then
fail();
end if;

json := JSON.makeNull();
json := JSON.addPair("$error", JSON.makeString(ErrorExt.printCheckpointMessagesStr()), json);
json := JSON.addPair("value", dumpJSONAbsynExpression(absynExp), json);
end try;
ErrorExt.delCheckpoint(getInstanceName());
end dumpJSONAnnotationExp2;

function dumpJSONSourceInfo
input SourceInfo info;
output JSON json = JSON.makeNull();
Expand Down
14 changes: 14 additions & 0 deletions doc/instanceAPI/expression.schema.json
Expand Up @@ -429,6 +429,20 @@
}
},
"required": ["$kind", "name", "arguments"]
},
{
"description": "An invalid expression",
"type": "object",
"properties": {
"$error": {
"description": "Error message",
"type": "string"
},
"value": {
"description": "The invalid expression",
"$ref": "#"
}
}
}
],
"definitions": {
Expand Down
14 changes: 0 additions & 14 deletions doc/instanceAPI/getModelInstance.schema.json
Expand Up @@ -132,20 +132,6 @@
},
{
"$ref": "expression.schema.json"
},
{
"description": "An invalid annotation",
"type": "object",
"properties": {
"$error": {
"description": "Error message",
"type": "string"
},
"value": {
"description": "Annotation dumped as a string",
"type": "string"
}
}
}
]
}
Expand Down
115 changes: 115 additions & 0 deletions testsuite/openmodelica/instance-API/GetModelInstanceAnnotation12.mos
@@ -0,0 +1,115 @@
// name: GetModelInstanceAnnotation12
// keywords:
// status: correct
// cflags: -d=newInst
//
//

loadString("
model M
annotation(Icon(graphics = {Rectangle(extent = {{1, 1}, {2, x}}), Text(textString = \"str\")}));
end M;
");

getModelInstance(M, prettyPrint=true);
getErrorString();

// Result:
// true
// "{
// \"name\": \"M\",
// \"restriction\": \"model\",
// \"annotation\": {
// \"Icon\": {
// \"graphics\": [
// {
// \"$error\": \"[<interactive>:3:21-3:96:writable] Error: Variable x not found in scope M.\\n\",
// \"value\": {
// \"$kind\": \"call\",
// \"name\": \"Rectangle\",
// \"namedArgs\": {
// \"extent\": [
// [
// 1,
// 1
// ],
// [
// 2,
// \"x\"
// ]
// ]
// }
// }
// },
// {
// \"$kind\": \"record\",
// \"name\": \"Text\",
// \"elements\": [
// true,
// [
// 0,
// 0
// ],
// 0,
// [
// 0,
// 0,
// 0
// ],
// [
// 0,
// 0,
// 0
// ],
// {
// \"$kind\": \"enum\",
// \"name\": \"LinePattern.Solid\",
// \"index\": 2
// },
// {
// \"$kind\": \"enum\",
// \"name\": \"FillPattern.None\",
// \"index\": 1
// },
// 0.25,
// [
// [
// -10,
// -10
// ],
// [
// 10,
// 10
// ]
// ],
// \"str\",
// 0,
// [
// -1,
// -1,
// -1
// ],
// \"\",
// [
//
// ],
// {
// \"$kind\": \"enum\",
// \"name\": \"TextAlignment.Center\",
// \"index\": 2
// }
// ]
// }
// ]
// }
// },
// \"source\": {
// \"filename\": \"<interactive>\",
// \"lineStart\": 2,
// \"columnStart\": 3,
// \"lineEnd\": 4,
// \"columnEnd\": 8
// }
// }"
// ""
// endResult
1 change: 1 addition & 0 deletions testsuite/openmodelica/instance-API/Makefile
Expand Up @@ -13,6 +13,7 @@ GetModelInstanceAnnotation8.mos \
GetModelInstanceAnnotation9.mos \
GetModelInstanceAnnotation10.mos \
GetModelInstanceAnnotation11.mos \
GetModelInstanceAnnotation12.mos \
GetModelInstanceAttributes1.mos \
GetModelInstanceAttributes2.mos \
GetModelInstanceBinding1.mos \
Expand Down

0 comments on commit 2757559

Please sign in to comment.