@@ -43,11 +43,13 @@ import Binding = NFBinding;
4343import NFComponent.Component ;
4444import NFInstNode.CachedData ;
4545import ComponentRef = NFComponentRef ;
46+ import Dimension = NFDimension ;
4647import NFFunction.Function ;
4748import Inst = NFInst ;
4849import NFInstNode.InstNodeType ;
4950import Lookup = NFLookup ;
5051import Typing = NFTyping ;
52+ import TypeCheck = NFTypeCheck ;
5153import ExpOrigin = NFTyping . ExpOrigin ;
5254import Types ;
5355import List ;
@@ -315,6 +317,12 @@ uniontype Call
315317 (call, ty, variability) := match callExp
316318 case Expression . CALL (UNTYPED_CALL (ref= ComponentRef . CREF (node= InstNode . CLASS_NODE (name= "pre" ))))
317319 then typePreCall(callExp. call, info);
320+ case Expression . CALL (UNTYPED_CALL (ref= ComponentRef . CREF (node= InstNode . CLASS_NODE (name= "min" ))))
321+ then typeMinMaxCall(callExp. call, info, "min" );
322+ case Expression . CALL (UNTYPED_CALL (ref= ComponentRef . CREF (node= InstNode . CLASS_NODE (name= "max" ))))
323+ then typeMinMaxCall(callExp. call, info, "max" );
324+ case Expression . CALL (UNTYPED_CALL (ref= ComponentRef . CREF (node= InstNode . CLASS_NODE (name= "smooth" ))))
325+ then typeSmoothCall(callExp. call, info);
318326 case Expression . CALL (UNTYPED_CALL ()) then typeNormalCall(callExp. call, info);
319327 case Expression . CALL (UNTYPED_MAP_CALL ()) then typeMapIteratorCall(callExp. call, info);
320328 end match;
@@ -516,6 +524,170 @@ uniontype Call
516524 end match;
517525 end typePreCall;
518526
527+ function typeMinMaxCall
528+ input output Call call;
529+ input SourceInfo info;
530+ input String name;
531+ output Type ty;
532+ output Variability variability;
533+ protected
534+ Call argtycall;
535+ InstNode fn_node;
536+ list< Function > fnl;
537+ Boolean fn_typed, special;
538+ Function fn;
539+ Expression e, e1, e2;
540+ Type ty1, ty2;
541+ list< Expression > es;
542+ list< Type > arg_ty;
543+ list< Variability > arg_var;
544+ CallAttributes ca;
545+ list< TypedArg > tyArgs;
546+ list< TypedNamedArg > nargs;
547+ Integer nArgs;
548+ Variability variability1, variability2;
549+ TypeCheck . MatchKind ty_match;
550+ algorithm
551+ (call , ty, variability) := match call
552+ case UNTYPED_CALL (ref = ComponentRef . CREF (node = fn_node))
553+ algorithm
554+ // Fetch the cached function(s).
555+ CachedData . FUNCTION ({fn}, fn_typed, special) := InstNode . getFuncCache(fn_node);
556+
557+ // Type the function(s) if not already done.
558+ if not fn_typed then
559+ fn := Function . typeFunction(fn);
560+ InstNode . setFuncCache(fn_node, CachedData . FUNCTION ({fn}, true , special));
561+ end if ;
562+
563+ // Type the arguments.
564+ ARG_TYPED_CALL (arguments= tyArgs, named_args= nargs) := typeArgs(call,info);
565+ nArgs := listLength(tyArgs);
566+ if not listEmpty(nargs) or not (nArgs == 1 or nArgs == 2 ) then
567+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , name + "(<T>) => <T>, " + name + "(<T>,<T>) => <T>" }, info);
568+ end if ;
569+
570+ if nArgs == 1 then
571+ {(e,ty,variability)} := tyArgs;
572+ es := {e};
573+ else
574+ {(e1,ty1,variability1),(e2,ty2,variability2)} := tyArgs;
575+ es := {e1,e2};
576+ variability := Prefixes . variabilityMax(variability1, variability2);
577+ (e1,e2,ty,ty_match) := TypeCheck . matchExpressions(e1,ty1,e2,ty2);
578+ if not TypeCheck . isCompatibleMatch(ty_match) then
579+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , "Incompatible types" }, info);
580+ end if ;
581+ end if ;
582+
583+ // TODO: Check that '<' or '>' operator is defined for the expression...
584+
585+ ca := CallAttributes . CALL_ATTR (
586+ ty,
587+ Type . isTuple(ty),
588+ Function . isBuiltin(fn),
589+ Function . isImpure(fn),
590+ Function . isFunctionPointer(fn),
591+ Function . inlineBuiltin(fn),
592+ DAE . NO_TAIL ());
593+
594+ then
595+ (TYPED_CALL (fn, es, ca), ty, variability);
596+
597+ else
598+ algorithm
599+ assert (false , getInstanceName() + " got invalid function call expression" );
600+ then
601+ fail();
602+ end match;
603+ end typeMinMaxCall;
604+
605+ function typeSmoothCall
606+ input output Call call;
607+ input SourceInfo info;
608+ output Type ty;
609+ output Variability variability;
610+ protected
611+ Call argtycall;
612+ InstNode fn_node;
613+ list< Function > fnl;
614+ Boolean fn_typed, special;
615+ Function fn;
616+ Expression e, e1, e2;
617+ Type ty1, ty2;
618+ list< Type > arg_ty;
619+ list< Variability > arg_var;
620+ CallAttributes ca;
621+ list< TypedArg > tyArgs;
622+ list< TypedNamedArg > nargs;
623+ Integer nArgs;
624+ Variability variability1, variability2;
625+ TypeCheck . MatchKind ty_match;
626+ algorithm
627+ (call , ty, variability) := match call
628+ case UNTYPED_CALL (ref = ComponentRef . CREF (node = fn_node))
629+ algorithm
630+ // Fetch the cached function(s).
631+ CachedData . FUNCTION ({fn}, fn_typed, special) := InstNode . getFuncCache(fn_node);
632+
633+ // Type the function(s) if not already done.
634+ if not fn_typed then
635+ fn := Function . typeFunction(fn);
636+ InstNode . setFuncCache(fn_node, CachedData . FUNCTION ({fn}, true , special));
637+ end if ;
638+
639+ // Type the arguments.
640+ ARG_TYPED_CALL (arguments= tyArgs, named_args= nargs) := typeArgs(call,info);
641+ nArgs := listLength(tyArgs);
642+ if not listEmpty(nargs) or nArgs <> 2 then
643+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , "smooth(i, <T>) => <T>" }, info);
644+ end if ;
645+
646+ {(e1,ty1,variability1),(e2,ty2,variability2)} := tyArgs;
647+
648+ if variability1 > Variability . PARAMETER then
649+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , "First argument of smooth must be a parameter or constant expression" }, info);
650+ end if ;
651+
652+ (e1, ty1, ty_match) := TypeCheck . matchTypes(ty1, Type . INTEGER (), e1);
653+
654+ if not TypeCheck . isCompatibleMatch(ty_match) then
655+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , "First argument of smooth must be an Integer expression" }, info);
656+ end if ;
657+
658+ variability := Prefixes . variabilityMax(variability1, variability2);
659+
660+ (e2, ty2, ty_match) := TypeCheck . matchTypes(ty2, Type . REAL (), e2);
661+ if not TypeCheck . isCompatibleMatch(ty_match) then
662+ (e2, ty2, ty_match) := TypeCheck . matchTypes(ty2, Type . ARRAY (Type . REAL (),{Dimension . UNKNOWN ()}), e2);
663+ end if ;
664+ // TODO: Allow ty2 is record with only allowed types...
665+ // TODO: Allow ty2 is multi-dim array
666+
667+ if not TypeCheck . isCompatibleMatch(ty_match) then
668+ Error . addSourceMessage(Error . NO_MATCHING_FUNCTION_FOUND , {toString(call), "<REMOVE ME>" , "Second argument of smooth must be a Real scalar or record with only Real components, or array expression of these (TODO: Not fully checked)" }, info);
669+ end if ;
670+
671+ ca := CallAttributes . CALL_ATTR (
672+ ty2,
673+ Type . isTuple(ty2),
674+ Function . isBuiltin(fn),
675+ Function . isImpure(fn),
676+ Function . isFunctionPointer(fn),
677+ Function . inlineBuiltin(fn),
678+ DAE . NO_TAIL ());
679+
680+ then
681+ (TYPED_CALL (fn, {e1,e2}, ca), ty2, variability);
682+
683+ else
684+ algorithm
685+ assert (false , getInstanceName() + " got invalid function call expression" );
686+ then
687+ fail();
688+ end match;
689+ end typeSmoothCall;
690+
519691 function typeArgs
520692 input output Call call;
521693 input SourceInfo info;
0 commit comments