public static Cons Last(int num,Cons list) { int len = Length(list); if(num > len) return null; return NthTail(len-num,list); }
public static Object MakeList(params Object[] args) { Cons ret = null; for(int i = args.Length-1;i>=0;--i) { ret = new Cons(args[i],ret); } return ret; }
public static Cons Reverse(Cons list) { Cons result = null; while(list != null) { result = new Cons(list.first, result); list = list.rest; } return result; }
public static int Length(Cons list) { int len = 0; while(list != null) { len++; list = list.rest; } return len; }
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; }
public static Object concat_d(params Object[] args) { Cons tail = (Cons)args[args.Length - 1]; for (int x = args.Length - 2; x >= 0; --x) { Cons prev = (Cons)args[x]; if (prev != null) { Cons.Last(1, prev).rest = tail; tail = prev; } } return(tail); }
public static Object macroexpand_1(params Object[] args) { Cons x = (Cons)arg(0, args); Symbol s = x.first as Symbol; if (s != null && s.isDefined() && s.getGlobalValue() is Macro) { Macro m = (Macro)s.getGlobalValue(); Object[] argarray = Cons.ToVector(x.rest); return(m.Invoke(argarray)); } else { return(x); } }
public override String ToString() { StringBuilder buf = new StringBuilder(); buf.Append('('); buf.Append(first.ToString()); Cons tail = rest; while (tail != null) { buf.Append(' '); buf.Append(tail.first.ToString()); tail = tail.rest; } buf.Append(')'); return(buf.ToString()); }
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 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); } }
public override String ToString() { // MEH: Avoid ToString throwing a null reference exception if first is nil. StringBuilder buf = new StringBuilder(); buf.Append('('); buf.Append(firstToString()); Cons tail = rest; while (tail != null) { buf.Append(' '); buf.Append(tail.firstToString()); tail = tail.rest; } buf.Append(')'); return(buf.ToString()); }
public static Object[] ToVector(Cons list) { int len = Length(list); if (len == 0) { return(Util.EMPTY_VECTOR); } else { Object[] result = new Object[len]; for (int i = 0; list != null; i++, list = list.rest) { result[i] = list.first; } return(result); } }
internal Object splitSymbol(String s) { //turn x[y] into ([y] x) - can we with readvector in place? //Int32 bridx = s.LastIndexOf("["); Int32 dotidx = s.LastIndexOf("."); Int32 colonidx = s.LastIndexOf(":"); //dot in the middle and not member(dot at start) or type(dot at end) if (dotidx >= 0 && dotidx > colonidx && dotidx < (s.Length - 1) && s[0] != '.') { //turn x.y into (.y x) return(Cons.MakeList(interpreter.intern(s.Substring(dotidx)), splitSymbol(s.Substring(0, dotidx)))); } return(interpreter.intern(s)); }
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 map_to_list(params Object[] args) { Object f = Primitives.arg(0, args); IEnumerator[] enums = new IEnumerator[args.Length - 1]; for (int i = 0; i < enums.Length; i++) { enums[i] = (IEnumerator)get_enum_gf.Invoke(Primitives.arg(i + 1, args)); } //n.b. setting up arg array which will be reused //mean functions cannot assume ownership of args w/o copying them Object[] fargs = new Object[enums.Length]; Cons ret = null; Cons tail = null; while (true) { for (int i = 0; i < enums.Length; i++) { if (enums[i].MoveNext()) { fargs[i] = enums[i].Current; } else //bail on shortest { return(ret); } } Object x = Util.InvokeObject(f, fargs); Cons node = new Cons(x, null); if (ret == null) { ret = tail = node; } else { tail = tail.rest = node; } } }
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); }
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 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)); }
public static Object First(Cons list) { return list.first; }
public static Cons Append(Cons x, Cons y) { return(x != null) ? new Cons(x.first, Append(x.rest, y)) : y; }
public static Cons NthTail(int n,Cons list) { while(n > 0) { n--; list = list.rest; } return list; }
public Cons(Object first,Cons rest) { this.first = first; this.rest = rest; }
public Cons(Object first, Cons rest) { this.first = first; this.rest = rest; }
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); }
private Boolean equalsFirst(Cons that) { return(first == null) ? that.first == null : first.Equals(that.first); }
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 CompositeSymbol(Cons symAsList) { this.symbolAsList = symAsList; }
internal Cons readDelimitedList(LocTextReader t,Int32 delim) { Cons ret = null; Cons tail = null; Int32 ch = t.Peek(); while(Char.IsWhiteSpace((Char)ch)) { t.Read(); ch = t.Peek(); } while(ch != delim) { Object o = doRead(t,delim == ')' && ret == null); if(eof(o)) { throw new Exception("Read error - eof found before matching: " + (Char)delim + "\n File: " + t.file + ", line: " + t.line); } EndDelimiter ed = o as EndDelimiter; if(ed != null) { if(ed.delim == delim) { return ret; } else throw new Exception("Read error - read unmatched: " + ed.delim + "\n File: " + t.file + ", line: " + t.line); } Cons link = new Cons(o,null); if(delim == ')' && ret == null && o is CompositeSymbol) { ret = ((CompositeSymbol)o).symbolAsList; tail = ret.rest; } else if(ret == null) { ret = tail = link; } else { tail.rest = link; tail = link; } ch = t.Peek(); while(Char.IsWhiteSpace((Char)ch)) { t.Read(); ch = t.Peek(); } } //eat delim t.Read(); return ret; }
internal Macro(Cons args, Env env, Interpreter interpreter, Loc loc) : base(args, env, interpreter, loc) { }
private Boolean equalsFirst(Cons that) { return((first == null) ? that.first == null : first.Equals(that.first)); }
private Boolean equalsRest(Cons that) { return((rest == null) ? that.rest == null : rest.Equals(that.rest)); }
public static Object Second(Cons list) { return list.rest.first; }
public static Object Fourth(Cons list) { return Third(list.rest); }
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)); } }
public static Object Nth(int n, Cons list) { return(NthTail(n, list).first); }
public static Object Fourth(Cons list) { return(Third(list.rest)); }
public object ObjectToLisp(object prim) { OSD data = OSD.FromObject(prim); if (data.Type!=OSDType.Unknown) return SerializeLisp(data); Type t = prim.GetType(); foreach (FieldInfo PI in t.GetFields(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public)) { object value = ToLispValue( PI.FieldType, PI.GetValue(prim)); object kv = new Cons(PI.Name, new Cons(value, null)); } return prim; }
public Boolean MoveNext() { current = next; if(current != null) next = current.rest; return current != null; }
//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); }
public void Reset() { this.current = null; this.next = start; }
public static Object Nth(int n,Cons list) { return NthTail(n,list).first; }
public static Object Third(Cons list) { return(Second(list.rest)); }
public static Object[] ToVector(Cons list) { int len = Length(list); if(len == 0) return Util.EMPTY_VECTOR; else { Object[] result = new Object[len]; for(int i = 0; list!=null; i++, list = list.rest) { result[i] = list.first; } return result; } }
public static Object Second(Cons list) { return(list.rest.first); }
public ConsEnumerator(Cons start) { this.start = start; this.current = null; this.next = start; }
public static Object Rest(Cons list) { return(list.rest); }
public static Object Rest(Cons list) { return list.rest; }
public static Object First(Cons list) { return(list.first); }
public static Object Third(Cons list) { return Second(list.rest); }
internal Cons readDelimitedList(LocTextReader t, Int32 delim) { Cons ret = null; Cons tail = null; Int32 ch = t.Peek(); //MEH: Check for EOF too. while (ch != -1 && Char.IsWhiteSpace((Char)ch)) { t.Read(); ch = t.Peek(); } while (ch != delim) { Object o = doRead(t, delim == ')' && ret == null); if (eof(o)) { throw new Exception("Read error - eof found before matching: " + (Char)delim + "\n File: " + t.file + ", line: " + t.line); } EndDelimiter ed = o as EndDelimiter; if (ed != null) { if (ed.delim == delim) { return(ret); } else { throw new Exception("Read error - read unmatched: " + ed.delim + "\n File: " + t.file + ", line: " + t.line); } } Cons link = new Cons(o, null); if (delim == ')' && ret == null && o is CompositeSymbol) { ret = ((CompositeSymbol)o).symbolAsList; tail = ret.rest; } else if (ret == null) { ret = tail = link; } else { tail.rest = link; tail = link; } ch = t.Peek(); //MEH: Check for EOF too. while (ch != -1 && Char.IsWhiteSpace((Char)ch)) { t.Read(); ch = t.Peek(); } } //eat delim t.Read(); return(ret); }
public static Cons Append(Cons x, Cons y) { return((x != null) ? new Cons(x.first, Append(x.rest, y)) : y); }
private Boolean equalsRest(Cons that) { return(rest == null) ? that.rest == null : rest.Equals(that.rest); }
//returns an array of evaluated args corresponding to params of argspec, //including substitution of default values where none provided, construction of //rest list etc //suitable for extending the environment prior to evaluating body of closure internal Object[] buildParamArray(Object[] code, Int32 offset, Env env//, Boolean evalArgs ) { //do nothing if fixed params and matching number if(argSpecs.nParams() == argSpecs.numReq && argSpecs.numReq == code.Length) return code; Object[] argArray = new Object[nParms()]; int nargs = code.Length-offset; if(nargs < argSpecs.numReq) throw new Exception("Too few arguments to procedure, expected at least " + argSpecs.numReq +", but found "+ nargs +" arguments"); int i; // Fill in the required parameters for(i = 0; i < argSpecs.numReq; i++) { argArray[i] = //evalArgs?Interpreter.execute(code[i+offset], env): code[i+offset]; } //now grab args to satisfy optionals if(argSpecs.numOpt > 0) { for(i = argSpecs.numReq; i < argSpecs.numReq + argSpecs.numOpt; i++) { if(i<nargs) { argArray[i] = //evalArgs?Interpreter.execute(code[i+offset], env): code[i+offset]; //if missing passed to optional, get default if(argArray[i] == Missing.Value) { argArray[i] = getDefaultParamValue(argSpecs.parameters[i]); } } else //ran out of args, default the rest { argArray[i] = getDefaultParamValue(argSpecs.parameters[i]); } } } //build a rest list Cons rest = null; for(int x = code.Length-1;x-offset >= i; --x) { Object val = //evalArgs?Interpreter.execute(code[x], env): code[x]; rest = new Cons(val, rest); } //search for key args in rest if(argSpecs.numKey > 0) { for(i = argSpecs.numReq + argSpecs.numOpt; i < argSpecs.numReq + argSpecs.numOpt + argSpecs.numKey; i++) { argArray[i] = findKeyParamValue(argSpecs.parameters[i],rest); } } // Add the rest parameter (if there is one) if(argSpecs.numRest == 1) { argArray[i] = rest; } return argArray; }
internal Object map_to_list(params Object[] args) { Object f = Primitives.arg(0,args); IEnumerator[] enums = new IEnumerator[args.Length - 1]; for(int i=0;i<enums.Length;i++) { enums[i] = (IEnumerator)get_enum_gf.Invoke(Primitives.arg(i+1,args)); } //n.b. setting up arg array which will be reused //mean functions cannot assume ownership of args w/o copying them Object[] fargs = new Object[enums.Length]; Cons ret = null; Cons tail = null; while(true) { for(int i=0;i<enums.Length;i++) { if(enums[i].MoveNext()) fargs[i] = enums[i].Current; else //bail on shortest return ret; } Object x = Util.InvokeObject(f,fargs); Cons node = new Cons(x,null); if(ret == null) ret = tail = node; else tail = tail.rest = node; } }
//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; }
//returns an array of evaluated args corresponding to params of argspec, //including substitution of default values where none provided, construction of //rest list etc //suitable for extending the environment prior to evaluating body of closure internal Object[] buildParamArray(Object[] code, Int32 offset, Env env //, Boolean evalArgs ) { //do nothing if fixed params and matching number if (argSpecs.nParams() == argSpecs.numReq && argSpecs.numReq == code.Length) { return(code); } Object[] argArray = new Object[nParms()]; int nargs = code.Length - offset; if (nargs < argSpecs.numReq) { throw new Exception("Too few arguments to procedure, expected at least " + argSpecs.numReq + ", but found " + nargs + " arguments"); } int i; // Fill in the required parameters for (i = 0; i < argSpecs.numReq; i++) { argArray[i] = //evalArgs?Interpreter.execute(code[i+offset], env): code[i + offset]; } //now grab args to satisfy optionals if (argSpecs.numOpt > 0) { for (i = argSpecs.numReq; i < argSpecs.numReq + argSpecs.numOpt; i++) { if (i < nargs) { argArray[i] = //evalArgs?Interpreter.execute(code[i+offset], env): code[i + offset]; //if missing passed to optional, get default if (argArray[i] == Missing.Value) { argArray[i] = getDefaultParamValue(argSpecs.parameters[i]); } } else //ran out of args, default the rest { argArray[i] = getDefaultParamValue(argSpecs.parameters[i]); } } } //build a rest list Cons rest = null; for (int x = code.Length - 1; x - offset >= i; --x) { Object val = //evalArgs?Interpreter.execute(code[x], env): code[x]; rest = new Cons(val, rest); } //search for key args in rest if (argSpecs.numKey > 0) { for (i = argSpecs.numReq + argSpecs.numOpt; i < argSpecs.numReq + argSpecs.numOpt + argSpecs.numKey; i++) { argArray[i] = findKeyParamValue(argSpecs.parameters[i], rest); } } // Add the rest parameter (if there is one) if (argSpecs.numRest == 1) { argArray[i] = rest; } return(argArray); }
public static object SerializeLisp(OSD osd) { switch (osd.Type) { case OSDType.Unknown: throw new InvalidCastException(); case OSDType.Boolean: return osd.AsBoolean(); case OSDType.Integer: return osd.AsInteger(); case OSDType.Real: return osd.AsReal(); case OSDType.String: return osd.AsString(); case OSDType.Date: return osd.AsDate(); case OSDType.URI: return osd.AsUri(); case OSDType.UUID: return osd.AsUUID(); case OSDType.Binary: return osd.AsBinary(); case OSDType.Array: OSDArray args = (OSDArray) osd; Cons ret = null; for (int i = args.Count - 1; i >= 0; --i) { ret = new Cons(args[i], ret); } return ret; case OSDType.Map: Cons list = null; OSDMap map = (OSDMap) osd; foreach (KeyValuePair<string, OSD> kvp in map) { Cons kv = new Cons(kvp.Key, new Cons(SerializeLisp(kvp.Value))); list = new Cons(kv,list); } return Cons.Reverse(list); default: return osd; } }
public static Object listlength(params Object[] args) { Cons x = (Cons)arg(0, args); return(Cons.Length(x)); }