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;
        }
 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);
     }
 }
Esempio n. 4
0
 internal Macro(Cons args, Env env, Interpreter interpreter, Loc loc)
     : base(args, env, interpreter, 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);
        }
 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;
 }
 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;
 }
 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;
 }
 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;
 }
Esempio n. 10
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;
 }
 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);
 }
 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 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);
     }
 }
 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);
 }
 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);
 }
Esempio n. 16
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;
        }