Esempio n. 1
0
        public static MultiMethod DefineMultiMethod(Symbol sym, LambdaSignature signature, string doc)
        {
            var func = new MultiMethod(signature);

            sym.FunctionValue = func;
            sym.Documentation = doc;
            return(func);
        }
Esempio n. 2
0
        public ParameterDef(Symbol sym, object specializer   = null,
                            Expression initForm              = null,
                            Func <object> initFormProc       = null,
                            LambdaSignature nestedParameters = null,
                            bool hidden = false)
        {
            Sym              = sym;
            Specializer      = specializer;
            NestedParameters = nestedParameters;
            InitForm         = initForm;
            InitFormProc     = initFormProc;
            Hidden           = hidden;

            if (InitForm != null && InitFormProc == null)
            {
                InitFormProc = Runtime.CompileToFunction(initForm);
            }
        }
Esempio n. 3
0
        public static Expression FillDataFrame(LambdaSignature signature, DynamicMetaObject[] input, ref BindingRestrictions restrictions)
        {
            var elementType = typeof(object);
            var offset      = 0;
            var output      = new List <Expression>();

            if (signature.ArgModifier == Symbols.RawParams)
            {
                var tail = new List <Expression>();
                for (var i = offset; i < input.Length; ++i)
                {
                    tail.Add(Expression.Convert(input[i].Expression, elementType));
                }
                var tailExpr = Expression.NewArrayInit(elementType, tail);
                return(tailExpr);
            }

            for (offset = 0; offset < signature.RequiredArgsCount; ++offset)
            {
                if (offset >= input.Length)
                {
                    throw new LispException("Missing required parameters");
                }
                output.Add(Expression.Convert(input[offset].Expression, elementType));
            }

            if (offset != signature.Parameters.Count)
            {
                var mod = signature.ArgModifier;

                if (mod == Symbols.Rest || mod == Symbols.Body || mod == Symbols.Params || mod == Symbols.Vector)
                {
                    var tail = new List <Expression>();
                    for (var i = offset; i < input.Length; ++i)
                    {
                        tail.Add(Expression.Convert(input[i].Expression, elementType));
                    }
                    var tailExpr = Expression.NewArrayInit(elementType, tail);
                    if (mod == Symbols.Rest || mod == Symbols.Body)
                    {
                        var conversion = Expression.Call(Runtime.AsListMethod, tailExpr);
                        output.Add(conversion);
                    }
                    else if (mod == Symbols.Params)
                    {
                        output.Add(tailExpr);
                    }
                    else if (mod == Symbols.Vector)
                    {
                        var conversion = Expression.Call(Runtime.AsVectorMethod, tailExpr);
                        output.Add(conversion);
                    }
                }
                else if (mod == Symbols.Optional)
                {
                    for (var i = offset; i < input.Length && i < signature.Parameters.Count; ++i)
                    {
                        output.Add(Expression.Convert(input[i].Expression, elementType));
                    }
                    for (var i = input.Length; i < signature.Parameters.Count; ++i)
                    {
                        var expr = signature.Parameters[i].InitForm ?? Expression.Constant(null);
                        output.Add(expr);
                    }
                    if (input.Length > signature.Parameters.Count)
                    {
                        throw new LispException("Too many arguments supplied");
                    }
                }
                else if (mod == Symbols.Key)
                {
                    var firstKey = offset;
                    var usedKeys = 0;

                    for (var i = firstKey; i < input.Length; i += 2)
                    {
                        if (!Runtime.Keywordp(input[i].Value) || i + 1 == input.Length)
                        {
                            throw new LispException("Invalid keyword/value list");
                        }
                        var keywordRestriction = BindingRestrictions.GetExpressionRestriction(Expression.Equal(input[i].Expression, Expression.Constant(input[i].Value)));
                        restrictions = restrictions.Merge(keywordRestriction);
                    }

                    for (var i = offset; i < signature.Parameters.Count; ++i)
                    {
                        Expression val = null;

                        for (var j = firstKey; j + 1 < input.Length; j += 2)
                        {
                            if (signature.Parameters[i].Sym.Name == ((Symbol)input[j].Value).Name)
                            {
                                val = input[j + 1].Expression;
                                ++usedKeys;
                                break;
                            }
                        }

                        if (val == null)
                        {
                            output.Add(signature.Parameters[i].InitForm ?? Expression.Constant(null));
                        }
                        else
                        {
                            output.Add(Expression.Convert(val, elementType));
                        }
                    }
                }
            }

            if (signature.WholeArg != null)
            {
                var tail = new List <Expression>();
                for (var i = 0; i < input.Length; ++i)
                {
                    tail.Add(Expression.Convert(input[i].Expression, elementType));
                }
                var tailExpr   = Expression.NewArrayInit(elementType, tail);
                var conversion = Expression.Call(Runtime.AsListMethod, tailExpr);
                output.Add(conversion);
            }

            return(Expression.NewArrayInit(elementType, output));
        }
Esempio n. 4
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);
        }
Esempio n. 5
0
        public ParameterDef(Symbol sym, object specializer = null,
            Expression initForm = null,
            Func<object> initFormProc = null,
            LambdaSignature nestedParameters = null,
            bool hidden = false)
        {
            Sym = sym;
            Specializer = specializer;
            NestedParameters = nestedParameters;
            InitForm = initForm;
            InitFormProc = initFormProc;
            Hidden = hidden;

            if (InitForm != null && InitFormProc == null)
            {
                InitFormProc = Runtime.CompileToFunction(initForm);
            }
        }
Esempio n. 6
0
 public MultiMethod(LambdaSignature signature)
 {
     Signature         = signature;
     RequiredArgsCount = signature.RequiredArgsCount;
 }
Esempio n. 7
0
        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, &params 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;
        }
Esempio n. 8
0
 public static Vector GetLambdaArgumentNames(LambdaSignature signature)
 {
     var v = new Vector();
     for (var i = 0; i < signature.Names.Count; ++i)
     {
         if (signature.Names[i] != Symbols.Underscore)
         {
             if (i >= signature.Parameters.Count || !signature.Parameters[i].Hidden)
             {
                 v.Add(signature.Names[i]);
             }
         }
     }
     if (signature.WholeArg != null)
     {
         v.Add(signature.WholeArg);
     }
     if (signature.EnvArg != null)
     {
         v.Add(signature.EnvArg);
     }
     return v;
 }