Skip to content

Commit

Permalink
Treat singleton uniontypes as records
Browse files Browse the repository at this point in the history
- Make it possible to access singleton records using dot-notation.
- LHS and RHS expressions have been tested for now and is working.
  • Loading branch information
sjoelund authored and OpenModelica-Hudson committed Jul 3, 2015
1 parent 0e1c517 commit 0693901
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 49 deletions.
4 changes: 3 additions & 1 deletion Compiler/FrontEnd/DAE.mo
Expand Up @@ -819,7 +819,7 @@ constant Type T_FUNCTION_DEFAULT = T_FUNCTION({},T_ANYTYPE_DEFAULT,FUNCTION_A
constant Type T_METATYPE_DEFAULT = T_METATYPE(T_UNKNOWN_DEFAULT, emptyTypeSource);
constant Type T_COMPLEX_DEFAULT = T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("")), {}, NONE(), emptyTypeSource) "default complex with unknown CiState";
constant Type T_COMPLEX_DEFAULT_RECORD = T_COMPLEX(ClassInf.RECORD(Absyn.IDENT("")), {}, NONE(), emptyTypeSource) "default complex with record CiState";
constant Type T_SOURCEINFO_DEFAULT = T_METAUNIONTYPE({Absyn.QUALIFIED("SourceInfo",Absyn.IDENT("SOURCEINFO"))},true,Absyn.IDENT("SourceInfo")::{});
constant Type T_SOURCEINFO_DEFAULT = T_METAUNIONTYPE({Absyn.QUALIFIED("SourceInfo",Absyn.IDENT("SOURCEINFO"))},true,{"fileName","isReadOnly","lineNumberStart","columnNumberStart","lineNumberEnd","columnNumberEnd","lastModification"},Absyn.IDENT("SourceInfo")::{});

// Arrays of unknown dimension, eg. Real[:]
public constant Type T_ARRAY_REAL_NODIM = T_ARRAY(T_REAL_DEFAULT,{DIM_UNKNOWN()}, emptyTypeSource);
Expand Down Expand Up @@ -948,8 +948,10 @@ public uniontype Type "models the different front-end and back-end types"
end T_METAOPTION;

record T_METAUNIONTYPE "MetaModelica Uniontype, added by simbj"
// TODO: You can't trust these fields as it seems MetaUtil.fixUniontype is sent empty elements when running dependency analysis
list<Absyn.Path> paths;
Boolean knownSingleton "The runtime system (dynload), does not know if the value is a singleton. But optimizations are safe if this is true.";
list<String> singletonFields "The field names of the singleton";
TypeSource source;
end T_METAUNIONTYPE;

Expand Down
87 changes: 48 additions & 39 deletions Compiler/FrontEnd/Lookup.mo
Expand Up @@ -2698,7 +2698,7 @@ protected function lookupVarF
output String name;
algorithm
(outCache,outAttributes,outType,outBinding,constOfForIteratorRange,splicedExpData,outComponentEnv,name) :=
matchcontinue (inCache,inBinTree,inComponentRef,inEnv)
match (inCache,inBinTree,inComponentRef,inEnv)
local
String id,id2;
SCode.ConnectorType ct;
Expand All @@ -2723,6 +2723,7 @@ algorithm
DAE.Attributes attr;
list<DAE.Var> fields;
Option<DAE.Exp> oSplicedExp;
Absyn.Path p;

// Simple identifier
case (cache,ht,DAE.CREF_IDENT(ident = id,subscriptLst = ss),_)
Expand All @@ -2739,50 +2740,58 @@ algorithm

// Qualified variables looked up through component environment with or without spliced exp
case (cache,ht,DAE.CREF_QUAL(ident = id,subscriptLst = ss,componentRef = ids), _)
equation
(DAE.TYPES_VAR(_,DAE.ATTR(variability = vt2),tyParent,parentBinding,_),_,_,_,componentEnv) = lookupVar2(ht, id, inEnv);
algorithm
(DAE.TYPES_VAR(_,DAE.ATTR(variability = vt2),tyParent,parentBinding,_),_,_,_,componentEnv) := lookupVar2(ht, id, inEnv);

