Beispiel #1
0
        public static Object second(params Object[] args)
        {
            Cons x = (Cons)arg(0, args);

            if (x == null)
            {
                return(null);
            }
            return(Cons.Second(x));;
        }
        internal SetExpression(Cons args, Env env, Interpreter interpreter, Loc loc)
        {
            this.loc         = loc;
            this.interpreter = interpreter;
            Int32 len = Cons.Length(args);

            if (len != 2)
            {
                throw new Exception("Wrong number of args for set");
            }
            var = (IVar)interpreter.analyze(args.first, env, loc);
            val = interpreter.analyze(Cons.Second(args), env, loc);
        }
        internal IfExpression(Cons args, Env env, Interpreter interpreter, Loc loc)
        {
            this.loc         = loc;
            this.interpreter = interpreter;
            Int32 len = Cons.Length(args);

            if (len < 2 || len > 3)
            {
                throw new Exception("Wrong number of args for if");
            }
            test   = interpreter.analyze(args.first, env, loc);
            brtrue = interpreter.analyze(Cons.Second(args), env, loc);
            if (len == 3)
            {
                brfalse = interpreter.analyze(Cons.Third(args), env, loc);
            }
            else
            {
                brfalse = new QuoteExpr(null);
            }
        }
Beispiel #4
0
 internal Object findKeyParamValue(Parameter p, Cons args)
 {
     for (; args != null; args = args.rest)
     {
         if (args.first == p.key)
         {
             if (args.rest != null)
             {
                 Object ret = Cons.Second(args);
                 if (ret == Missing.Value)
                 {
                     ret = getDefaultParamValue(p);
                 }
                 return(ret);
             }
             else
             {
                 throw   new Exception("Key args must be provided in pairs of [:key value]");
             }
         }
     }
     return(getDefaultParamValue(p));
 }
Beispiel #5
0
        //parse out params from spec (which may contain &optional, &key, &rest, initforms etc

        internal ArgSpecs analyzeArgSpec(Cons arglist, Env env, Loc loc)
        {
            //count the params
            int  nParams = 0;
            Cons a       = arglist;

            while (a != null)
            {
                Object p = a.first;
                if (p != interpreter.AMPOPT && p != interpreter.AMPKEY && p != interpreter.AMPREST)
                {
                    ++nParams;
                }
                a = a.rest;
            }

            ArgSpecs ret = new ArgSpecs(env);

            ret.parameters = new Parameter[nParams];
            Parameter.Spec state = Parameter.Spec.REQ;

            int param = 0;

            a = arglist;
            while (a != null)
            {
                Object p = a.first;
                switch (state)
                {
                case Parameter.Spec.REQ:
                    if (p == interpreter.AMPOPT)
                    {
                        state = Parameter.Spec.OPT;
                    }
                    else if (p == interpreter.AMPKEY)
                    {
                        state = Parameter.Spec.KEY;
                    }
                    else if (p == interpreter.AMPREST)
                    {
                        state = Parameter.Spec.REST;
                    }
                    else
                    {
                        if (p is Symbol)
                        {
                            ret.parameters[param++] =
                                new Parameter((Symbol)p, Parameter.Spec.REQ, null);
                            ++ret.numReq;
                        }
                        else if (p is Cons)
                        {
                            ret.parameters[param] =
                                new Parameter((Symbol)((Cons)p).first, Parameter.Spec.REQ, null);
                            ret.parameters[param].typeSpec = interpreter.eval(Cons.Second((Cons)p), env);
                            ++param;
                            ++ret.numReq;
                        }
                    }
                    break;

                case Parameter.Spec.OPT:
                    if (p == interpreter.AMPOPT)
                    {
                        throw new Exception("&optional can appear only once in arg list");
                    }
                    else if (p == interpreter.AMPKEY)
                    {
                        state = Parameter.Spec.KEY;
                    }
                    else if (p == interpreter.AMPREST)
                    {
                        state = Parameter.Spec.REST;
                    }
                    else
                    {
                        if (p is Symbol)
                        {
                            ret.parameters[param++] =
                                new Parameter((Symbol)p, Parameter.Spec.OPT, null);
                            ++ret.numOpt;
                        }
                        else if (p is Cons)
                        {
                            ret.parameters[param++] =
                                new Parameter((Symbol)((Cons)p).first, Parameter.Spec.OPT,
                                              interpreter.analyze(Cons.Second((Cons)p), env, loc));
                            ++ret.numOpt;
                        }
                        else
                        {
                            throw   new Exception("&optional parameters must be symbols or (symbol init-form)");
                        }
                    }
                    break;

                case Parameter.Spec.KEY:
                    if (p == interpreter.AMPOPT)
                    {
                        throw new Exception("&optional must appear before &key in arg list");
                    }
                    else if (p == interpreter.AMPKEY)
                    {
                        throw new Exception("&key can appear only once in arg list");
                    }
                    else if (p == interpreter.AMPREST)
                    {
                        state = Parameter.Spec.REST;
                    }
                    else
                    {
                        if (p is Symbol)
                        {
                            ret.parameters[param] =
                                new Parameter((Symbol)p, Parameter.Spec.KEY, null);
                            ret.parameters[param].key = interpreter.intern(":" + ((Symbol)p).name);
                            ++param;
                            ++ret.numKey;
                        }
                        else if (p is Cons)
                        {
                            ret.parameters[param] =
                                new Parameter((Symbol)((Cons)p).first, Parameter.Spec.KEY,
                                              interpreter.analyze(Cons.Second((Cons)p), env, loc));
                            ret.parameters[param].key =
                                interpreter.intern(":" + ((Symbol)((Cons)p).first).name);
                            ++param;
                            ++ret.numKey;
                        }
                        else
                        {
                            throw   new Exception("&key parameters must be symbols or (symbol init-form)");
                        }
                    }
                    break;

                case Parameter.Spec.REST:
                    if (p == interpreter.AMPOPT)
                    {
                        throw new Exception("&optional must appear before &rest in arg list");
                    }
                    else if (p == interpreter.AMPKEY)
                    {
                        throw new Exception("&key must appear before &rest in arg list");
                    }
                    else if (p == interpreter.AMPREST)
                    {
                        throw new Exception("&rest can appear only once in arg list");
                    }
                    else
                    {
                        if (!(p is Symbol))
                        {
                            throw new Exception("&rest parameter must be a symbol");
                        }
                        else
                        {
                            if (ret.numRest > 0)                            //already got a rest param
                            {
                                throw new Exception("Only one &rest arg can be specified");
                            }
                            ret.parameters[param++] =
                                new Parameter((Symbol)p, Parameter.Spec.REST, null);
                            ++ret.numRest;
                        }
                    }
                    break;
                }

                a = a.rest;
            }

            return(ret);
        }