public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (pcon.Rhc != RHC.Return) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)), "try__" + RT.nextID()); // (try try-expr* catch-expr* finally-expr?) // catch-expr: (catch class sym expr*) // finally-expr: (finally expr*) IPersistentVector body = PersistentVector.EMPTY; IPersistentVector catches = PersistentVector.EMPTY; Expr bodyExpr = null; Expr finallyExpr = null; bool caught = false; int retLocal = Compiler.GetAndIncLocalNum(); int finallyLocal = Compiler.GetAndIncLocalNum(); for (ISeq fs = form.next(); fs != null; fs = fs.next()) { object f = fs.first(); object op = (f is ISeq) ? ((ISeq)f).first() : null; if (!Util.equals(op, Compiler.CATCH) && !Util.equals(op, Compiler.FINALLY)) { if (caught) throw new Exception("Only catch or finally clause can follow catch in try expression"); body = body.cons(f); } else { if (bodyExpr == null) bodyExpr = new BodyExpr.Parser().Parse(pcon.SetAssign(false),RT.seq(body)); if (Util.equals(op, Compiler.CATCH)) { Type t = HostExpr.MaybeType(RT.second(f), false); if (t == null) throw new ArgumentException("Unable to resolve classname: " + RT.second(f)); if (!(RT.third(f) is Symbol)) throw new ArgumentException("Bad binding form, expected symbol, got: " + RT.third(f)); Symbol sym = (Symbol)RT.third(f); if (sym.Namespace != null) throw new Exception("Can't bind qualified name: " + sym); IPersistentMap dynamicBindings = RT.map( Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.NEXT_LOCAL_NUM, Compiler.NEXT_LOCAL_NUM.deref(), Compiler.IN_CATCH_FINALLY, true); try { Var.pushThreadBindings(dynamicBindings); LocalBinding lb = Compiler.RegisterLocal(sym, (Symbol)(RT.second(f) is Symbol ? RT.second(f) : null), null,false); Expr handler = (new BodyExpr.Parser()).Parse(pcon.SetAssign(false), RT.next(RT.next(RT.next(f)))); catches = catches.cons(new CatchClause(t, lb, handler)); ; } finally { Var.popThreadBindings(); } caught = true; } else // finally { if (fs.next() != null) throw new Exception("finally clause must be last in try expression"); try { //Var.pushThreadBindings(RT.map(Compiler.IN_CATCH_FINALLY, RT.T)); Var.pushThreadBindings(RT.map(Compiler.IN_CATCH_FINALLY, true)); finallyExpr = (new BodyExpr.Parser()).Parse(pcon.SetRhc(RHC.Statement).SetAssign(false), RT.next(f)); } finally { Var.popThreadBindings(); } } } } if ( bodyExpr == null ) bodyExpr = (new BodyExpr.Parser()).Parse(pcon, RT.seq(body)); return new TryExpr(bodyExpr, catches, finallyExpr, retLocal, finallyLocal); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LoopSym); IPersistentVector bindings = RT.second(form) as IPersistentVector; if (bindings == null) throw new ParseException("Bad binding form, expected vector"); if ((bindings.count() % 2) != 0) throw new ParseException("Bad binding form, expected matched symbol/value pairs."); ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID()); ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = PersistentVector.EMPTY; for (int i = 0; i < bindings.count() / 2; i++) { recurMismatches = recurMismatches.cons(false); } // may repeat once for each binding with a mismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); method.Locals = backupMethodLocals; method.IndexLocals = backupMethodIndexLocals; if (isLoop) dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null); try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) throw new ParseException("Can't let qualified name: " + sym); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); if (isLoop) { if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2)) ) { HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); List<HostArg> has = new List<HostArg>(1); has.Add(ha); init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false); if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); } else if (Compiler.MaybePrimitiveType(init) == typeof(int)) { List<HostArg> args = new List<HostArg>(); args.Add(new HostArg(HostArg.ParameterType.Standard, init, null)); init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false); } else if (Compiler.MaybePrimitiveType(init) == typeof(float)) { List<HostArg> args = new List<HostArg>(); args.Add(new HostArg(HostArg.ParameterType.Standard, init, null)); init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false); } } // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) loopLocals = loopLocals.cons(b); } if (isLoop) Compiler.LoopLocalsVar.set(loopLocals); Expr bodyExpr; bool moreMismatches = false; try { if (isLoop) { // stuff with clear paths, Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null)); } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { Var.popThreadBindings(); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMismatch) { recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true); moreMismatches = true; } } } } if (!moreMismatches) return new LetExpr(bindingInits, bodyExpr, isLoop); } finally { Var.popThreadBindings(); } } }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (pcon.Rhc != RHC.Return) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "try__" + RT.nextID())); } // (try try-expr* catch-expr* finally-expr?) // catch-expr: (catch class sym expr*) // finally-expr: (finally expr*) IPersistentVector body = PersistentVector.EMPTY; IPersistentVector catches = PersistentVector.EMPTY; Expr bodyExpr = null; Expr finallyExpr = null; bool caught = false; ParserContext recursePcon = new ParserContext(RHC.Expression, false); int retLocal = Compiler.GetAndIncLocalNum(); int finallyLocal = Compiler.GetAndIncLocalNum(); for (ISeq fs = form.next(); fs != null; fs = fs.next()) { object f = fs.first(); ISeq fSeq = f as ISeq; object op = fSeq != null?fSeq.first() : null; if (!Util.equals(op, Compiler.CatchSym) && !Util.equals(op, Compiler.FinallySym)) { if (caught) { throw new ParseException("Only catch or finally clause can follow catch in try expression"); } body = body.cons(f); } else { if (bodyExpr == null) { try { Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, true)); bodyExpr = new BodyExpr.Parser().Parse(pcon, RT.seq(body)); } finally { Var.popThreadBindings(); } } if (Util.equals(op, Compiler.CatchSym)) { Type t = HostExpr.MaybeType(RT.second(f), false); if (t == null) { throw new ParseException("Unable to resolve classname: " + RT.second(f)); } if (!(RT.third(f) is Symbol)) { throw new ParseException("Bad binding form, expected symbol, got: " + RT.third(f)); } Symbol sym = (Symbol)RT.third(f); if (sym.Namespace != null) { throw new ParseException("Can't bind qualified name: " + sym); } IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref(), Compiler.InCatchFinallyVar, true); try { Var.pushThreadBindings(dynamicBindings); LocalBinding lb = Compiler.RegisterLocal(sym, (Symbol)(RT.second(f) is Symbol ? RT.second(f) : null), null, false); Expr handler = (new BodyExpr.Parser()).Parse(recursePcon, RT.next(RT.next(RT.next(f)))); catches = catches.cons(new CatchClause(t, lb, handler));; } finally { Var.popThreadBindings(); } caught = true; } else // finally { if (fs.next() != null) { throw new InvalidOperationException("finally clause must be last in try expression"); } try { //Var.pushThreadBindings(RT.map(Compiler.IN_CATCH_FINALLY, RT.T)); Var.pushThreadBindings(RT.map(Compiler.InCatchFinallyVar, true)); finallyExpr = (new BodyExpr.Parser()).Parse(pcon.SetRhc(RHC.Statement).SetAssign(false), RT.next(f)); } finally { Var.popThreadBindings(); } } } } if (bodyExpr == null) { try { Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, true)); bodyExpr = (new BodyExpr.Parser()).Parse(recursePcon, RT.seq(body)); } finally { Var.popThreadBindings(); } } return(new TryExpr(bodyExpr, catches, finallyExpr, retLocal, finallyLocal)); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LoopSym); if (!(RT.second(form) is IPersistentVector bindings)) { throw new ParseException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ParseException("Bad binding form, expected matched symbol/value pairs."); } ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID())); } ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = PersistentVector.EMPTY; for (int i = 0; i < bindings.count() / 2; i++) { recurMismatches = recurMismatches.cons(false); } // may repeat once for each binding with a mismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); method.SetLocals(backupMethodLocals, backupMethodIndexLocals); if (isLoop) { dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null); } try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) { throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new ParseException("Can't let qualified name: " + sym); } Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); if (isLoop) { if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2))) { HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); List <HostArg> has = new List <HostArg>(1) { ha }; init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false); if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) { RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); } } else if (Compiler.MaybePrimitiveType(init) == typeof(int)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false); } else if (Compiler.MaybePrimitiveType(init) == typeof(float)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false); } } // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, typeof(Object), false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) { loopLocals = loopLocals.cons(b); } } if (isLoop) { Compiler.LoopLocalsVar.set(loopLocals); } Expr bodyExpr; bool moreMismatches = false; try { if (isLoop) { object methodReturnContext = pcon.Rhc == RHC.Return ? Compiler.MethodReturnContextVar.deref() : null; // stuff with clear paths, Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null, Compiler.MethodReturnContextVar, methodReturnContext)); } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { Var.popThreadBindings(); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMismatch) { recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true); moreMismatches = true; } } } } if (!moreMismatches) { return(new LetExpr(bindingInits, bodyExpr, isLoop)); } } finally { Var.popThreadBindings(); } } }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (pcon.Rhc != RHC.Return) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "try__" + RT.nextID()); // (try try-expr* catch-expr* finally-expr?) // catch-expr: (catch class sym expr*) // finally-expr: (finally expr*) IPersistentVector body = PersistentVector.EMPTY; IPersistentVector catches = PersistentVector.EMPTY; Expr bodyExpr = null; Expr finallyExpr = null; bool caught = false; ParserContext recursePcon = new ParserContext(RHC.Expression,false); int retLocal = Compiler.GetAndIncLocalNum(); int finallyLocal = Compiler.GetAndIncLocalNum(); for (ISeq fs = form.next(); fs != null; fs = fs.next()) { object f = fs.first(); ISeq fSeq = f as ISeq; object op = fSeq != null ? fSeq.first() : null; if (!Util.equals(op, Compiler.CatchSym) && !Util.equals(op, Compiler.FinallySym)) { if (caught) throw new ParseException("Only catch or finally clause can follow catch in try expression"); body = body.cons(f); } else { if (bodyExpr == null) { try { Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, true, Compiler.InTryBlockVar, true)); bodyExpr = new BodyExpr.Parser().Parse(pcon, RT.seq(body)); } finally { Var.popThreadBindings(); } } if (Util.equals(op, Compiler.CatchSym)) { Type t = HostExpr.MaybeType(RT.second(f), false); if (t == null) throw new ParseException("Unable to resolve classname: " + RT.second(f)); if (!(RT.third(f) is Symbol)) throw new ParseException("Bad binding form, expected symbol, got: " + RT.third(f)); Symbol sym = (Symbol)RT.third(f); if (sym.Namespace != null) throw new ParseException("Can't bind qualified name: " + sym); IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref(), Compiler.InCatchFinallyVar, true); try { Var.pushThreadBindings(dynamicBindings); LocalBinding lb = Compiler.RegisterLocal(sym, (Symbol)(RT.second(f) is Symbol ? RT.second(f) : null), null, typeof(Object), false); Expr handler = (new BodyExpr.Parser()).Parse(recursePcon, RT.next(RT.next(RT.next(f)))); catches = catches.cons(new CatchClause(t, lb, handler)); ; } finally { Var.popThreadBindings(); } caught = true; } else // finally { if (fs.next() != null) throw new InvalidOperationException("finally clause must be last in try expression"); try { //Var.pushThreadBindings(RT.map(Compiler.IN_CATCH_FINALLY, RT.T)); Var.pushThreadBindings(RT.map(Compiler.InCatchFinallyVar, true)); finallyExpr = (new BodyExpr.Parser()).Parse(pcon.SetRhc(RHC.Statement).SetAssign(false), RT.next(f)); } finally { Var.popThreadBindings(); } } } } if (bodyExpr == null) { // this codepath is hit when there is neither catch nor finally, e.g., (try (expr)) // return a body expr directly try { Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, true)); bodyExpr = (new BodyExpr.Parser()).Parse(recursePcon, RT.seq(body)); } finally { Var.popThreadBindings(); } return bodyExpr; } return new TryExpr(bodyExpr, catches, finallyExpr, retLocal, finallyLocal); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LOOP); IPersistentVector bindings = RT.second(form) as IPersistentVector; if (bindings == null) throw new ArgumentException("Bad binding form, expected vector"); if ((bindings.count() % 2) != 0) throw new ArgumentException("Bad binding form, expected matched symbol/value pairs."); ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)),"let__"+RT.nextID()); ObjMethod method = (ObjMethod)Compiler.METHOD.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = null; // we might repeat once if a loop with a recurMismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.NEXT_LOCAL_NUM, Compiler.NEXT_LOCAL_NUM.deref()); if (isLoop) dynamicBindings = dynamicBindings.assoc(Compiler.LOOP_LOCALS, null); try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) throw new ArgumentException("Bad binding form, expected symbol, got " + bindings.nth(i)); Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) throw new Exception("Can't let qualified name: " + sym); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); //if (isLoop) //{ // if (recurMismatches != null && ((LocalBinding)recurMismatches.nth(i / 2)).RecurMistmatch) // { // HostArg ha = new HostArg(HostArg.ParameterType.Standard,init,null); // List<HostArg> has = new List<HostArg>(1); // has.Add(ha); // init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", has); // if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) // RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); // } // else if (Compiler.MaybePrimitiveType(init) == typeof(int)) // { // HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); // List<HostArg> has = new List<HostArg>(1); // has.Add(ha); // init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "longCast", has); // } // else if (Compiler.MaybePrimitiveType(init) == typeof(float)) // { // HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); // List<HostArg> has = new List<HostArg>(1); // has.Add(ha); // init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "doubleCast", has); // } //} // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) loopLocals = loopLocals.cons(b); } if (isLoop) Compiler.LOOP_LOCALS.set(loopLocals); Expr bodyExpr; try { if (isLoop) { // stuff with clear paths } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { // stuff with clear paths recurMismatches = null; for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMistmatch) recurMismatches = loopLocals; } } } if (recurMismatches == null) return new LetExpr(bindingInits, bodyExpr, isLoop); } finally { Var.popThreadBindings(); } } }