Пример #1
0
        internal ArgSpecs copy(Env env)
        {
            ArgSpecs a = (ArgSpecs)MemberwiseClone();

            a.env = env;
            return(a);
        }
Пример #2
0
	internal Closure(Cons args,Env env,Interpreter interpreter,Loc loc)
		{
		this.interpreter = interpreter;
		this.loc = loc;
		ArgSpecs specs = analyzeArgSpec((Cons)args.first,env,loc);
		//create an env expanded by params in which to analyze body
		Env env2 = new Env(specs.parameters, null, env, interpreter);

		this.argSpecs = specs;
		this.body = interpreter.analyze(new Cons(interpreter.BLOCK,args.rest), env2,loc);
		this.env = env;
		}
Пример #3
0
        internal Closure(Cons args, Env env, Interpreter interpreter, Loc loc)
        {
            this.interpreter = interpreter;
            this.loc         = loc;
            ArgSpecs specs = analyzeArgSpec((Cons)args.first, env, loc);
            //create an env expanded by params in which to analyze body
            Env env2 = new Env(specs.parameters, null, env);

            this.argSpecs = specs;
            this.body     = interpreter.analyze(new Cons(interpreter.BLOCK, args.rest), env2, loc);
            this.env      = env;
        }
Пример #4
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;
		}
Пример #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);
        }