// leave just the last scope from component env as it SHOULD BE ONLY THERE, i.e. don't go on searching the parents!
// componentEnv = FGraph.setScope(componentEnv, List.create(FGraph.lastScopeRef(componentEnv)));

(cache,DAE.ATTR(ct,prl,vt,di,io,vis),tyChild,binding,cnstForRange,InstTypes.SPLICEDEXPDATA(texp,idTp),_,componentEnv,name) = lookupVar(cache, componentEnv, ids);

ltCref = elabComponentRecursive((texp));
_ = match ltCref
case (tCref::_) // with a spliced exp
equation
ty = if Types.isBoxedType(tyParent) and not Types.isUnknownType(tyParent)
then Types.boxIfUnboxedType(tyChild)
else tyChild "The internal types in a metarecord are lookup up in a clean environment, so we have to box them";
ty1 = checkSubscripts(tyParent, ss);
ty = sliceDimensionType(ty1,ty);
ty2_2 = Types.simplifyType(tyParent);
ss = addArrayDimensions(ty2_2,ss);
xCref = ComponentReference.makeCrefQual(id,ty2_2,ss,tCref);
eType = Types.simplifyType(ty);
splicedExp = Expression.makeCrefExp(xCref,eType);
oSplicedExp = SOME(splicedExp);
then ();
case ({}) // without spliced Expression
equation
oSplicedExp = NONE();
then ();
(attr,ty,binding,cnstForRange,componentEnv,name) := match tyParent
case DAE.T_METARECORD(fields=fields)
algorithm
{} := ss;
DAE.CREF_IDENT(ident=id2,subscriptLst={}) := ids;
DAE.TYPES_VAR(name,attr,ty,binding,cnstForRange) := listGet(fields,Types.findVarIndex(id2,fields)+1);
splicedExpData := InstTypes.SPLICEDEXPDATA(NONE(),ty);
then (attr,ty,binding,cnstForRange,componentEnv,name);
case DAE.T_METAUNIONTYPE(knownSingleton=true, paths={p})
algorithm
{} := ss;
DAE.CREF_IDENT(ident=id2,subscriptLst={}) := ids;
(cache, DAE.T_METARECORD(fields=fields), _) := lookupType(cache, componentEnv, p, NONE());
DAE.TYPES_VAR(name,attr,ty,binding,cnstForRange) := listGet(fields,Types.findVarIndex(id2,fields)+1);
splicedExpData := InstTypes.SPLICEDEXPDATA(NONE(),ty);
then (attr,ty,binding,cnstForRange,componentEnv,name);
case DAE.T_METAUNIONTYPE()
then fail();
else
algorithm
(cache,DAE.ATTR(ct,prl,vt,di,io,vis),tyChild,binding,cnstForRange,InstTypes.SPLICEDEXPDATA(texp,idTp),_,componentEnv,name) := lookupVar(cache, componentEnv, ids);

ltCref := elabComponentRecursive((texp));
oSplicedExp := match ltCref
case (tCref::_) // with a spliced exp
algorithm
ty1 := checkSubscripts(tyParent, ss);
ty := sliceDimensionType(ty1,tyChild);
ty2_2 := Types.simplifyType(tyParent);
ss := addArrayDimensions(ty2_2,ss);
xCref := ComponentReference.makeCrefQual(id,ty2_2,ss,tCref);
eType := Types.simplifyType(ty);
splicedExp := Expression.makeCrefExp(xCref,eType);
then SOME(splicedExp);
case ({}) // without spliced Expression
then NONE();
end match;
vt := SCode.variabilityOr(vt,vt2);
binding := lookupBinding(inComponentRef, tyParent, ty, parentBinding, binding);
splicedExpData := InstTypes.SPLICEDEXPDATA(oSplicedExp,idTp);
then
(DAE.ATTR(ct,prl,vt,di,io,vis),ty,binding,cnstForRange,componentEnv,name);
end match;
vt = SCode.variabilityOr(vt,vt2);
binding = lookupBinding(inComponentRef, tyParent, ty, parentBinding, binding);
then
(cache,DAE.ATTR(ct,prl,vt,di,io,vis),ty,binding,cnstForRange,InstTypes.SPLICEDEXPDATA(oSplicedExp,idTp),componentEnv,name);

