public Expr Parse(ParserContext pcon, object frms) { ISeq forms = (ISeq)frms; if (Util.equals(RT.first(forms), Compiler.DoSym)) { forms = RT.next(forms); } IPersistentVector exprs = PersistentVector.EMPTY; for (; forms != null; forms = forms.next()) { Expr e = (pcon.Rhc != RHC.Eval && (pcon.Rhc == RHC.Statement || forms.next() != null)) ? Compiler.Analyze(pcon.SetRhc(RHC.Statement), forms.first()) : Compiler.Analyze(pcon, forms.first()); exprs = exprs.cons(e); } if (exprs.count() == 0) { exprs = exprs.cons(Compiler.NilExprInstance); } return(new BodyExpr(exprs)); }
public Expr Parse(ParserContext pcon, object form) { if (pcon.Rhc == RHC.Eval) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)), "throw__" + RT.nextID()); return new ThrowExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), RT.second(form))); }
public Expr Parse(ParserContext pcon, object form) { if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnSym, PersistentVector.EMPTY, form)), "throw__" + RT.nextID())); } return(new ThrowExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), RT.second(form)))); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (RT.Length(form) != 3) throw new ParseException("Malformed assignment, expecting (set! target val)"); Expr target = Compiler.Analyze(new ParserContext(RHC.Expression, true), RT.second(form)); AssignableExpr ae = target as AssignableExpr; if (ae == null) throw new ParseException("Invalid assignment target"); return new AssignExpr(ae, Compiler.Analyze(pcon.SetRhc(RHC.Expression),RT.third(form))); }
public Expr Parse(ParserContext pcon, object form) { if (pcon.Rhc == RHC.Eval) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "throw__" + RT.nextID()); if (RT.Length((ISeq)form) == 1) return new ThrowExpr(); if (RT.count(form) > 2) throw new InvalidOperationException("Too many arguments to throw, throw expects a single Exception instance"); return new ThrowExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), RT.second(form))); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (RT.Length(form) != 3) { throw new ParseException("Malformed assignment, expecting (set! target val)"); } Expr target = Compiler.Analyze(new ParserContext(RHC.Expression, true), RT.second(form)); if (!(target is AssignableExpr ae)) { throw new ParseException("Invalid assignment target"); } return(new AssignExpr(ae, Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.third(form)))); }
public Expr Parse(ParserContext pcon, object form) { if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "throw__" + RT.nextID())); } if (RT.Length((ISeq)form) == 1) { return(new ThrowExpr()); } if (RT.count(form) > 2) { throw new InvalidOperationException("Too many arguments to throw, throw expects a single Exception instance"); } return(new ThrowExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), RT.second(form)))); }
public Expr Parse(ParserContext pcon, object frms) { ISeq forms = (ISeq)frms; if (Util.equals(RT.first(forms), Compiler.DoSym)) forms = RT.next(forms); IPersistentVector exprs = PersistentVector.EMPTY; for (; forms != null; forms = forms.next()) { Expr e = (pcon.Rhc != RHC.Eval && (pcon.Rhc == RHC.Statement || forms.next() != null)) ? Compiler.Analyze(pcon.SetRhc(RHC.Statement), forms.first()) : Compiler.Analyze(pcon, forms.first()); exprs = exprs.cons(e); } if (exprs.count() == 0) exprs = exprs.cons(Compiler.NilExprInstance); return new BodyExpr(exprs); }
public static Expr Parse(ParserContext pcon, ISeq form) { pcon = pcon.EvalOrExpr(); Expr fexpr = Compiler.Analyze(pcon, form.first()); VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar) && RT.count(form) == 3) { Expr sexpr = Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form)); ConstantExpr csexpr = sexpr as ConstantExpr; if (csexpr != null) { Type tval = csexpr.Val as Type; if (tval != null) { return(new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), tval, Compiler.Analyze(pcon, RT.third(form)))); } } } if (varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); for (ISeq s = RT.seq(arglists); s != null; s = s.next()) { IPersistentVector sargs = (IPersistentVector)s.first(); if (sargs.count() == arity) { string primc = FnMethod.PrimInterface(sargs); if (primc != null) { return(Compiler.Analyze(pcon, RT.listStar(Symbol.intern(".invokePrim"), ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))), form.next()))); } break; } } } KeywordExpr kwFexpr = fexpr as KeywordExpr; if (kwFexpr != null && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound) { Expr target = Compiler.Analyze(pcon, RT.second(form)); return(new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target)); } IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(Compiler.Analyze(pcon, s.first())); } //if (args.count() > Compiler.MAX_POSITIONAL_ARITY) // throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY)); return(new InvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form), Compiler.TagOf(form), fexpr, args)); }
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(); } } }
//(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?) //prepared by case macro and presumed correct //case macro binds actual expr in let so expr is always a local, //no need to worry about multiple evaluation public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq) frm; if (pcon.Rhc == RHC.Eval) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnSym, PersistentVector.EMPTY, form)),"case__"+RT.nextID()); PersistentVector args = PersistentVector.create(form.next()); object exprForm = args.nth(0); int shift = Util.ConvertToInt(args.nth(1)); int mask = Util.ConvertToInt(args.nth(2)); object defaultForm = args.nth(3); IPersistentMap caseMap = (IPersistentMap)args.nth(4); Keyword switchType = (Keyword)args.nth(5); Keyword testType = (Keyword)args.nth(6); IPersistentSet skipCheck = RT.count(args) < 8 ? null : (IPersistentSet)args.nth(7); ISeq keys = RT.keys(caseMap); int low = Util.ConvertToInt(RT.first(keys)); int high = Util.ConvertToInt(RT.nth(keys,RT.count(keys)-1)); LocalBindingExpr testexpr = (LocalBindingExpr)Compiler.Analyze(pcon.SetRhc(RHC.Expression),exprForm); SortedDictionary<int,Expr> tests = new SortedDictionary<int,Expr>(); Dictionary<int,Expr> thens = new Dictionary<int,Expr>(); //testexpr.shouldClear = false; //PathNode branch = new PathNode(PATHTYPE.BRANCH, (PathNode) CLEAR_PATH.get()); foreach ( IMapEntry me in caseMap ) { int minhash = Util.ConvertToInt(me.key()); object pair = me.val(); // [test-val then-expr] object first = RT.first(pair); Expr testExpr = testType == _intKey ? NumberExpr.Parse(Util.ConvertToInt(first)) : (first == null ? Compiler.NilExprInstance : new ConstantExpr(first)); tests[minhash] = testExpr; Expr thenExpr; //try //{ // Var.pushThreadBindings( // RT.map(CLEAR_PATH, new PathNode(PATHTYPE.PATH,branch))); thenExpr = Compiler.Analyze(pcon,RT.second(pair)); //} //finally //{ // Var.popThreadBindings(); //} thens[minhash] = thenExpr; } Expr defaultExpr; //try //{ // Var.pushThreadBindings( // RT.map(CLEAR_PATH, new PathNode(PATHTYPE.PATH,branch))); defaultExpr = Compiler.Analyze(pcon,defaultForm); //} //finally //{ // Var.popThreadBindings(); //} return new CaseExpr( (IPersistentMap) Compiler.SourceSpanVar.deref(), testexpr, shift, mask, low, high, defaultExpr, tests, thens, switchType, testType, skipCheck); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (letfn* [var1 (fn [args] body) ... ] body ... ) 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/expression pairs."); } ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "letfn__" + RT.nextID())); } IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); try { Var.pushThreadBindings(dynamicBindings); // pre-seed env (like Lisp labels) IPersistentVector lbs = 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); } LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), null, typeof(Object), false); // b.CanBeCleared = false; lbs = lbs.cons(b); } IPersistentVector bindingInits = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { Symbol sym = (Symbol)bindings.nth(i); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression), bindings.nth(i + 1), sym.Name); LocalBinding b = (LocalBinding)lbs.nth(i / 2); b.Init = init; BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); } return(new LetFnExpr(bindingInits, new BodyExpr.Parser().Parse(pcon, body))); } finally { Var.popThreadBindings(); } }
//(case* expr shift mask low high default map<minhash, [test then]> identity?) //prepared by case macro and presumed correct //case macro binds actual expr in let so expr is always a local, //no need to worry about multiple evaluation public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq) frm; if (pcon.Rhc == RHC.Eval) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form)),"case__"+RT.nextID()); PersistentVector args = PersistentVector.create(form.next()); Dictionary<int,Expr> tests = new Dictionary<int,Expr>(); Dictionary<int,Expr> thens = new Dictionary<int,Expr>(); LocalBindingExpr testexpr = (LocalBindingExpr)Compiler.Analyze(pcon.SetRhc(RHC.Expression),args.nth(0)); //testexpr.shouldClear = false; //PathNode branch = new PathNode(PATHTYPE.BRANCH, (PathNode) CLEAR_PATH.get()); foreach ( IMapEntry e in ((IPersistentMap)args.nth(6)) ) { int minhash = (int)e.key(); IMapEntry me = (IMapEntry)e.val(); Expr testExpr = new ConstantExpr(me.key()); tests[minhash] = testExpr; Expr thenExpr; //try //{ // Var.pushThreadBindings( // RT.map(CLEAR_PATH, new PathNode(PATHTYPE.PATH,branch))); thenExpr = Compiler.Analyze(pcon,me.val()); //} //finally //{ // Var.popThreadBindings(); //} thens[minhash] = thenExpr; } Expr defaultExpr; //try //{ // Var.pushThreadBindings( // RT.map(CLEAR_PATH, new PathNode(PATHTYPE.PATH,branch))); defaultExpr = Compiler.Analyze(pcon,args.nth(5)); //} //finally //{ // Var.popThreadBindings(); //} return new CaseExpr( (IPersistentMap) Compiler.SOURCE_SPAN.deref(), testexpr, (int)args.nth(1), (int)args.nth(2), (int)args.nth(3), (int)args.nth(4), defaultExpr, tests, thens, RT.booleanCast(args.nth(7))); }
public Expr Parse(ParserContext pcon, object form) { return(new MonitorEnterExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form)))); }
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) { string source = (string)Compiler.SourceVar.deref(); IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // Compiler.GetSourceSpanMap(form); ISeq form = (ISeq)frm; IPersistentVector loopLocals = (IPersistentVector)Compiler.LoopLocalsVar.deref(); if (pcon.Rhc != RHC.Return || loopLocals == null) { throw new ParseException("Can only recur from tail position"); } if (Compiler.NoRecurVar.deref() != null) { throw new ParseException("Cannot recur across try"); } IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), s.first())); } if (args.count() != loopLocals.count()) { throw new ParseException(string.Format("Mismatched argument count to recur, expected: {0} args, got {1}", loopLocals.count(), args.count())); } for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { bool mismatch = false; Type pt = Compiler.MaybePrimitiveType((Expr)args.nth(i)); if (primt == typeof(long)) { if (!(pt == typeof(long) || pt == typeof(int) || pt == typeof(short) || pt == typeof(uint) || pt == typeof(ushort) || pt == typeof(ulong) || pt == typeof(char) || pt == typeof(byte) || pt == typeof(sbyte))) { mismatch = true; } } else if (primt == typeof(double)) { if (!(pt == typeof(double) || pt == typeof(float))) { mismatch = true; } } if (mismatch) { lb.RecurMismatch = true; if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) { RT.errPrintWriter().WriteLine("{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", source, spanMap != null ? (int)spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, pt != null ? pt.Name : "Object", primt.Name); } } } } return(new RecurExpr(source, spanMap, loopLocals, args)); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; IPersistentVector loopLocals = (IPersistentVector)Compiler.LOOP_LOCALS.deref(); if ( pcon.Rhc != RHC.Return || loopLocals == null) throw new InvalidOperationException("Can only recur from tail position"); if (Compiler.IN_CATCH_FINALLY.deref() != null) throw new InvalidOperationException("Cannot recur from catch/finally."); IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) args = args.cons(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false),s.first())); if (args.count() != loopLocals.count()) throw new ArgumentException(string.Format("Mismatched argument count to recur, expected: {0} args, got {1}", loopLocals.count(), args.count())); //for (int i = 0; i < loopLocals.count(); i++) //{ // LocalBinding lb = (LocalBinding)loopLocals.nth(i); // Type primt = lb.PrimitiveType; // if (primt != null) // { // bool mismatch = false; // Type pt = Compiler.MaybePrimitiveType((Expr)args.nth(i)); // if (pt == typeof(long)) // { // if (!(pt == typeof(long) || pt == typeof(int) || pt == typeof(short) || pt == typeof(uint) || pt == typeof(ushort) || pt == typeof(ulong) // || pt == typeof(char) || pt == typeof(byte) || pt == typeof(sbyte))) // mismatch = true; // } // else if (pt == typeof(double)) // { // if (!(pt == typeof(double) || pt == typeof(float))) // mismatch = true; // } // if (mismatch) // { // lb.RecurMistmatch = true; // if (RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) // RT.errPrintWriter().WriteLine("{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", // "Source", "Line", lb.Name, pt != null ? pt.Name : "Object", primt.Name); // } // } //} return new RecurExpr(loopLocals, args); }
public Expr Parse(ParserContext pcon, object form) { return new MonitorEnterExpr(Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form))); }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (letfn* [var1 (fn [args] body) ... ] body ... ) 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/expression pairs."); ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval) return Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "letfn__" + RT.nextID()); IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); try { Var.pushThreadBindings(dynamicBindings); // pre-seed env (like Lisp labels) IPersistentVector lbs = 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); LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), null, typeof(Object), false); // b.CanBeCleared = false; lbs = lbs.cons(b); } IPersistentVector bindingInits = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { Symbol sym = (Symbol)bindings.nth(i); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression),bindings.nth(i + 1),sym.Name); LocalBinding b = (LocalBinding)lbs.nth(i / 2); b.Init = init; BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); } return new LetFnExpr(bindingInits,new BodyExpr.Parser().Parse(pcon, body)); } finally { Var.popThreadBindings(); } }
public static Expr Parse(ParserContext pcon, ISeq form) { bool tailPosition = Compiler.InTailCall(pcon.Rhc); pcon = pcon.EvalOrExpr(); Expr fexpr = Compiler.Analyze(pcon, form.first()); VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar) && RT.count(form) == 3) { Expr sexpr = Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form)); if (sexpr is ConstantExpr csexpr) { Type tval = csexpr.Val as Type; if (tval != null) { return(new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), tval, Compiler.Analyze(pcon, RT.third(form)))); } } } if (RT.booleanCast(Compiler.GetCompilerOption(Compiler.DirectLinkingKeyword)) && varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; if (!v.isDynamic() && !RT.booleanCast(RT.get(v.meta(), Compiler.RedefKeyword, false)) && !RT.booleanCast(RT.get(v.meta(), RT.DeclaredKey, false))) { Symbol formTag = Compiler.TagOf(form); //object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); object sigtag = SigTag(arity, v); object vtag = RT.get(RT.meta(v), RT.TagKey); if (StaticInvokeExpr.Parse(v, RT.next(form), formTag ?? sigtag ?? vtag) is StaticInvokeExpr ret && !((Compiler.IsCompiling || Compiler.IsCompilingDefType) && GenContext.IsInternalAssembly(ret.Method.DeclaringType.Assembly))) { //Console.WriteLine("invoke direct: {0}", v); return(ret); } //Console.WriteLine("NOT direct: {0}", v); } } if (varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); for (ISeq s = RT.seq(arglists); s != null; s = s.next()) { IPersistentVector sargs = (IPersistentVector)s.first(); if (sargs.count() == arity) { string primc = FnMethod.PrimInterface(sargs); if (primc != null) { return(Compiler.Analyze(pcon, ((IObj)RT.listStar(Symbol.intern(".invokePrim"), ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))), form.next())).withMeta((IPersistentMap)RT.conj(RT.meta(v), RT.meta(form))))); } break; } } } if (fexpr is KeywordExpr kwFexpr && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound) { Expr target = Compiler.Analyze(pcon, RT.second(form)); return(new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target)); } IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(Compiler.Analyze(pcon, s.first())); } //if (args.count() > Compiler.MAX_POSITIONAL_ARITY) // throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY)); return(new InvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form), Compiler.TagOf(form), fexpr, args, tailPosition)); }
public static Expr Parse(ParserContext pcon, ISeq form) { pcon = pcon.EvalOrExpr(); Expr fexpr = Compiler.Analyze(pcon,form.first()); VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar) && RT.count(form) == 3) { Expr sexpr = Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form)); ConstantExpr csexpr = sexpr as ConstantExpr; if (csexpr != null) { Type tval = csexpr.Val as Type; if (tval != null) return new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), tval, Compiler.Analyze(pcon, RT.third(form))); } } if (varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); for (ISeq s = RT.seq(arglists); s != null; s = s.next()) { IPersistentVector sargs = (IPersistentVector)s.first(); if (sargs.count() == arity) { string primc = FnMethod.PrimInterface(sargs); if (primc != null) return Compiler.Analyze(pcon, RT.listStar(Symbol.intern(".invokePrim"), ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))), form.next())); break; } } } KeywordExpr kwFexpr = fexpr as KeywordExpr; if (kwFexpr != null && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound) { Expr target = Compiler.Analyze(pcon, RT.second(form)); return new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target); } IPersistentVector args = PersistentVector.EMPTY; for ( ISeq s = RT.seq(form.next()); s != null; s = s.next()) args = args.cons(Compiler.Analyze(pcon,s.first())); //if (args.count() > Compiler.MAX_POSITIONAL_ARITY) // throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY)); return new InvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form), Compiler.TagOf(form), fexpr, args); }
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; 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); 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(); } } }
//(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?) //prepared by case macro and presumed correct //case macro binds actual expr in let so expr is always a local, //no need to worry about multiple evaluation public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "case__" + RT.nextID())); } IPersistentVector args = LazilyPersistentVector.create(form.next()); object exprForm = args.nth(0); int shift = Util.ConvertToInt(args.nth(1)); int mask = Util.ConvertToInt(args.nth(2)); object defaultForm = args.nth(3); IPersistentMap caseMap = (IPersistentMap)args.nth(4); Keyword switchType = (Keyword)args.nth(5); Keyword testType = (Keyword)args.nth(6); IPersistentSet skipCheck = RT.count(args) < 8 ? null : (IPersistentSet)args.nth(7); ISeq keys = RT.keys(caseMap); int low = Util.ConvertToInt(RT.first(keys)); int high = Util.ConvertToInt(RT.nth(keys, RT.count(keys) - 1)); LocalBindingExpr testexpr = (LocalBindingExpr)Compiler.Analyze(pcon.SetRhc(RHC.Expression), exprForm); SortedDictionary <int, Expr> tests = new SortedDictionary <int, Expr>(); Dictionary <int, Expr> thens = new Dictionary <int, Expr>(); foreach (IMapEntry me in caseMap) { int minhash = Util.ConvertToInt(me.key()); object pair = me.val(); // [test-val then-expr] object first = RT.first(pair); Expr testExpr = testType == _intKey ? NumberExpr.Parse(Util.ConvertToInt(first)) : (first == null ? Compiler.NilExprInstance : new ConstantExpr(first)); tests[minhash] = testExpr; Expr thenExpr; thenExpr = Compiler.Analyze(pcon, RT.second(pair)); thens[minhash] = thenExpr; } Expr defaultExpr; defaultExpr = Compiler.Analyze(pcon, defaultForm); return(new CaseExpr( (IPersistentMap)Compiler.SourceSpanVar.deref(), testexpr, shift, mask, low, high, defaultExpr, tests, thens, switchType, testType, skipCheck)); }
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) { string source = (string)Compiler.SourceVar.deref(); IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // Compiler.GetSourceSpanMap(form); ISeq form = (ISeq)frm; IPersistentVector loopLocals = (IPersistentVector)Compiler.LoopLocalsVar.deref(); if (pcon.Rhc != RHC.Return || loopLocals == null) throw new ParseException("Can only recur from tail position"); if (Compiler.InCatchFinallyVar.deref() != null) throw new ParseException("Cannot recur from catch/finally."); if (Compiler.NoRecurVar.deref() != null) throw new ParseException("Cannot recur across try"); IPersistentVector args = PersistentVector.EMPTY; for (ISeq s = RT.seq(form.next()); s != null; s = s.next()) args = args.cons(Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), s.first())); if (args.count() != loopLocals.count()) throw new ParseException(string.Format("Mismatched argument count to recur, expected: {0} args, got {1}", loopLocals.count(), args.count())); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { bool mismatch = false; Type pt = Compiler.MaybePrimitiveType((Expr)args.nth(i)); if (primt == typeof(long)) { if (!(pt == typeof(long) || pt == typeof(int) || pt == typeof(short) || pt == typeof(uint) || pt == typeof(ushort) || pt == typeof(ulong) || pt == typeof(char) || pt == typeof(byte) || pt == typeof(sbyte))) mismatch = true; } else if (primt == typeof(double)) { if (!(pt == typeof(double) || pt == typeof(float))) mismatch = true; } if (mismatch) { lb.RecurMismatch = true; if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) RT.errPrintWriter().WriteLine("{0}:{1} recur arg for primitive local: {2} is not matching primitive, had: {3}, needed {4}", source, spanMap != null ? (int)spanMap.valAt(RT.StartLineKey, 0) : 0, lb.Name, pt != null ? pt.Name : "Object", primt.Name); } } } return new RecurExpr(source, spanMap, loopLocals, args); }
public static Expr Parse(ParserContext pcon, ISeq form) { bool tailPosition = Compiler.InTailCall(pcon.Rhc); pcon = pcon.EvalOrExpr(); Expr fexpr = Compiler.Analyze(pcon,form.first()); VarExpr varFexpr = fexpr as VarExpr; if (varFexpr != null && varFexpr.Var.Equals(Compiler.InstanceVar) && RT.count(form) == 3) { Expr sexpr = Compiler.Analyze(pcon.SetRhc(RHC.Expression), RT.second(form)); ConstantExpr csexpr = sexpr as ConstantExpr; if (csexpr != null) { Type tval = csexpr.Val as Type; if (tval != null) return new InstanceOfExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), tval, Compiler.Analyze(pcon, RT.third(form))); } } if ( RT.booleanCast(Compiler.GetCompilerOption(Compiler.DirectLinkingKeyword)) && varFexpr != null && pcon.Rhc != RHC.Eval ) { Var v = varFexpr.Var; if ( ! v.isDynamic() && !RT.booleanCast(RT.get(v.meta(), Compiler.RedefKeyword, false)) && !RT.booleanCast(RT.get(v.meta(), RT.DeclaredKey, false)) ) { Symbol formTag = Compiler.TagOf(form); object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); object sigtag = SigTag(arity, v); object vtag = RT.get(RT.meta(v), RT.TagKey); StaticInvokeExpr ret = StaticInvokeExpr.Parse(v, RT.next(form), formTag ?? sigtag ?? vtag) as StaticInvokeExpr; if (ret != null && !((Compiler.IsCompiling || Compiler.IsCompilingDefType) && GenContext.IsInternalAssembly(ret.Method.DeclaringType.Assembly))) { //Console.WriteLine("invoke direct: {0}", v); return ret; } //Console.WriteLine("NOT direct: {0}", v); } } if (varFexpr != null && pcon.Rhc != RHC.Eval) { Var v = varFexpr.Var; object arglists = RT.get(RT.meta(v), Compiler.ArglistsKeyword); int arity = RT.count(form.next()); for (ISeq s = RT.seq(arglists); s != null; s = s.next()) { IPersistentVector sargs = (IPersistentVector)s.first(); if (sargs.count() == arity) { string primc = FnMethod.PrimInterface(sargs); if (primc != null) return Compiler.Analyze(pcon, ((IObj)RT.listStar(Symbol.intern(".invokePrim"), ((Symbol)form.first()).withMeta(RT.map(RT.TagKey, Symbol.intern(primc))), form.next())).withMeta((IPersistentMap)RT.conj(RT.meta(v), RT.meta(form)))); break; } } } KeywordExpr kwFexpr = fexpr as KeywordExpr; if (kwFexpr != null && RT.count(form) == 2 && Compiler.KeywordCallsitesVar.isBound) { Expr target = Compiler.Analyze(pcon, RT.second(form)); return new KeywordInvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), Compiler.TagOf(form), kwFexpr, target); } IPersistentVector args = PersistentVector.EMPTY; for ( ISeq s = RT.seq(form.next()); s != null; s = s.next()) args = args.cons(Compiler.Analyze(pcon,s.first())); //if (args.count() > Compiler.MAX_POSITIONAL_ARITY) // throw new ArgumentException(String.Format("No more than {0} args supported", Compiler.MAX_POSITIONAL_ARITY)); return new InvokeExpr((string)Compiler.SourceVar.deref(), (IPersistentMap)Compiler.SourceSpanVar.deref(), //Compiler.GetSourceSpanMap(form), Compiler.TagOf(form), fexpr, args, tailPosition); }