private IEnumerable <ExecutionMessage> SLet(List <SExpression> args, Environment e) { Environment local = new Environment(e); //TODO BUG: (let () ...) parses the name name bindings that are the pair <EmptyList,NULL> if (args[0] is SPair) { SPair nameBindings = (SPair)args[0]; if (!nameBindings.isProperList()) { throw new Exception("Can't use impro per list in a let"); } List <SExpression> names = nameBindings.flatten(); for (int i = 0; i < names.Count - 1; i++) { String name = ((SID)((SPair)names[i]).getHead()).identifier; SExpression val = ((SPair)((SPair)names[i]).getTail()).getHead(); //Cycle through the yields until done var elmEnum = evaluate(val, e).GetEnumerator(); SExpression elm = null; while (elmEnum.MoveNext()) { ExecutionMessage current = elmEnum.Current; if (current.status == ExecStatus.DONE) { elm = current.returnVal; break; } yield return(current); } local.addVal(name, elm); } } else if (args[0] is SEmptyList) { } else { throw new Exception("Name bindings section of let must be a list"); } //Lets can have an arbitrary number of statements after the name bindings, execute them for stateful effects ExecutionMessage msg = null; for (int i = 1; i < args.Count; i++) { foreach (var tmsg in evaluate(args[i], local)) { msg = tmsg; if (msg.status == ExecStatus.DONE) { continue; } yield return(msg); } } //yield final message yield return(msg); }
public SFunc(SID arglst, SExpression body, Environment e) { arglist = arglst; names = null; //our starting environment is the env we were defined in env = new Environment(e); env.addVal(arglist.identifier, new SNone()); //add bound variables to environment with default None value fixedArgCount = false; this.body = body; }
public SExpression body; //body of execution public SFunc(List <SID> names, SExpression body, Environment e) { //our starting environment is the env we were defined in arglist = null; env = new Environment(e); foreach (SID id in names) { env.addVal(id.identifier, new SNone()); //add bound variables to environment with default None value } this.names = names; this.body = body; fixedArgCount = true; argCount = names.Count; }
private IEnumerable <ExecutionMessage> SDefine(List <SExpression> args, Environment e) { if (e.hasParent()) { throw new Exception("Define only allowed at global scope"); } SID name = (SID)args[0]; ExecutionMessage msg = null; foreach (var tmsg in evaluate(args[1], e)) { msg = tmsg; if (msg.status == ExecStatus.DONE) { break; } yield return(msg); } e.addVal(name.identifier, msg.returnVal); yield return(new ExecutionMessage(ExecStatus.DONE, new SNone())); }
public DerpInterpreter() { callStack = new List <SExpression>(); e = new Environment(); parser = new DerpParser(""); e.addVal("+", new SPrimitive(SAdd, false, 0)); e.addVal("*", new SPrimitive(SMult, false, 0)); e.addVal("/", new SPrimitive(SDiv, true, 2)); e.addVal("-", new SPrimitive(SSub, false, 0)); e.addVal("mod", new SPrimitive(SMod, true, 2)); e.addVal("if", new SPrimitive(SIf, true, 3, false)); e.addVal("let", new SPrimitive(SLet, false, 0, false)); e.addVal("define", new SPrimitive(SDefine, true, 2, false)); e.addVal("lambda", new SPrimitive(SLambda, true, 2, false)); e.addVal("debug", new SPrimitive(SDebug, true, 1)); e.addVal("list", new SPrimitive(SList, false, 0)); e.addVal("cons", new SPrimitive(SCons, true, 2)); e.addVal("car", new SPrimitive(SCar, true, 1)); e.addVal("cdr", new SPrimitive(SCdr, true, 1)); e.addVal("null?", new SPrimitive(SNullList, true, 1)); e.addVal("=", new SPrimitive(SEq, true, 2)); e.addVal(">", new SPrimitive(SGt, true, 2)); e.addVal("<", new SPrimitive(SLt, true, 2)); e.addVal("begin", new SPrimitive(SBegin, false, 0)); e.addVal("typeof", new SPrimitive(TypeOf, false, 1)); e.addVal("eval", new SPrimitive(Eval, false, 1)); }