Example #1
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;
		}
 internal BacktraceFrame(Loc loc,Object f,Object args)
 {
     if(loc != null)
     {
     this.file = loc.file;
     this.line = loc.line;
     }
     else
     {
     this.file = "no file";
     this.line = 0;
     }
     this.f = f;
     this.args = args;
 }
 internal ApplyExpression(Cons args,Env env,Interpreter interpreter,Loc loc)
 {
     this.loc = loc;
     this.interpreter = interpreter;
     fexpr = interpreter.analyze(args.first,env,loc);
     if(fexpr is IVar)
     {
     fsym = ((IVar)fexpr).getSymbol();
     }
     Int32 len = Cons.Length(args.rest);
     argexprs = new IExpression[len];
     args = args.rest;
     for(Int32 i=0;i<argexprs.Length;i++,args = args.rest)
     {
     argexprs[i] = interpreter.analyze(args.first,env,loc);
     }
 }
        internal IExpression analyze(Object expr, Env env, Loc enclosingLoc)
        {
            Symbol symbol = expr as Symbol;
            if(symbol != null)
            {
            if(symbol.isDynamic)
                return new DynamicVar(symbol);
            Object var = env.lookup(symbol);
            if(var is LocalVariable)
                return new LocalVar((LocalVariable)var);
            else
                return new GlobalVar((Symbol)var);
            }
            if(!(expr is Cons))	 //must be literal
            return new QuoteExpr(expr);

            Cons exprs = (Cons)expr;

            Loc loc = (Loc)reader.locTable[expr];
            if(loc != null)
            reader.locTable.Remove(expr);
            else
            loc = enclosingLoc;

            Object f = exprs.first;
            Cons args = exprs.rest;

            //see if it's a macro
            Symbol s = f as Symbol;
            if(s != null && s.isDefined() && s.getGlobalValue() is Macro)
            {
            Macro m = (Macro)s.getGlobalValue();
            Object[] argarray = Cons.ToVector(args);
            Object mexprs = null;
            try
                {
                mexprs = m.Invoke(argarray);
                }
            catch(Exception ex)
                {
                BacktraceFrame frame = new BacktraceFrame(loc,s,args);
                throw BacktraceException.push(ex,frame,this);
                }
            try
                {
                return analyze(mexprs,env,loc);
                }
            catch(Exception ex)
                {
                BacktraceFrame frame = new BacktraceFrame(loc,"when expanding ",exprs);
                throw BacktraceException.push(ex,frame,this);
                }
            }
            Int32 numargs = Cons.Length(args);

            if(f == DLET)
            return new DynamicLet(args,env,this,loc);
            else if(f == FN)
            return new Closure(args,env,this,loc);
            else if(f == MACRO)
            return new Macro(args,env,this,loc);
            else if(f == WHILE)
            return new WhileExpression(args,env,this,loc);
            else if(f == BLOCK)
            {
            if(numargs == 0)
                return new QuoteExpr(null);
            //remove block from block of one
            else if(numargs == 1)
                return analyze(args.first,env,loc);
            else
                return new BlockExpression(args,env,this,loc);
            }
            else if(f == OR)
            {
            if(numargs == 0)
                return new QuoteExpr(null);
            else
                return new OrExpression(args,env,this,loc);
            }
            else if(f == IF)
            return new IfExpression(args,env,this,loc);
            else if(f == QUOTE)
            return new QuoteExpr(args.first);
            else if(f == SET)
            return new SetExpression(args,env,this,loc);
            else	//presume funcall
            return new ApplyExpression(exprs,env,this,loc);
        }
Example #5
0
	internal Object Load(LocTextReader t)
		{
		Object expr = null;
		do    
			{
			Int32 line = t.line;
			expr = Read(t);
			if(!Eof(expr))
				{
				try
					{
					eval(expr,globalenv);
					}
				catch(Exception ex)
					{
                        Loc loc = new Loc(t.file, line);
					    Console.Error.WriteLine(ex);
                        Console.Error.WriteLine("loc=" + loc);

                        Console.ReadLine();
					throw BacktraceException.push(ex,
                                                            new BacktraceFrame(loc, "when evaluating ", expr), this);
					}
				}
			}while(!Eof(expr));
		return true;
		}
Example #6
0
 internal Object ReadVector(params Object[] args)
 {
     LocTextReader t = (LocTextReader)args[0];
     Int32 line = t.line;
     Cons largs = readDelimitedList(t,']');
     Object ret = new Cons(interpreter.VECTOR,largs);
     //record the location
     locTable[ret] = new Loc(t.file,line);
     return ret;
 }
Example #7
0
 internal Object ReadUnquote(params Object[] args)
 {
     LocTextReader t = (LocTextReader)args[0];
     Int32 line = t.line;
     Int32 ch = t.Peek();
     Object ret = null;
     if(ch == '@')
     {
     t.Read();
     ret = Cons.MakeList(interpreter.UNQUOTE_SPLICING,doRead(t,false));
     }
     else
     ret = Cons.MakeList(interpreter.UNQUOTE,doRead(t,false));
     //record the location
     locTable[ret] = new Loc(t.file,line);
     return ret;
 }
