// 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); }
///============================================================================================ /// 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"); } }