Example #1
0
 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));
     }
 }
Example #2
0
        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);
        }