Example #8
0
 internal Object ReadString(params Object[] args)
 {
     StringBuilder b = new StringBuilder();
     LocTextReader t = (LocTextReader)args[0];
     Int32 line = t.line;
     //eat the double-quote
     //t.Read();
     //Int32 ch = t.Peek();
     Int32 ch = t.Read();
     while(ch != '"')
     {
     if(ch == -1)
         {
         throw new Exception("Read error - eof found before matching: \""
                                   + "\n File: " + t.file + ", line: " + t.line);
         }
     //eat it
     //t.Read();
     if(ch == '\\')	//escape
         {
         ch = t.Read();
         if(ch == -1)
             {
             throw new Exception("Read error - eof found before matching: \""
                                       + "\n File: " + t.file + ", line: " + t.line);
             }
         switch(ch)
             {
             case 't':
                 ch = '\t';
                 break;
             case 'r':
                 ch = '\r';
                 break;
             case 'n':
                 ch = '\n';
                 break;
             case '\\':
                 break;
             case '"':
                 break;
             default:
                 throw new Exception("Unsupported escape character: \\" + (Char)ch
                                           + "\n File: " + t.file + ", line: " + t.line);
             }
         }
     b.Append((Char)ch);
     //ch = t.Peek();
     ch = t.Read();
     }
     //eat the trailing quote
     //t.Read();
     Object ret = b.ToString();
     //record the location
     locTable[ret] = new Loc(t.file,line);
     return ret;
 }
Example #9
0
 internal Object ReadQuote(params Object[] args)
 {
     LocTextReader t = (LocTextReader)args[0];
     Int32 line = t.line;
     Object ret = Cons.MakeList(interpreter.QUOTE,doRead(t,false));
     //record the location
     locTable[ret] = new Loc(t.file,line);
     return ret;
 }
Example #10
0
	internal Macro(Cons args,Env env,Interpreter interpreter,Loc loc)
	:base(args,env,interpreter,loc)
		{
		}
Example #11
0
	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);
		}
Example #12
0
	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);
		}
Example #13
0
	internal OrExpression(Cons args,Env env,Interpreter interpreter,Loc loc)
		{
		this.loc = loc;
		this.interpreter = interpreter;
		exprs = new IExpression[Cons.Length(args)];
		for(Int32 i=0;i<exprs.Length;i++,args = args.rest)
			{
			exprs[i] = interpreter.analyze(args.first,env,loc);
			}
		}
Example #14
0
	internal WhileExpression(Cons args,Env env,Interpreter interpreter,Loc loc)
		{
		this.loc = loc;
		this.interpreter = interpreter;
		this.test = interpreter.analyze(args.first,env,loc);
		this.body = interpreter.analyze(new Cons(interpreter.BLOCK,args.rest),env,loc);
		}
Example #15
0
	internal DynamicLet(Cons args,Env env,Interpreter interpreter,Loc loc)
		{
		this.loc = loc;
		this.interpreter = interpreter;
		Cons bindlist = (Cons)args.first;
		Int32 blen = Cons.Length(bindlist);
		if((blen%2) != 0)	//odd
			{
			throw new Exception("Odd number of args in dynamic-let binding list");
			}
		binds = new BindPair[blen/2];
		for(int i = 0;i<binds.Length;i++)
			{
			binds[i].dvar = (DynamicVar)interpreter.analyze(bindlist.first, env,loc);
			bindlist = bindlist.rest;
			binds[i].expr = interpreter.analyze(bindlist.first, env,loc);
			bindlist = bindlist.rest;
			}
		this.body = interpreter.analyze(new Cons(interpreter.BLOCK,args.rest), env,loc);
		}
Example #16
0
	internal DynamicLet(Cons args,Env env,Interpreter interpreter,Loc loc)
		{
		this.loc = loc;
		this.interpreter = interpreter;
		Cons bindlist = (Cons)args.first;
		Int32 blen = Cons.Length(bindlist);
		if((blen%2) != 0)	//odd
			{
			throw new Exception("Odd number of args in dynamic-let binding list");
			}
		binds = new BindPair[blen/2];
		for(int i = 0;i<binds.Length;i++)
			{
			// MEH: Better error instead of InvalidCastException
			//binds[i].dvar = (DynamicVar)interpreter.analyze(bindlist.first, env,loc);
			if((binds[i].dvar = (interpreter.analyze(bindlist.first, env,loc) as DynamicVar)) == null)
				throw new Exception("Dynamic vars must have prefix *");
			bindlist = bindlist.rest;
			binds[i].expr = interpreter.analyze(bindlist.first, env,loc);
			bindlist = bindlist.rest;
			}
		this.body = interpreter.analyze(new Cons(interpreter.BLOCK,args.rest), env,loc);
		}
Example #17
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;
		}
Example #18
0
 internal Object ReadList(params Object[] args)
 {
     LocTextReader t = (LocTextReader)args[0];
     Int32 line = t.line;
     Object ret = readDelimitedList(t,')');
     //record the location
     if(ret != null)
     locTable[ret] = new Loc(t.file,line);
     return ret;
 }