// create a function value // BUG: a persistent function must not reference a non-persistent global public AstValue Funval(AstType rettype, IList <AstField> arguments, AstBodyStatement body) { var code = Code(body.Statement as AstValue, Headingof(arguments), "λ", false, body.AccumCount, body.HasWin); return(new AstFunval { Value = code, DataType = DataTypeCode.Get(code.DataType, code.Lookup) }); }
// finalise function definition, from basic definition previously created // set or check return type // null body just defines type // Note: null arguments means argless (lazy) rather than deffun // BUG: a persistent function must not reference a non-persistent global public AstStatement Deffun(string ident, AstType rettype, IList <AstField> arguments, AstBodyStatement body) { var op = FindDefFunc(ident); var callinfo = op.CallInfo; if (callinfo.ReturnType == DataTypes.Unknown) { callinfo.ReturnType = body.DataType; } else if (callinfo.ReturnType != body.DataType) { Parser.ParseError($"{ident} return type mismatch"); } if (op.DataType == DataTypes.Unknown) { if (arguments == null) { op.DataType = callinfo.ReturnType; } } else if (op.DataType != callinfo.ReturnType) { Parser.ParseError("body does not match declared type"); } // assume top overload is the one being defined //op.callinfo.ReturnType = op.DataType; callinfo.AccumCount = body.AccumCount; callinfo.HasWin = body.HasWin; // symbol is foldable if all overloads are foldable // FIX: put this test where it's used var foldable = (callinfo.NumArgs == 2 && arguments[0].DataType == callinfo.ReturnType && arguments[1].DataType == callinfo.ReturnType) && (callinfo.OverLoad == null || op.IsFoldable); if (foldable && !op.IsFoldable) { op.Foldable = FoldableFlags.ANY; } Symbols.AddCatalog(op); // assemble node var code = Code(body.Statement as AstValue, Headingof(arguments), callinfo.Name, true, body.AccumCount, body.HasWin); return(GenFunCall(FindFunc(SymNames.Defer), Args(code))); }