Skip to content

Commit

Permalink
Implemented initial support for size in nfinst.
Browse files Browse the repository at this point in the history
- Implemented instantiation and typing of size calls in nfinst.
  • Loading branch information
perost authored and OpenModelica-Hudson committed Aug 23, 2017
1 parent 1a120c8 commit c74f605
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 32 deletions.
4 changes: 2 additions & 2 deletions Compiler/NFFrontEnd/NFBuiltin.mo
Expand Up @@ -115,7 +115,7 @@ constant InstNode REAL_TYPE = InstNode.CLASS_NODE("Real",
constant InstNode INT_TYPE = InstNode.CLASS_NODE("Integer",
Elements.INTEGER,
Pointer.createImmutable(Class.PARTIAL_BUILTIN(Type.INTEGER(), NFClassTree.EMPTY, Modifier.NOMOD())),
Pointer.createImmutable(NFInstNode.CachedData.FUNCTION({NFBuiltinFuncs.INTEGER}, true)),
Pointer.createImmutable(NFInstNode.CachedData.FUNCTION({NFBuiltinFuncs.INTEGER}, true, false)),
InstNode.EMPTY_NODE(), InstNodeType.NORMAL_CLASS());

constant InstNode BOOLEAN_TYPE = InstNode.CLASS_NODE("Boolean",
Expand All @@ -130,7 +130,7 @@ constant InstNode STRING_TYPE = InstNode.CLASS_NODE("String",
Pointer.createImmutable(NFInstNode.CachedData.FUNCTION({
NFBuiltinFuncs.STRING_ENUM, NFBuiltinFuncs.STRING_INT,
NFBuiltinFuncs.STRING_BOOL, NFBuiltinFuncs.STRING_REAL,
NFBuiltinFuncs.STRING_REAL_FORMAT}, true)),
NFBuiltinFuncs.STRING_REAL_FORMAT}, true, false)),
InstNode.EMPTY_NODE(), InstNodeType.NORMAL_CLASS());

constant InstNode ENUM_TYPE = InstNode.CLASS_NODE("enumeration",
Expand Down
48 changes: 40 additions & 8 deletions Compiler/NFFrontEnd/NFCall.mo
Expand Up @@ -119,10 +119,16 @@ uniontype Call
ComponentRef fn_ref;
list<Expression> args;
list<NamedArg> named_args;
Boolean specialBuiltin;
algorithm
(fn_ref, fn_node) := Function.instFunc(functionName,scope,info);
(fn_ref, fn_node, specialBuiltin) := Function.instFunc(functionName,scope,info);
(args, named_args) := instArgs(functionArgs, scope, info);
callExp := Expression.CALL(UNTYPED_CALL(fn_ref, {}, args, named_args));

if specialBuiltin and Absyn.crefFirstIdent(functionName) == "size" then
callExp := makeSizeCall(args, named_args, info);
else
callExp := Expression.CALL(UNTYPED_CALL(fn_ref, {}, args, named_args));
end if;
end instantiate;

function instArgs
Expand Down Expand Up @@ -170,7 +176,7 @@ uniontype Call
Call call, argtycall;
InstNode fn_node;
list<Function> fnl;
Boolean fn_typed;
Boolean fn_typed, special;
Function fn;
list<Expression> args;
list<Type> arg_ty;
Expand All @@ -182,12 +188,12 @@ uniontype Call
case Expression.CALL(call = call as UNTYPED_CALL(ref = ComponentRef.CREF(node = fn_node)))
algorithm
// Fetch the cached function(s).
CachedData.FUNCTION(fnl, fn_typed) := InstNode.cachedData(fn_node);
CachedData.FUNCTION(fnl, fn_typed, special) := InstNode.cachedData(fn_node);

// Type the function(s) if not already done.
if not fn_typed then
fnl := list(Function.typeFunction(f) for f in fnl);
InstNode.setCachedData(CachedData.FUNCTION(fnl, true), fn_node);
InstNode.setCachedData(CachedData.FUNCTION(fnl, true, special), fn_node);
end if;

// Type the arguments.
Expand All @@ -197,8 +203,6 @@ uniontype Call

args := list(Util.tuple31(a) for a in tyArgs);

// This does segfault when list is empty
// variability := Types.constAnd(Util.tuple33(a) for a in tyArgs);
variability := DAE.C_CONST();
for a in tyArgs loop
variability := Types.constAnd(variability,Util.tuple33(a));
Expand Down Expand Up @@ -288,7 +292,7 @@ uniontype Call

(args, typematched, matchKind) := matchFunction(fn, call.arguments, call.named_args, info);

if(typematched) then
if typematched then
matchedFunctions := (fn,args,matchKind)::matchedFunctions;
matchingFuncs := fn::matchingFuncs;
end if;
Expand Down Expand Up @@ -471,6 +475,34 @@ uniontype Call
end match;
end typedFunction;

function makeSizeCall
input list<Expression> posArgs;
input list<NamedArg> namedArgs;
input SourceInfo info;
output Expression callExp;
protected
Integer argc = listLength(posArgs);
Expression arg1, arg2;
algorithm
if not listEmpty(namedArgs) then
for arg in namedArgs loop
Error.addSourceMessage(Error.NO_SUCH_PARAMETER,
{"size", Util.tuple21(arg)}, info);
end for;
fail();
end if;

callExp := match posArgs
case {arg1} then Expression.SIZE(arg1, NONE());
case {arg1, arg2} then Expression.SIZE(arg1, SOME(arg2));
else
algorithm
Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND,
{"size", "", ":\n size(array) => Integer[:]\n size(array, Integer) => Integer"}, info);
then
fail();
end match;
end makeSizeCall;
end Call;

