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); } }
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)); }
//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); }