// MetaModelica meta-records
case (cache,ht,(DAE.CREF_QUAL(ident = id,subscriptLst = {},componentRef = DAE.CREF_IDENT(ident=id2,subscriptLst={}))), _)
equation
true = Config.acceptMetaModelicaGrammar();
(DAE.TYPES_VAR(ty=DAE.T_METARECORD(fields=fields)),_,_,_,componentEnv) = lookupVar2(ht, id, inEnv);
DAE.TYPES_VAR(name,attr,ty,binding,cnstForRange) = listGet(fields,Types.findVarIndex(id2,fields)+1);
then
(cache,attr,ty,binding,cnstForRange,InstTypes.SPLICEDEXPDATA(NONE(),ty),componentEnv,name);
then (cache,attr,ty,binding,cnstForRange,splicedExpData,componentEnv,name);

end matchcontinue;
end match;
end lookupVarF;

protected function lookupBinding
Expand Down
15 changes: 11 additions & 4 deletions Compiler/FrontEnd/MetaUtil.mo
Expand Up @@ -269,24 +269,31 @@ public function fixUniontype
input SCode.ClassDef inClassDef;
output Option<DAE.Type> outType;
algorithm
outType := matchcontinue(inState, inClassDef)
outType := match (inState, inClassDef)
local
Boolean b;
Absyn.Path p;
list<Absyn.Path> paths;
list<String> names;
list<String> names, singletonFields;
DAE.TypeSource ts;

case (ClassInf.META_UNIONTYPE(), SCode.PARTS())
algorithm
p := Absyn.makeFullyQualified(inState.path);
names := SCode.elementNames(inClassDef.elementLst);
paths := list(Absyn.pathReplaceIdent(p, n) for n in names);
b := listLength(paths)==1;
if b then
singletonFields := SCode.componentNames(listGet(inClassDef.elementLst, 1));
else
singletonFields := {};
end if;
ts := Types.mkTypeSource(SOME(p));
then
SOME(DAE.T_METAUNIONTYPE(paths, listLength(paths) == 1, ts));
SOME(DAE.T_METAUNIONTYPE(paths,b,singletonFields,ts));

else NONE();
end matchcontinue;
end match;
end fixUniontype;

public function checkArrayType
Expand Down
11 changes: 7 additions & 4 deletions Compiler/FrontEnd/Types.mo
Expand Up @@ -5797,7 +5797,7 @@ algorithm
case (DAE.T_METARECORD(knownSingleton=false,utPath = path1), DAE.T_METARECORD(knownSingleton=false,utPath=path2))
equation
true = Absyn.pathEqual(path1,path2);
then DAE.T_METAUNIONTYPE({},false,{path1});
then DAE.T_METAUNIONTYPE({},false,{},{path1});

