예제 #1
0
        // Create for user defined
        public static CallInfo Create(string name, DataType rettype, DataColumn[] argcols, int accums = 0, CallInfo overload = null)
        {
            var ci = new CallInfo {
                Name       = name,
                ReturnType = rettype,
                Arguments  = argcols,
                AccumCount = accums,
                OverLoad   = overload,
            };

            return(ci);
        }
예제 #2
0
        ///============================================================================================
        /// Type checking
        ///

        // check symbol with a method and arguments, return return type and callinfo
        // raises error if type error detected
        // no of args: symbol table sets a limit because some builtins have extra trailing args
        public void CheckTypeError(Symbol symbol, out DataType datatype, out CallInfo callinfo, params DataType[] datatypes)
        {
            Logger.Assert(symbol.CallInfo != null, "no callinfo");
            // use symbol type as result type unless (a) not IsParameter or (b) Has Overloads
            datatype = symbol.DataType;
            callinfo = symbol.CallInfo;
            var nargs = symbol.NumArgs; // max no to check

            if (datatypes.Length > nargs)
            {
                Parser.ParseError("'{0}' expected {1} arguments, found {2}", symbol.Name, nargs, datatypes.Length);
            }
            if (symbol.IsCompareOp && !datatypes[0].Equals(datatypes[1]))
            {
                Parser.ParseError("'{0}' arguments type mismatch: {1} and {2}", symbol.Name, datatypes[0], datatypes[1]);
            }

            // Must search for correct callinfo in order to make call
            // If more than one (HasOverloads), then use return type as datatype
            // Careful: may be argless
            var match = false;

            for (var cinf = symbol.CallInfo; cinf != null && !match; cinf = cinf.OverLoad)
            {
                var nargsi = Math.Min(symbol.NumArgs, cinf.NumArgs); // max no to check
                if (datatypes.Length == nargsi &&
                    Enumerable.Range(0, nargsi).All(x => TypeMatch(cinf.Arguments[x].DataType, datatypes[x])))
                {
                    if (match)
                    {
                        Parser.ParseError("'{0}' ambiguous type match", symbol.Name);
                    }
                    match    = true;
                    callinfo = cinf;
                }
            }
            if (!match)
            {
                Parser.ParseError("no definition matches call to '{0}'", symbol.Name);
            }
            // special functions to handle these two cases
            if (symbol.IsDyadic)
            {
                CheckDyadicType(symbol, datatypes[0], datatypes[1], ref datatype);
            }
            else if (datatype == DataTypes.Table || datatype == DataTypes.Infer || datatype == DataTypes.Ordered)
            {
                CheckInferType(symbol, datatypes, ref datatype);
            }
            // for overloads and deffunc assume the callinfo is correct
            // note: sym for seq() has the heading info (callinfo less specific)
            else if (symbol.HasOverloads || symbol.IsDefFunc)
            {
                datatype = callinfo.ReturnType;
            }

            if (!datatype.IsPassable)
            {
                Parser.ParseError($"{symbol.Name}: cannot infer return type");
            }
        }