annotation(__OpenModelica_Interface="frontend");
Expand Down
54 changes: 35 additions & 19 deletions Compiler/NFFrontEnd/NFFunction.mo
Expand Up @@ -149,7 +149,6 @@ constant FunctionMatchKind EXACT_MATCH = FunctionMatchKind.EXACT();
constant FunctionMatchKind CAST_MATCH = FunctionMatchKind.CAST();
constant FunctionMatchKind NO_MATCH = FunctionMatchKind.NOT_COMPATIBLE();


uniontype Function

record FUNCTION
Expand All @@ -176,16 +175,10 @@ uniontype Function
Pointer<Boolean> collected;
algorithm
(inputs, outputs, locals) := collectParams(node);
// Slots should be created after typing
// slots := makeSlots(inputs);
attr := makeAttributes(node, inputs, outputs);
collected := Pointer.create(false);
fn := FUNCTION(path, node, inputs, outputs, locals, {}, Type.UNKNOWN(), attr, collected);

// Make sure builtin functions aren't added to the function tree.
if isBuiltin(fn) then
collect(fn);
end if;
collected := Pointer.create(isBuiltinAttr(attr));
fn := FUNCTION(path, node, inputs, outputs, locals, {}, Type.UNKNOWN(), attr, collected);
end new;

protected
Expand Down Expand Up @@ -226,6 +219,7 @@ uniontype Function
input SourceInfo info;
output ComponentRef fn_ref;
output InstNode fn_node;
output Boolean specialBuiltin;
protected
CachedData cache;
Absyn.Path fn_path;
Expand All @@ -235,8 +229,8 @@ uniontype Function
cache := InstNode.cachedData(fn_node);

// Check if a cached instantiation of this function already exists.
fn_node := match cache
case CachedData.FUNCTION() then fn_node;
(fn_node, specialBuiltin) := match cache
case CachedData.FUNCTION() then (fn_node, cache.specialBuiltin);
else instFunc2(fn_path,fn_node, info);
end match;
end instFunc;
Expand All @@ -246,9 +240,9 @@ uniontype Function
input Absyn.Path fnPath;
input output InstNode fnNode;
input SourceInfo info;
output Boolean specialBuiltin;
algorithm

fnNode := match InstNode.definition(fnNode)
(fnNode, specialBuiltin) := match InstNode.definition(fnNode)
local
SCode.ClassDef cdef;
Function fn;
Expand All @@ -261,19 +255,22 @@ uniontype Function
cr := Absyn.pathToCref(p);
(_,sub_fnNode) := instFunc(cr,fnNode /*This should be the scope right?*/,info);
for f in getCachedFuncs(sub_fnNode) loop
fnNode := InstNode.cacheAddFunc(f, fnNode);
fnNode := InstNode.cacheAddFunc(f, false, fnNode);
end for;
end for;
then fnNode;
then
(fnNode, false);

case SCode.CLASS()
algorithm
fnNode := InstNode.setNodeType(NFInstNode.InstNodeType.ROOT_CLASS(), fnNode);
fnNode := Inst.instantiate(fnNode);
Inst.instExpressions(fnNode);
fn := Function.new(fnPath, fnNode);
fnNode := InstNode.cacheAddFunc(fn, fnNode);
then fnNode;
specialBuiltin := isSpecialBuiltin(fn);
fnNode := InstNode.cacheAddFunc(fn, specialBuiltin, fnNode);
then
(fnNode, specialBuiltin);

end match;
end instFunc2;
Expand Down Expand Up @@ -661,13 +658,32 @@ uniontype Function