case (DAE.T_INTEGER(),DAE.T_REAL())
then DAE.T_REAL_DEFAULT;
Expand Down Expand Up @@ -7824,7 +7824,10 @@ algorithm
case (DAE.T_METALIST(t, _), ts) then DAE.T_METALIST(t, ts);
case (DAE.T_METATUPLE(tys, _), ts) then DAE.T_METATUPLE(tys, ts);
case (DAE.T_METAOPTION(t, _), ts) then DAE.T_METAOPTION(t, ts);
case (DAE.T_METAUNIONTYPE(ps, b, _), ts) then DAE.T_METAUNIONTYPE(ps, b, ts);
case (t as DAE.T_METAUNIONTYPE(), ts)
algorithm
t.source := ts;
then t;
case (DAE.T_METARECORD(p, i, v, b, _), ts) then DAE.T_METARECORD(p, i, v, b, ts);
case (DAE.T_METAARRAY(t, _), ts) then DAE.T_METAARRAY(t, ts);
case (DAE.T_METABOXED(t, _), ts) then DAE.T_METABOXED(t, ts);
Expand Down Expand Up @@ -8218,7 +8221,7 @@ algorithm
local
Boolean b;
Absyn.Path p;
case DAE.T_METARECORD(utPath=p,knownSingleton=b) then DAE.T_METAUNIONTYPE({},b,{p});
case DAE.T_METARECORD(utPath=p,knownSingleton=b) then DAE.T_METAUNIONTYPE({},b,if b then list(varName(v) for v in inTy.fields) else {},{p});
else inTy;
end match;
end getUniontypeIfMetarecord;
Expand All @@ -8237,7 +8240,7 @@ protected function getUniontypeIfMetarecordTraverse
output Integer odummy = dummy;
algorithm
oty := match ty
case DAE.T_METARECORD() then DAE.T_METAUNIONTYPE({},ty.knownSingleton,{ty.utPath});
case DAE.T_METARECORD() then DAE.T_METAUNIONTYPE({},ty.knownSingleton,if ty.knownSingleton then list(varName(v) for v in ty.fields) else {},{ty.utPath});
else ty;
end match;
end getUniontypeIfMetarecordTraverse;
Expand Down
19 changes: 18 additions & 1 deletion Compiler/Template/CodegenCFunctions.tpl
Expand Up @@ -2412,6 +2412,20 @@ template algStmtAssign(DAE.Statement stmt, Context context, Text &varDecls, Text
((modelica_metatype*)MMC_UNTAGPTR(<%tmp%>))[<%indexInRecord%>] = <%expPart%>;
<%varPart%> = <%tmp%>;
>>
case STMT_ASSIGN(exp1=CREF(componentRef=cr as CREF_QUAL(identType=T_METATYPE(ty=t1 as T_METAUNIONTYPE(__)), componentRef=cr2 as CREF_IDENT(__)),ty=t2)) then
let &preExp = buffer ""
let tmp = tempDecl("modelica_metatype",&varDecls)
let varPart = '_<%cr.ident%>' // So it only works in function context?
let expPart = daeExp(exp, context, &preExp, &varDecls, &auxFunction)
let indexInRecord = intAdd(1, position(cr2.ident, t1.singletonFields))
let len = intAdd(2, listLength(t1.singletonFields))
<<
<%preExp%>
<%tmp%> = MMC_TAGPTR(mmc_alloc_words(<%len%>));
memcpy(MMC_UNTAGPTR(<%tmp%>), MMC_UNTAGPTR(<%varPart%>), <%len%>*sizeof(modelica_metatype));
((modelica_metatype*)MMC_UNTAGPTR(<%tmp%>))[<%indexInRecord%>] = <%expPart%>;
<%varPart%> = <%tmp%>;
>>
case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_VAR(__)))
case STMT_ASSIGN(exp1=CREF(ty = T_FUNCTION_REFERENCE_FUNC(__))) then
let &preExp = buffer ""
Expand Down Expand Up @@ -4373,7 +4387,10 @@ template daeExpCrefRhs(Exp exp, Context context, Text &preExp,
case CREF(componentRef = cr, ty = T_FUNCTION_REFERENCE_VAR(__)) then
'((modelica_fnptr) _<%crefStr(cr)%>)'
case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METARECORD(__)), componentRef=cri as CREF_IDENT(__))) then
let offset = intAdd(findVarIndex(cri.ident,ty.fields),2)
let offset = intAdd(findVarIndex(cri.ident,ty.fields),2) // 0-based
'(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%cr.ident%>), <%offset%>)))'
case CREF(componentRef = cr as CREF_QUAL(subscriptLst={}, identType = T_METATYPE(ty=ty as T_METAUNIONTYPE(__)), componentRef=cri as CREF_IDENT(__))) then
let offset = intAdd(position(cri.ident,ty.singletonFields),1) // 1-based
'(MMC_FETCH(MMC_OFFSET(MMC_UNTAGPTR(_<%cr.ident%>), <%offset%>)))'
else
match context
Expand Down
1 change: 1 addition & 0 deletions Compiler/Template/SimCodeTV.mo
Expand Up @@ -1873,6 +1873,7 @@ package DAE
record T_METAUNIONTYPE "MetaModelica Uniontype, added by simbj"
list<Absyn.Path> paths;
Boolean knownSingleton "The runtime system (dynload), does not know if the value is a singleton. But optimizations are safe if this is true.";
list<String> singletonFields "The field names of the singleton";
TypeSource source;
end T_METAUNIONTYPE;

Expand Down

0 comments on commit 0693901

Please sign in to comment.