object IApply.Apply(object[] args) { // Entrypoint when called via funcall or apply or map etc. if (Kind == LambdaKind.Macro) { var form = (Cons)args[0]; var env = args[1]; return(ApplyLambdaBind(null, Runtime.AsArray(Runtime.Cdr(form)), false, env, form)); // throw new LispException("Invalid macro call."); } else if (Definition.Signature.ArgModifier == Symbols.RawParams) { return(ApplyLambdaBind(null, args, true, null, null)); } else { return(ApplyLambdaBind(null, args, false, null, null)); } }
public Exception FillDataFrame(LambdaSignature signature, object[] input, object[] output, int offsetOutput, object env, Cons wholeMacroForm) { var offset = 0; var firstKey = -1; var usedKeys = 0; var haveAll = false; var firstArg = 0; if (signature.Kind != LambdaKind.Macro && signature.RequiredArgsCount > 0) { // This does not work for nested parameters. var n = signature.RequiredArgsCount; if (input.Length < n) { throw new LispException("Missing required parameters"); } Array.Copy(input, 0, output, offsetOutput, n); offsetOutput += n; firstArg = n; offset = n; } for (var iArg = firstArg; !haveAll && iArg < signature.Parameters.Count; ++iArg) { var mod = (iArg < signature.RequiredArgsCount) ? null : signature.ArgModifier; var arg = signature.Parameters[iArg]; object val; if (mod == Symbols.Params) { var buf = new object[input.Length - offset]; Array.Copy(input, offset, buf, 0, buf.Length); val = buf; haveAll = true; } else if (mod == Symbols.Vector) { var v = new Vector(input.Length - offset); for (var i = offset; i < input.Length; ++i) { v.Add(input[i]); } val = v; haveAll = true; } else if (mod == Symbols.Rest || mod == Symbols.Body) { Cons list = null; for (var i = input.Length - 1; i >= offset; --i) { list = new Cons(input[i], list); } val = list; haveAll = true; } else if (mod == Symbols.Key) { if (firstKey == -1) { firstKey = offset; for (var i = firstKey; i < input.Length; i += 2) { if (!Runtime.Keywordp(input[i]) || i + 1 == input.Length) { throw new LispException("Invalid keyword/value list"); } } } val = Runtime.MissingValue; for (var i = firstKey; i + 1 < input.Length; i += 2) { if (arg.Sym.Name == ((Symbol)input[i]).Name) { val = input[i + 1]; ++usedKeys; break; } } } else if (offset < input.Length) { val = input[offset]; ++offset; } else if (mod == Symbols.Optional) { val = Runtime.MissingValue; } else { throw new LispException("Missing required argument: {0}", arg.Sym); } if (val == Runtime.MissingValue) { if (arg.InitFormProc != null) { val = arg.InitFormProc(); } else { val = null; } } if (arg.NestedParameters != null) { // required macro parameter var nestedInput = Runtime.AsArray((IEnumerable)val); FillDataFrame(arg.NestedParameters, nestedInput, output, offsetOutput, env, null); offsetOutput += arg.NestedParameters.Names.Count; } else { output[offsetOutput++] = val; } } if (signature.WholeArg != null) { Cons list = wholeMacroForm; if (list == null) { for (var i = input.Length - 1; i >= 0; --i) { list = new Cons(input[i], list); } } int j = output.Length - 1 - ((signature.EnvArg != null) ? 1 : 0); output[j] = list; haveAll = true; } if (signature.EnvArg != null) { int j = output.Length - 1; output[j] = env; } if (offset < input.Length && !haveAll && firstKey == -1) { throw new LispException("Too many parameters supplied"); } return(null); }