function isBuiltin
input Function fn;
output Boolean isBuiltin = isBuiltinAttr(fn.attributes);
end isBuiltin;

function isBuiltinAttr
input DAE.FunctionAttributes attrs;
output Boolean isBuiltin;
algorithm
isBuiltin := match fn.attributes.isBuiltin
isBuiltin := match attrs.isBuiltin
case DAE.FunctionBuiltin.FUNCTION_NOT_BUILTIN() then false;
else true;
end match;
end isBuiltin;
end isBuiltinAttr;

function isSpecialBuiltin
input Function fn;
output Boolean special;
algorithm
if not isBuiltin(fn) then
special := false;
else
special := match fn.path
case Absyn.IDENT(name = "size") then true;
else false;
end match;
end if;
end isSpecialBuiltin;

function isImpure
input Function fn;
Expand Down
10 changes: 7 additions & 3 deletions Compiler/NFFrontEnd/NFInstNode.mo
Expand Up @@ -76,6 +76,7 @@ uniontype CachedData
record FUNCTION
list<Function> funcs;
Boolean typed;
Boolean specialBuiltin;
end FUNCTION;

function empty
Expand All @@ -84,12 +85,14 @@ uniontype CachedData

function addFunc
input Function fn;
input Boolean specialBuiltin;
input output CachedData cache;
algorithm
cache := match cache
case NO_CACHE() then FUNCTION({fn}, false);
case NO_CACHE() then FUNCTION({fn}, false, specialBuiltin);
// Append to end so the error messages are ordered properly.
case FUNCTION() then FUNCTION(listAppend(cache.funcs,{fn}), false);
case FUNCTION() then FUNCTION(listAppend(cache.funcs,{fn}), false,
cache.specialBuiltin or specialBuiltin);
else
algorithm
assert(false, getInstanceName() + ": Invalid cache for function");
Expand Down Expand Up @@ -685,12 +688,13 @@ uniontype InstNode

function cacheAddFunc
input Function fn;
input Boolean specialBuiltin;
input output InstNode node;
algorithm
() := match node
case CLASS_NODE()
algorithm
Pointer.update(node.cached, CachedData.addFunc(fn, Pointer.access(node.cached)));
Pointer.update(node.cached, CachedData.addFunc(fn, specialBuiltin, Pointer.access(node.cached)));
then
();

Expand Down
49 changes: 49 additions & 0 deletions Compiler/NFFrontEnd/NFTyping.mo
Expand Up @@ -479,6 +479,7 @@ algorithm
case Expression.TYPENAME() then (exp, exp.ty, Const.C_CONST());
case Expression.ARRAY() then typeArray(exp.elements, info);
case Expression.RANGE() then typeRange(exp, info);
case Expression.SIZE() then typeSize(exp, info);

case Expression.END() then (exp, Type.INTEGER(), Const.C_CONST());

Expand Down Expand Up @@ -714,6 +715,54 @@ algorithm
fail();
end printRangeTypeError;

function typeSize
input output Expression sizeExp;
input SourceInfo info;
output Type sizeType;
output DAE.Const variability;
protected
Option<Expression> oindex;
Expression exp, index;
Type exp_ty, index_ty;
TypeCheck.MatchKind ty_match;
algorithm
Expression.SIZE(exp = exp, dimIndex = oindex) := sizeExp;

(exp, exp_ty, _) := typeExp(exp, info);

// The first argument must be an array of any type.
if not Type.isArray(exp_ty) then
Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {"size"}, info);
fail();
end if;

if isSome(oindex) then
SOME(index) := oindex;
(index, index_ty, variability) := typeExp(index, info);

// The second argument must be an Integer.
(index, _, ty_match) :=
TypeCheck.matchTypes(index_ty, Type.INTEGER(), index);

if TypeCheck.isIncompatibleMatch(ty_match) then
Error.addSourceMessage(Error.ARG_TYPE_MISMATCH,
{"2", "size ", "dim", Expression.toString(index), Type.toString(index_ty), "Integer"}, info);
fail();
end if;

oindex := SOME(index);
sizeType := Type.INTEGER();
else
// TODO: Fill in correct dimension size here.
sizeType := Type.ARRAY(Type.INTEGER(), {Dimension.INTEGER(1)});
// The number of dimensions is always known, but the dimension sizes
// themselves might not be known here.
variability := DAE.C_VAR();
end if;

sizeExp := Expression.SIZE(exp, oindex);
end typeSize;

function typeSections
input InstNode classNode;
protected
Expand Down

0 comments on commit c74f605

Please sign in to comment.