protected PortableLambdaType(string name, LambdaKind lambdaKind, CodeType[] parameters) : base(name) { LambdaKind = lambdaKind; ParameterTypesKnown = true; Parameters = parameters; AddInvokeFunction(); }
public PortableLambdaType(LambdaKind lambdaType, CodeType[] parameters, bool returnsValue, CodeType returnType, bool parameterTypesKnown) : base("lambda") { LambdaKind = lambdaType; Parameters = parameters; ReturnsValue = returnsValue; ReturnType = returnType; ParameterTypesKnown = parameterTypesKnown; AddInvokeFunction(); }
} // Are parameter types known? public PortableLambdaTypeBuilder(LambdaKind kind, CodeType[] parameters, CodeType returnType) { Name = "lambda"; LambdaKind = kind; Parameters = parameters; ReturnType = returnType; ReturnsValue = returnType != null; ParameterTypesKnown = true; }
public PortableLambdaTypeBuilder( LambdaKind kind, string name = "lambda", CodeType[] parameters = null, CodeType returnType = null, bool returnsValue = false, bool parameterTypesKnown = false) { Name = name; LambdaKind = kind; Parameters = parameters ?? new CodeType[0]; ReturnType = returnType; ReturnsValue = returnsValue; ParameterTypesKnown = parameterTypesKnown; }
public PortableLambdaType(LambdaKind lambdaType) : this(lambdaType, new CodeType[0], false, null, false) { }
protected BaseLambda(string name, LambdaKind lambdaKind, CodeType[] argumentTypes) : base(name, lambdaKind, argumentTypes) { CanBeDeleted = false; CanBeExtended = false; Kind = "constant"; }
public LambdaSignature(LambdaKind kind) { Kind = kind; }
public static Expression CompileLambdaDef(Symbol name, Cons forms, AnalysisScope scope, LambdaKind kind, out string doc) { CheckMinLength(forms, 0); if (Length(forms) == 1) { PrintWarning("Function body contains no forms."); } var args = (Cons)First(forms); var body = Cdr(forms); var funscope = new AnalysisScope(scope, name == null ? null : name.Name); funscope.IsLambda = true; var template = new LambdaDefinition(); template.Name = name; template.Signature = CompileFormalArgs(args, scope, kind); if (kind == LambdaKind.Method) { var container = name.Value as MultiMethod; if (container != null) { var m = template.Signature; var g = container.Signature; var m1 = m.RequiredArgsCount; var m2 = m.Parameters.Count; var m3 = m.ArgModifier; var g1 = g.RequiredArgsCount; var g2 = g.Parameters.Count; var g3 = g.ArgModifier; if (m1 != g1) { throw new LispException("Method does not match multi-method: number of required arguments"); } if (m3 != g3) { throw new LispException("Method does not match multi-method: different argument modifiers"); } if (g3 != Symbols.Key && m2 != g2) { throw new LispException("Method does not match multi-method: number of arguments"); } if (g3 == Symbols.Key) { // Replace keyword parameters with the full list from the generic definition, but keep the defaults var usedKeys = template.Signature.Parameters.GetRange(m1, m2 - m1); var replacementKeys = container.Signature.Parameters.GetRange(g1, g2 - g1); template.Signature.Parameters.RemoveRange(m1, m2 - m1); template.Signature.Names.RemoveRange(m1, m2 - m1); foreach (var par in replacementKeys) { var oldpar = usedKeys.FirstOrDefault(x => x.Sym == par.Sym); if (oldpar != null) { var newpar = new ParameterDef(par.Sym, initForm: oldpar.InitForm); template.Signature.Parameters.Add(newpar); template.Signature.Names.Add(par.Sym); } else { // Insert place holder var newpar = new ParameterDef(par.Sym, hidden: true); template.Signature.Parameters.Add(newpar); template.Signature.Names.Add(newpar.Sym); } } } } } if (name != null) { template.Syntax = MakeListStar(template.Name, args); } template.Source = MakeListStar(Symbols.Lambda, args, body); doc = ""; if (body != null) { if (body.Car is string) { doc = (string)body.Car; if (body.Cdr != null) { body = body.Cdr; } } } var lambdaListNative = funscope.DefineNativeLocal(Symbols.LambdaList, ScopeFlags.All); var selfNative = funscope.DefineNativeLocal(Symbols.Self, ScopeFlags.All); var argsNative = funscope.DefineNativeLocal(Symbols.Args, ScopeFlags.All); Expression code; var rawparams = template.Signature.ArgModifier == Symbols.RawParams; var names = GetLambdaArgumentNames(template.Signature); var temp = GenTemp(); var body4 = FormatCode(LambdaTemplate, Symbols.Args, temp, GetDeclarations(rawparams, names, temp), body); code = Compile(body4, funscope); template.Proc = CompileToFunction3(code, lambdaListNative, selfNative, argsNative); return CallRuntime(MakeLambdaClosureMethod, Expression.Constant(template, typeof(LambdaDefinition))); }
public static LambdaSignature CompileFormalArgs(Cons args, AnalysisScope scope, LambdaKind kind) { var signature = new LambdaSignature(kind); signature.ArgModifier = null; bool wantWholeArgName = false; bool wantEnvArgName = false; foreach (object item in ToIter(args)) { if (wantWholeArgName) { signature.WholeArg = (Symbol)item; wantWholeArgName = false; } else if (wantEnvArgName) { signature.EnvArg = (Symbol)item; wantEnvArgName = false; } else if (item is Symbol) { var sym = (Symbol)item; if (sym == Symbols.Whole) { if (kind != LambdaKind.Macro) { throw new LispException("&whole parameter can only be used for a macro"); } wantWholeArgName = true; } else if (sym == Symbols.Environment) { if (kind != LambdaKind.Macro) { throw new LispException("&environment parameter can only be used for a macro"); } wantEnvArgName = true; } else if (sym == Symbols.Optional || sym == Symbols.Key || sym == Symbols.Rest || sym == Symbols.Body || sym == Symbols.Params || sym == Symbols.Vector || sym == Symbols.RawParams) { if (signature.ArgModifier != null) { throw new LispException("Only one modifier can be used: &key, &optional, &rest, &body, &vector, ¶ms or &rawparams"); } signature.ArgModifier = sym; signature.RequiredArgsCount = signature.Parameters.Count; continue; } else { var arg = new ParameterDef(sym); signature.Parameters.Add(arg); signature.Names.Add(sym); } } else if (item is Cons) { var list = (Cons)item; if (signature.ArgModifier == Symbols.Key || signature.ArgModifier == Symbols.Optional) { var sym = (Symbol)First(list); var initForm = Second(list); if (initForm == null) { signature.Parameters.Add(new ParameterDef(sym)); signature.Names.Add(sym); } else { var initForm2 = Compile(initForm, scope); signature.Parameters.Add(new ParameterDef(sym, initForm: initForm2)); signature.Names.Add(sym); } } else if (signature.ArgModifier == null && kind == LambdaKind.Macro) { var nestedArgs = CompileFormalArgs(list, scope, kind); var arg = new ParameterDef(null, nestedParameters: nestedArgs); signature.Parameters.Add(arg); signature.Names.AddRange(nestedArgs.Names); } else if (signature.ArgModifier == null && kind == LambdaKind.Method) { var sym = (Symbol)First(list); var type = Second(list); if (type == null) { var arg = new ParameterDef(sym); signature.Parameters.Add(arg); signature.Names.Add(sym); } else if (type is Cons && First(type) == FindSymbol("lisp:eql")) { // Compile time constants! var expr = Eval(Second(type)); var arg = new ParameterDef(sym, specializer: new EqlSpecializer(expr)); signature.Parameters.Add(arg); signature.Names.Add(sym); } else { if (!Symbolp(type) || Keywordp(type)) { throw new LispException("Invalid type specifier: {0}", type); } var realType = GetType((Symbol)type); var arg = new ParameterDef(sym, specializer: realType); signature.Parameters.Add(arg); signature.Names.Add(sym); } } else { throw new LispException("Invalid CONS in lambda parameter list"); } } } if (signature.ArgModifier == null) { signature.RequiredArgsCount = signature.Parameters.Count; } //if (kind == LambdaKind.Function) { var sym = signature.ArgModifier; if (sym == Symbols.RawParams) { if (signature.Parameters.Count != 1) { throw new LispException("&rawparams: parameter count must be one."); } } else if (sym == Symbols.Rest || sym == Symbols.Body || sym == Symbols.Params || sym == Symbols.Vector) { if (signature.RequiredArgsCount + 1 != signature.Parameters.Count) { throw new LispException("Invalid placement of &rest or similar modifier."); } } } return signature; }