public Expr Parse(ParserContext pcon, object form) { int argCount = RT.count(form) - 1; if (argCount != 1) { IPersistentMap exData = new PersistentArrayMap(new Object[] { FormKey, form }); throw new ExceptionInfo("Wrong number of args (" + argCount + ") passed to quote", exData); } object v = RT.second(form); if (v == null) return Compiler.NilExprInstance; else if (v is Boolean) { if ((bool)v) return Compiler.TrueExprInstance; else return Compiler.FalseExprInstance; } else if (Util.IsNumeric(v)) return NumberExpr.Parse(v); else if (v is string) return new StringExpr((String)v); else if (v is IPersistentCollection && ((IPersistentCollection)v).count() == 0) return new EmptyExpr(v); else return new ConstantExpr(v); }
public Expr Parse(ParserContext pcon, object frm) { // frm is: (deftype* tagname classname [fields] :implements [interfaces] :tag tagname methods*) ISeq rform = (ISeq)frm; rform = RT.next(rform); string tagname = ((Symbol)rform.first()).getName(); rform = rform.next(); Symbol classname = (Symbol)rform.first(); rform = rform.next(); IPersistentVector fields = (IPersistentVector)rform.first(); rform = rform.next(); IPersistentMap opts = PersistentHashMap.EMPTY; while (rform != null && rform.first() is Keyword) { opts = opts.assoc(rform.first(), RT.second(rform)); rform = rform.next().next(); } ObjExpr ret = Build((IPersistentVector)RT.get(opts, Compiler.ImplementsKeyword, PersistentVector.EMPTY), fields, null, tagname, classname, (Symbol)RT.get(opts, RT.TagKey), rform, frm,opts); return ret; }
public static Expr Parse(ParserContext pcon, IPersistentMap form) { ParserContext pconToUse = pcon.EvEx(); bool constant = true; IPersistentVector keyvals = PersistentVector.EMPTY; for (ISeq s = RT.seq(form); s != null; s = s.next()) { IMapEntry e = (IMapEntry)s.first(); Expr k = Compiler.Analyze(pconToUse, e.key()); Expr v = Compiler.Analyze(pconToUse, e.val()); keyvals = (IPersistentVector)keyvals.cons(k); keyvals = (IPersistentVector)keyvals.cons(v); if (!(k is LiteralExpr && v is LiteralExpr)) constant = false; } Expr ret = new MapExpr(keyvals); if (form is IObj && ((IObj)form).meta() != null) return Compiler.OptionallyGenerateMetaInit(pcon, form, ret); else if (constant) { // This 'optimzation' works, mostly, unless you have nested map values. // The nested map values do not participate in the constants map, so you end up with the code to create the keys. // Result: huge duplication of keyword creation. 3X increase in init time to the REPL. //IPersistentMap m = PersistentHashMap.EMPTY; //for (int i = 0; i < keyvals.length(); i += 2) // m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val); //return new ConstantExpr(m); return ret; } else return ret; }
public Expr Parse(ParserContext pcon, object frm) { // frm is: (reify this-name? [interfaces] (method-name [args] body)* ) ISeq form = (ISeq)frm; ObjMethod enclosingMethod = (ObjMethod)Compiler.MethodVar.deref(); string baseName = enclosingMethod != null ? (ObjExpr.TrimGenId(enclosingMethod.Objx.Name) + "$") : (Compiler.munge(Compiler.CurrentNamespace.Name.Name) + "$"); string simpleName = "reify__" + RT.nextID(); string className = baseName + simpleName; ISeq rform = RT.next(form); IPersistentVector interfaces = ((IPersistentVector)RT.first(rform)).cons(Symbol.intern("clojure.lang.IObj")); rform = RT.next(rform); ObjExpr ret = Build(interfaces, null, null, className, Symbol.intern(className), null, rform,frm, null); IObj iobj = frm as IObj; if (iobj != null && iobj.meta() != null) return new MetaExpr(ret, MapExpr.Parse(pcon.EvalOrExpr(),iobj.meta())); else return ret; }
public static Expr Parse(ParserContext pcon, IPersistentVector form) { ParserContext pconToUse = pcon.EvEx(); bool constant = true; IPersistentVector args = PersistentVector.EMPTY; for (int i = 0; i < form.count(); i++ ) { Expr v = Compiler.Analyze(pconToUse, form.nth(i)); args = (IPersistentVector)args.cons(v); if ( !(v is LiteralExpr) ) constant = false; } Expr ret = new VectorExpr(args); if ( form is IObj && ((IObj)form).meta() != null ) return Compiler.OptionallyGenerateMetaInit(pcon,form, ret); else if ( constant ) { IPersistentVector rv = PersistentVector.EMPTY; for ( int i=0; i<args.count(); i++ ) { LiteralExpr ve = (LiteralExpr)args.nth(i); rv = (IPersistentVector)rv.cons(ve.Val); } return new ConstantExpr(rv); } else return ret; }
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 static Expr Parse(ParserContext pcon, IPersistentMap form) { ParserContext pconToUse = pcon.EvEx(); bool constant = true; IPersistentVector keyvals = PersistentVector.EMPTY; for (ISeq s = RT.seq(form); s != null; s = s.next()) { IMapEntry e = (IMapEntry)s.first(); Expr k = Compiler.Analyze(pconToUse, e.key()); Expr v = Compiler.Analyze(pconToUse, e.val()); keyvals = (IPersistentVector)keyvals.cons(k); keyvals = (IPersistentVector)keyvals.cons(v); if (!(k is LiteralExpr && v is LiteralExpr)) constant = false; } Expr ret = new MapExpr(keyvals); if (form is IObj && ((IObj)form).meta() != null) return Compiler.OptionallyGenerateMetaInit(pcon, form, ret); else if (constant) { IPersistentMap m = PersistentHashMap.EMPTY; for (int i = 0; i < keyvals.length(); i += 2) m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val); return new ConstantExpr(m); } else return ret; }
public static Expr Parse(ParserContext pcon, IPersistentSet form) { ParserContext pconToUse = pcon.EvEx(); bool constant = true; IPersistentVector keys = PersistentVector.EMPTY; for (ISeq s = RT.seq(form); s != null; s = s.next()) { object e = s.first(); Expr expr = Compiler.Analyze(pconToUse, e); keys = (IPersistentVector)keys.cons(expr); if (!(expr is LiteralExpr)) constant = false; } Expr ret = new SetExpr(keys); if (form is IObj && ((IObj)form).meta() != null) return Compiler.OptionallyGenerateMetaInit(pcon, form, ret); else if (constant) { IPersistentSet set = PersistentHashSet.EMPTY; for (int i = 0; i < keys.count(); i++) { LiteralExpr ve = (LiteralExpr)keys.nth(i); set = (IPersistentSet)set.cons(ve.Val); } return new ConstantExpr(set); } else return ret; }
public Expr Parse(ParserContext pcon, object form) { Symbol sym = (Symbol)RT.second(form); Var v = Compiler.LookupVar(sym, false); if (v != null) return new TheVarExpr(v); throw new ParseException(string.Format("Unable to resolve var: {0} in this context", sym)); }
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; if (RT.Length(form) != 3) throw new ArgumentException("Malformed assignment, expecting (set! target val)"); Expr target = Compiler.Analyze(new ParserContext(RHC.Expression, true), RT.second(form)); if (!(target is AssignableExpr)) throw new ArgumentException("Invalid assignment target"); return new AssignExpr((AssignableExpr)target, 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 test then) or (if test then else) if (form.count() > 4) throw new ParseException("Too many arguments to if"); if (form.count() < 3) throw new ParseException("Too few arguments to if"); Expr testExpr = Compiler.Analyze(pcon.EvalOrExpr().SetAssign(false),RT.second(form)); Expr thenExpr = Compiler.Analyze(pcon.SetAssign(false), RT.third(form)); Expr elseExpr = Compiler.Analyze(pcon.SetAssign(false), RT.fourth(form)); return new IfExpr((IPersistentMap)Compiler.SourceSpanVar.deref(), testExpr, thenExpr, elseExpr); }
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); }
private static void Compile1(TypeBuilder tb, CljILGen ilg, ObjExpr objx, object form) { object line = LineVarDeref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.LineKey)) line = RT.meta(form).valAt(RT.LineKey); object column = ColumnVarDeref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.ColumnKey)) column = RT.meta(form).valAt(RT.ColumnKey); IPersistentMap sourceSpan = (IPersistentMap)SourceSpanVar.deref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.SourceSpanKey)) sourceSpan = (IPersistentMap)RT.meta(form).valAt(RT.SourceSpanKey); ParserContext evPC = new ParserContext(RHC.Eval); Var.pushThreadBindings(RT.map(LineVar, line, ColumnVar, column, SourceSpanVar, sourceSpan)); try { form = Macroexpand(form); if (form is ISeq && Util.Equals(RT.first(form), DoSym)) { for (ISeq s = RT.next(form); s != null; s = RT.next(s)) Compile1(tb, ilg, objx, RT.first(s)); } else { Expr expr = Analyze(evPC, form); objx.Keywords = (IPersistentMap)KeywordsVar.deref(); objx.Vars = (IPersistentMap)VarsVar.deref(); objx.Constants = (PersistentVector)ConstantsVar.deref(); objx.EmitConstantFieldDefs(tb); expr.Emit(RHC.Expression,objx,ilg); ilg.Emit(OpCodes.Pop); expr.Eval(); } } finally { Var.popThreadBindings(); } }
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.FnSym, 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, 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)); 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(); } }
private static Expr AnalyzeSeq(ParserContext pcon, ISeq form, string name ) { object line = LineVarDeref(); object column = ColumnVarDeref(); IPersistentMap sourceSpan = (IPersistentMap)SourceSpanVar.deref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.LineKey)) line = RT.meta(form).valAt(RT.LineKey); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.ColumnKey)) column = RT.meta(form).valAt(RT.ColumnKey); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.SourceSpanKey)) sourceSpan = (IPersistentMap)RT.meta(form).valAt(RT.SourceSpanKey); Var.pushThreadBindings(RT.map(LineVar, line, ColumnVar, column, SourceSpanVar, sourceSpan)); try { object me = MacroexpandSeq1(form); if (me != form) return Analyze(pcon, me, name); object op = RT.first(form); if (op == null) throw new ArgumentNullException("form","Can't call nil"); IFn inline = IsInline(op, RT.count(RT.next(form))); if (inline != null) return Analyze(pcon, MaybeTransferSourceInfo(PreserveTag(form, inline.applyTo(RT.next(form))), form)); IParser p; if (op.Equals(FnSym)) return FnExpr.Parse(pcon, form, name); if ((p = GetSpecialFormParser(op)) != null) return p.Parse(pcon, form); else return InvokeExpr.Parse(pcon, form); } catch (CompilerException) { throw; } catch (Exception e) { throw new CompilerException((String)SourcePathVar.deref(), LineVarDeref(), ColumnVarDeref(), e); } 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>(); 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 form) { // (def x) or (def x initexpr) or (def x "docstring" initexpr) string docstring = null; if (RT.count(form) == 4 && (RT.third(form) is String)) { docstring = (String)RT.third(form); form = RT.list(RT.first(form), RT.second(form), RT.fourth(form)); } if (RT.count(form) > 3) throw new ParseException("Too many arguments to def"); if (RT.count(form) < 2) throw new ParseException("Too few arguments to def"); Symbol sym = RT.second(form) as Symbol; if (sym == null) throw new ParseException("First argument to def must be a Symbol."); //Console.WriteLine("Def {0}", sym.Name); Var v = Compiler.LookupVar(sym, true); if (v == null) throw new ParseException("Can't refer to qualified var that doesn't exist"); if (!v.Namespace.Equals(Compiler.CurrentNamespace)) { if (sym.Namespace == null) { v = Compiler.CurrentNamespace.intern(sym); Compiler.RegisterVar(v); } //throw new Exception(string.Format("Name conflict, can't def {0} because namespace: {1} refers to: {2}", // sym, Compiler.CurrentNamespace.Name, v)); else throw new ParseException("Can't create defs outside of current namespace"); } IPersistentMap mm = sym.meta(); bool isDynamic = RT.booleanCast(RT.get(mm, Compiler.DynamicKeyword)); if (isDynamic) v.setDynamic(); if (!isDynamic && sym.Name.StartsWith("*") && sym.Name.EndsWith("*") && sym.Name.Length > 2) { RT.errPrintWriter().WriteLine("Warning: {0} not declared dynamic and thus is not dynamically rebindable, " + "but its name suggests otherwise. Please either indicate ^:dynamic {0} or change the name. ({1}:{2}\n", sym,Compiler.SourcePathVar.get(),Compiler.LineVar.get()); } if (RT.booleanCast(RT.get(mm, Compiler.ArglistsKeyword))) { IPersistentMap vm = v.meta(); //vm = (IPersistentMap)RT.assoc(vm, Compiler.STATIC_KEY, true); // drop quote vm = (IPersistentMap)RT.assoc(vm, Compiler.ArglistsKeyword, RT.second(mm.valAt(Compiler.ArglistsKeyword))); v.setMeta(vm); } Object source_path = Compiler.SourcePathVar.get(); source_path = source_path ?? "NO_SOURCE_FILE"; mm = (IPersistentMap)RT.assoc(mm,RT.LineKey, Compiler.LineVar.get()) .assoc(RT.ColumnKey,Compiler.ColumnVar.get()) .assoc(RT.FileKey, source_path); //.assoc(RT.SOURCE_SPAN_KEY,Compiler.SOURCE_SPAN.deref()); if (docstring != null) mm = (IPersistentMap)RT.assoc(mm, RT.DocKey, docstring); // Following comment in JVM version //mm = mm.without(RT.DOC_KEY) // .without(Keyword.intern(null, "arglists")) // .without(RT.FILE_KEY) // .without(RT.LINE_KEY) // .without(RT.COLUMN_KEY) // .without(Keyword.intern(null, "ns")) // .without(Keyword.intern(null, "name")) // .without(Keyword.intern(null, "added")) // .without(Keyword.intern(null, "static")); mm = (IPersistentMap)Compiler.ElideMeta(mm); Expr meta = mm == null || mm.count() == 0 ? null : Compiler.Analyze(pcon.EvalOrExpr(),mm); Expr init = Compiler.Analyze(pcon.EvalOrExpr(),RT.third(form), v.Symbol.Name); bool initProvided = RT.count(form) == 3; return new DefExpr( (string)Compiler.SourceVar.deref(), Compiler.LineVarDeref(), Compiler.ColumnVarDeref(), v, init, meta, initProvided,isDynamic); }
internal static List<HostArg> ParseArgs(ParserContext pcon, ISeq argSeq) { List<HostArg> args = new List<HostArg>(); for (ISeq s = argSeq; s != null; s = s.next()) { object arg = s.first(); HostArg.ParameterType paramType = HostArg.ParameterType.Standard; LocalBinding lb = null; if (arg is ISeq) { Symbol op = RT.first(arg) as Symbol; if (op != null && op.Equals(BY_REF)) { if (RT.Length((ISeq)arg) != 2) throw new ArgumentException("Wrong number of arguments to {0}", ((Symbol)op).Name); object localArg = RT.second(arg); if (!(localArg is Symbol) || (lb = Compiler.ReferenceLocal((Symbol)localArg)) == null) throw new ArgumentException("Argument to {0} must be a local variable.", ((Symbol)op).Name); paramType = HostArg.ParameterType.ByRef; arg = localArg; } } Expr expr = Compiler.Analyze(pcon.EvEx(),arg); args.Add(new HostArg(paramType, expr, lb)); } return args; }
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 Analyze(ParserContext pcontext, object form) { return Analyze(pcontext, form, null); }
public static object eval(object form) { object line = LineVarDeref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.LineKey)) line = RT.meta(form).valAt(RT.LineKey); object column = ColumnVarDeref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.ColumnKey)) column = RT.meta(form).valAt(RT.ColumnKey); IPersistentMap sourceSpan = (IPersistentMap)SourceSpanVar.deref(); if (RT.meta(form) != null && RT.meta(form).containsKey(RT.SourceSpanKey)) sourceSpan = (IPersistentMap)RT.meta(form).valAt(RT.SourceSpanKey); ParserContext pconExpr = new ParserContext(RHC.Expression); ParserContext pconEval = new ParserContext(RHC.Eval); Var.pushThreadBindings(RT.map(LineVar, line, ColumnVar, column, SourceSpanVar, sourceSpan, CompilerContextVar, null)); try { form = Macroexpand(form); if (form is ISeq && Util.equals(RT.first(form), DoSym)) { ISeq s = RT.next(form); for (; RT.next(s) != null; s = RT.next(s)) eval(RT.first(s)); return eval(RT.first(s)); } else if ( (form is IType) || (form is IPersistentCollection && !(RT.first(form) is Symbol && ((Symbol)RT.first(form)).Name.StartsWith("def")))) { ObjExpr objx = (ObjExpr)Analyze(pconExpr, RT.list(FnSym, PersistentVector.EMPTY, form), "eval__" + RT.nextID()); IFn fn = (IFn)objx.Eval(); return fn.invoke(); } else { Expr expr = Analyze(pconEval, form); return expr.Eval(); } } 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)); 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, ((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)); }
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.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); 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 static Expr Parse(ParserContext pcon, ISeq form, string name) { ISeq origForm = form; FnExpr fn = new FnExpr(Compiler.TagOf(form)); fn.Src = form; Keyword retKey = Keyword.intern(null, "rettag"); // TODO: make static object retTag = RT.get(RT.meta(form), retKey); ObjMethod enclosingMethod = (ObjMethod)Compiler.MethodVar.deref(); fn._hasEnclosingMethod = enclosingMethod != null; if (((IMeta)form.first()).meta() != null) { fn.OnceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE)); } fn.ComputeNames(form, name); List <string> prims = new List <string>(); //arglist might be preceded by symbol naming this fn Symbol nm = RT.second(form) as Symbol; if (nm != null) { fn.ThisName = nm.Name; form = RT.cons(Compiler.FnSym, RT.next(RT.next(form))); } // Normalize body //now (fn [args] body...) or (fn ([args] body...) ([args2] body2...) ...) //turn former into latter if (RT.second(form) is IPersistentVector) { form = RT.list(Compiler.FnSym, RT.next(form)); } fn.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); GenContext newContext = null; GenContext context = Compiler.CompilerContextVar.deref() as GenContext ?? Compiler.EvalContext; newContext = context.WithNewDynInitHelper(fn.InternalName + "__dynInitHelper_" + RT.nextID().ToString()); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, newContext)); try { try { Var.pushThreadBindings(RT.mapUniqueKeys( Compiler.ConstantsVar, PersistentVector.EMPTY, Compiler.ConstantIdsVar, new IdentityHashMap(), Compiler.KeywordsVar, PersistentHashMap.EMPTY, Compiler.VarsVar, PersistentHashMap.EMPTY, Compiler.KeywordCallsitesVar, PersistentVector.EMPTY, Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY, Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(), Compiler.NoRecurVar, null)); SortedDictionary <int, FnMethod> methods = new SortedDictionary <int, FnMethod>(); FnMethod variadicMethod = null; bool usesThis = false; for (ISeq s = RT.next(form); s != null; s = RT.next(s)) { FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s), retTag); if (f.UsesThis) { //Console.WriteLine("{0} uses this",fn.Name); usesThis = true; } if (f.IsVariadic) { if (variadicMethod == null) { variadicMethod = f; } else { throw new ParseException("Can't have more than 1 variadic overload"); } } else if (!methods.ContainsKey(f.RequiredArity)) { methods[f.RequiredArity] = f; } else { throw new ParseException("Can't have 2 overloads with the same arity."); } if (f.Prim != null) { prims.Add(f.Prim); } } if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams) { throw new ParseException("Can't have fixed arity methods with more params than the variadic method."); } fn.CanBeDirect = !fn._hasEnclosingMethod && fn.Closes.count() == 0 && !usesThis; IPersistentCollection allMethods = null; foreach (FnMethod method in methods.Values) { allMethods = RT.conj(allMethods, method); } if (variadicMethod != null) { allMethods = RT.conj(allMethods, variadicMethod); } if (fn.CanBeDirect) { for (ISeq s = RT.seq(allMethods); s != null; s = s.next()) { FnMethod fm = s.first() as FnMethod; if (fm.Locals != null) { for (ISeq sl = RT.seq(RT.keys(fm.Locals)); sl != null; sl = sl.next()) { LocalBinding lb = sl.first() as LocalBinding; if (lb.IsArg) { lb.Index -= 1; } } } } } fn.Methods = allMethods; fn._variadicMethod = variadicMethod; fn.Keywords = (IPersistentMap)Compiler.KeywordsVar.deref(); fn.Vars = (IPersistentMap)Compiler.VarsVar.deref(); fn.Constants = (PersistentVector)Compiler.ConstantsVar.deref(); fn.KeywordCallsites = (IPersistentVector)Compiler.KeywordCallsitesVar.deref(); fn.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref(); fn.VarCallsites = (IPersistentSet)Compiler.VarCallsitesVar.deref(); fn.ConstantsID = RT.nextID(); } finally { Var.popThreadBindings(); } IPersistentMap fmeta = RT.meta(origForm); if (fmeta != null) { fmeta = fmeta.without(RT.LineKey).without(RT.ColumnKey).without(RT.SourceSpanKey).without(RT.FileKey).without(retKey); } fn._hasMeta = RT.count(fmeta) > 0; IPersistentVector primTypes = PersistentVector.EMPTY; foreach (string typename in prims) { primTypes = primTypes.cons(Type.GetType(typename)); } fn.Compile( fn.IsVariadic ? typeof(RestFn) : typeof(AFunction), null, primTypes, fn.OnceOnly, newContext); if (fn.SupportsMeta) { return(new MetaExpr(fn, MapExpr.Parse(pcon.EvalOrExpr(), fmeta))); } else { return(fn); } } finally { if (newContext != null) { Var.popThreadBindings(); } } }
public Expr Parse(ParserContext pcon, object form) { // (def x) or (def x initexpr) or (def x "docstring" initexpr) string docstring = null; if (RT.count(form) == 4 && (RT.third(form) is String)) { docstring = (String)RT.third(form); form = RT.list(RT.first(form), RT.second(form), RT.fourth(form)); } if (RT.count(form) > 3) { throw new ParseException("Too many arguments to def"); } if (RT.count(form) < 2) { throw new ParseException("Too few arguments to def"); } Symbol sym = RT.second(form) as Symbol; if (sym == null) { throw new ParseException("First argument to def must be a Symbol."); } //Console.WriteLine("Def {0}", sym.Name); Var v = Compiler.LookupVar(sym, true); if (v == null) { throw new ParseException("Can't refer to qualified var that doesn't exist"); } if (!v.Namespace.Equals(Compiler.CurrentNamespace)) { if (sym.Namespace == null) { v = Compiler.CurrentNamespace.intern(sym); } //throw new Exception(string.Format("Name conflict, can't def {0} because namespace: {1} refers to: {2}", // sym, Compiler.CurrentNamespace.Name, v)); else { throw new ParseException("Can't create defs outside of current namespace"); } } IPersistentMap mm = sym.meta(); bool isDynamic = RT.booleanCast(RT.get(mm, Compiler.DynamicKeyword)); if (isDynamic) { v.setDynamic(); } if (!isDynamic && sym.Name.StartsWith("*") && sym.Name.EndsWith("*") && sym.Name.Length > 1) { RT.errPrintWriter().WriteLine("Warning: {0} not declared dynamic and thus is not dynamically rebindable, " + "but its name suggests otherwise. Please either indicate ^:dynamic {0} or change the name. ({1}:{2}\n", sym, Compiler.SourcePathVar.get(), Compiler.LineVar.get()); } if (RT.booleanCast(RT.get(mm, Compiler.ArglistsKeyword))) { IPersistentMap vm = v.meta(); //vm = (IPersistentMap)RT.assoc(vm, Compiler.STATIC_KEY, true); // drop quote vm = (IPersistentMap)RT.assoc(vm, Compiler.ArglistsKeyword, RT.second(mm.valAt(Compiler.ArglistsKeyword))); v.setMeta(vm); } Object source_path = Compiler.SourcePathVar.get(); source_path = source_path ?? "NO_SOURCE_FILE"; mm = (IPersistentMap)RT.assoc(mm, RT.LineKey, Compiler.LineVar.get()) .assoc(RT.FileKey, source_path); //.assoc(RT.SOURCE_SPAN_KEY,Compiler.SOURCE_SPAN.deref()); if (docstring != null) { mm = (IPersistentMap)RT.assoc(mm, RT.DocKey, docstring); } //mm = mm.without(RT.DOC_KEY) // .without(Keyword.intern(null, "arglists")) // .without(RT.FILE_KEY) // .without(RT.LINE_KEY) // .without(Keyword.intern(null, "ns")) // .without(Keyword.intern(null, "name")) // .without(Keyword.intern(null, "added")) // .without(Keyword.intern(null, "static")); mm = (IPersistentMap)Compiler.ElideMeta(mm); Expr meta = mm == null || mm.count() == 0 ? null : Compiler.Analyze(pcon.EvalOrExpr(), mm); Expr init = Compiler.Analyze(pcon.EvalOrExpr(), RT.third(form), v.Symbol.Name); bool initProvided = RT.count(form) == 3; return(new DefExpr( (string)Compiler.SourceVar.deref(), (int)Compiler.LineVar.deref(), v, init, meta, initProvided, isDynamic)); }
public Expr Parse(ParserContext pcon, object frm) { return(new ImportExpr((string)RT.second(frm))); }
public static Expr Analyze(ParserContext pcontext, object form, string name) { try { if (form is LazySeq) { form = RT.seq(form); if (form == null) form = PersistentList.EMPTY; } if (form == null) return NilExprInstance; else if (form is Boolean) return ((bool)form) ? TrueExprInstance : FalseExprInstance; Type type = form.GetType(); if (type == typeof(Symbol)) return AnalyzeSymbol((Symbol)form); else if (type == typeof(Keyword)) return RegisterKeyword((Keyword)form); else if (Util.IsNumeric(form)) return NumberExpr.Parse(form); else if (type == typeof(String)) return new StringExpr(String.Intern((String)form)); else if (form is IPersistentCollection && ((IPersistentCollection)form).count() == 0) return OptionallyGenerateMetaInit(pcontext, form, new EmptyExpr(form)); else if (form is ISeq) return AnalyzeSeq(pcontext, (ISeq)form, name); else if (form is IPersistentVector) return VectorExpr.Parse(pcontext, (IPersistentVector)form); else if (form is IRecord) return new ConstantExpr(form); else if (form is IType) return new ConstantExpr(form); else if (form is IPersistentMap) return MapExpr.Parse(pcontext, (IPersistentMap)form); else if (form is IPersistentSet) return SetExpr.Parse(pcontext, (IPersistentSet)form); else return new ConstantExpr(form); } catch (CompilerException) { throw; } catch (Exception e) { throw new CompilerException((String)SourcePathVar.deref(), LineVarDeref(), ColumnVarDeref(), e); } }
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) { 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; 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 is one of: // (. x fieldname-sym) // (. x 0-ary-method) // (. x propertyname-sym) // (. x methodname-sym args)+ // (. x (methodname-sym args?)) // (. x (generic-m if (RT.Length(form) < 3) throw new ArgumentException("Malformed member expression, expecting (. target member ... )"); string source = (string)Compiler.SOURCE.deref(); IPersistentMap spanMap = (IPersistentMap)Compiler.SOURCE_SPAN.deref(); // Compiler.GetSourceSpanMap(form); Symbol tag = Compiler.TagOf(form); // determine static or instance // static target must be symbol, either fully.qualified.Typename or Typename that has been imported Type t = HostExpr.MaybeType(RT.second(form), false); // at this point, t will be non-null if static Expr instance = null; if (t == null) instance = Compiler.Analyze(pcon.EvEx(),RT.second(form)); bool isZeroArityCall = RT.Length(form) == 3 && (RT.third(form) is Symbol || RT.third(form) is Keyword); if (isZeroArityCall) { PropertyInfo pinfo = null; FieldInfo finfo = null; MethodInfo minfo = null; Symbol sym = (RT.third(form) is Keyword) ? ((Keyword)RT.third(form)).Symbol : (Symbol)RT.third(form); string fieldName = Compiler.munge(sym.Name); // The JVM version does not have to worry about Properties. It captures 0-arity methods under fields. // We have to put in special checks here for this. // Also, when reflection is required, we have to capture 0-arity methods under the calls that // are generated by StaticFieldExpr and InstanceFieldExpr. if (t != null) { if ((finfo = Reflector.GetField(t, fieldName, true)) != null) return new StaticFieldExpr(source, spanMap, tag, t, fieldName, finfo); if ((pinfo = Reflector.GetProperty(t, fieldName, true)) != null) return new StaticPropertyExpr(source, spanMap, tag, t, fieldName, pinfo); if ((minfo = Reflector.GetArityZeroMethod(t, fieldName, true)) != null) return new StaticMethodExpr(source, spanMap, tag, t, fieldName, null, new List<HostArg>()); throw new MissingMemberException(t.Name, fieldName); } else if (instance != null && instance.HasClrType && instance.ClrType != null) { Type instanceType = instance.ClrType; if ((finfo = Reflector.GetField(instanceType, fieldName, false)) != null) return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, finfo); if ((pinfo = Reflector.GetProperty(instanceType, fieldName, false)) != null) return new InstancePropertyExpr(source, spanMap, tag, instance, fieldName, pinfo); if ((minfo = Reflector.GetArityZeroMethod(instanceType, fieldName, false)) != null) return new InstanceMethodExpr(source, spanMap, tag, instance, fieldName, null, new List<HostArg>()); if (pcon.IsAssignContext) return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null else return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName); } else { // t is null, so we know this is not a static call // If instance is null, we are screwed anyway. // If instance is not null, then we don't have a type. // So we must be in an instance call to a property, field, or 0-arity method. // The code generated by InstanceFieldExpr/InstancePropertyExpr with a null FieldInfo/PropertyInfo // will generate code to do a runtime call to a Reflector method that will check all three. //return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null //return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName); if (pcon.IsAssignContext) return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null else return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName); } } //ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); ISeq call; List<Type> typeArgs = null; //object third = RT.third(form); //if (third is ISeq && RT.first(third) is Symbol && ((Symbol)RT.first(third)).Equals(GENERIC)) //{ // // We have a generic method call // // (. thing (generic methodname type1 ...) args...) // typeArgs = ParseGenericMethodTypeArgs(RT.next(RT.next(third))); // call = RT.listStar(RT.second(third), RT.next(RT.next(RT.next(form)))); //} //else // call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); object fourth = RT.fourth(form); if (fourth is ISeq && RT.first(fourth) is Symbol && ((Symbol)RT.first(fourth)).Equals(TYPE_ARGS)) { // We have a type args supplied for a generic method call // (. thing methodname (type-args type1 ... ) args ...) typeArgs = ParseGenericMethodTypeArgs(RT.next(fourth)); call = RT.listStar(RT.third(form), RT.next(RT.next(RT.next(RT.next(form))))); } else call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); if (!(RT.first(call) is Symbol)) throw new ArgumentException("Malformed member exception"); string methodName = Compiler.munge(((Symbol)RT.first(call)).Name); List<HostArg> args = ParseArgs(pcon, RT.next(call)); return t != null ? (MethodExpr)(new StaticMethodExpr(source, spanMap, tag, t, methodName, typeArgs, args)) : (MethodExpr)(new InstanceMethodExpr(source, spanMap, tag, instance, methodName, typeArgs, args)); }
public static Expr Parse(ParserContext pcon, ISeq form, string name) { ISeq origForm = form; FnExpr fn = new FnExpr(Compiler.TagOf(form)); fn._src = form; if (((IMeta)form.first()).meta() != null) { fn._onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE)); } fn.ComputeNames(form, name); // Java: fn.objtype = Type.getObjectType(fn.internalName) -- makes no sense for us, this is ASM only. List<string> prims = new List<string>(); try { Var.pushThreadBindings(RT.map( Compiler.CONSTANTS, PersistentVector.EMPTY, Compiler.CONSTANT_IDS, new IdentityHashMap(), Compiler.KEYWORDS, PersistentHashMap.EMPTY, Compiler.VARS, PersistentHashMap.EMPTY, Compiler.KEYWORD_CALLSITES,PersistentVector.EMPTY, Compiler.PROTOCOL_CALLSITES,PersistentVector.EMPTY, Compiler.VAR_CALLSITES,Compiler.EmptyVarCallSites(), Compiler.NO_RECUR,null)); //arglist might be preceded by symbol naming this fn if (RT.second(form) is Symbol) { Symbol nm = (Symbol)RT.second(form); fn._thisName = nm.Name; fn.IsStatic = false; // RT.booleanCast(RT.get(nm.meta(), Compiler.STATIC_KEY)); form = RT.cons(Compiler.FN, RT.next(RT.next(form))); } // Normalize body //now (fn [args] body...) or (fn ([args] body...) ([args2] body2...) ...) //turn former into latter if (RT.second(form) is IPersistentVector) form = RT.list(Compiler.FN, RT.next(form)); SortedDictionary<int, FnMethod> methods = new SortedDictionary<int, FnMethod>(); FnMethod variadicMethod = null; for (ISeq s = RT.next(form); s != null; s = RT.next(s)) { FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s),fn.IsStatic); if (f.IsVariadic) { if (variadicMethod == null) variadicMethod = f; else throw new Exception("Can't have more than 1 variadic overload"); } else if (!methods.ContainsKey(f.RequiredArity)) methods[f.RequiredArity] = f; else throw new Exception("Can't have 2 overloads with the same arity."); if (f.Prim != null) prims.Add(f.Prim); } if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams) throw new Exception("Can't have fixed arity methods with more params than the variadic method."); if ( fn.IsStatic && fn.Closes.count() > 0 ) throw new ArgumentException("static fns can't be closures"); IPersistentCollection allMethods = null; foreach (FnMethod method in methods.Values) allMethods = RT.conj(allMethods, method); if (variadicMethod != null) allMethods = RT.conj(allMethods, variadicMethod); fn._methods = allMethods; fn._variadicMethod = variadicMethod; fn.Keywords = (IPersistentMap)Compiler.KEYWORDS.deref(); fn.Vars = (IPersistentMap)Compiler.VARS.deref(); fn.Constants = (PersistentVector)Compiler.CONSTANTS.deref(); fn.KeywordCallsites = (IPersistentVector)Compiler.KEYWORD_CALLSITES.deref(); fn.ProtocolCallsites = (IPersistentVector)Compiler.PROTOCOL_CALLSITES.deref(); fn.VarCallsites = (IPersistentSet)Compiler.VAR_CALLSITES.deref(); fn._constantsID = RT.nextID(); } finally { Var.popThreadBindings(); } IPersistentMap fmeta = RT.meta(origForm); if (fmeta != null) fmeta = fmeta.without(RT.LINE_KEY).without(RT.FILE_KEY); fn._hasMeta = RT.count(fmeta) > 0; if (Compiler.IsCompiling || prims.Count > 0) { GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? Compiler.EvalContext; GenContext genC = context.WithNewDynInitHelper(fn.InternalName + "__dynInitHelper_" + RT.nextID().ToString()); IPersistentVector primTypes = PersistentVector.EMPTY; foreach (string typename in prims) primTypes = primTypes.cons(Type.GetType(typename)); fn.Compile( fn.IsVariadic ? typeof(RestFn) : typeof(AFunction), null, primTypes, fn.OnceOnly, genC); } else { fn.CompiledType = fn.GetPrecompiledType(); fn.FnMode = FnMode.Light; } if (fn.SupportsMeta) return new MetaExpr(fn, MapExpr.Parse(pcon.EvEx(),fmeta)); else return fn; }
public Expr Parse(ParserContext pcon, object form) { object v = RT.second(form); if (v == null) return Compiler.NIL_EXPR; else return new ConstantExpr(v); }
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(); object op = f is ISeq fSeq?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.MethodReturnContextVar, null)); 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(pcon, RT.seq(body)); } finally { Var.popThreadBindings(); } return(bodyExpr); } return(new TryExpr(bodyExpr, catches, finallyExpr, retLocal, finallyLocal)); }
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 form) { ISeq sform = (ISeq)form; // form is one of: // (. x fieldname-sym) // (. x 0-ary-method) // (. x propertyname-sym) // (. x methodname-sym args)+ // (. x (methodname-sym args?)) // (. x (generic-m if (RT.Length(sform) < 3) { throw new ParseException("Malformed member expression, expecting (. target member ... )"); } string source = (string)Compiler.SourceVar.deref(); IPersistentMap spanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // Compiler.GetSourceSpanMap(form); Symbol tag = Compiler.TagOf(sform); // determine static or instance // static target must be symbol, either fully.qualified.Typename or Typename that has been imported Type t = HostExpr.MaybeType(RT.second(sform), false); // at this point, t will be non-null if static Expr instance = null; if (t == null) { instance = Compiler.Analyze(pcon.EvalOrExpr(), RT.second(sform)); } bool isZeroArityCall = RT.Length(sform) == 3 && RT.third(sform) is Symbol; if (isZeroArityCall) { PropertyInfo pinfo = null; FieldInfo finfo = null; // TODO: Figure out if we want to handle the -propname otherwise. bool isPropName = false; Symbol sym = (Symbol)RT.third(sform); if (sym.Name[0] == '-') { isPropName = true; sym = Symbol.intern(sym.Name.Substring(1)); } string fieldName = Compiler.munge(sym.Name); // The JVM version does not have to worry about Properties. It captures 0-arity methods under fields. // We have to put in special checks here for this. // Also, when reflection is required, we have to capture 0-arity methods under the calls that // are generated by StaticFieldExpr and InstanceFieldExpr. if (t != null) { if ((finfo = Reflector.GetField(t, fieldName, true)) != null) { return(new StaticFieldExpr(source, spanMap, tag, t, fieldName, finfo)); } if ((pinfo = Reflector.GetProperty(t, fieldName, true)) != null) { return(new StaticPropertyExpr(source, spanMap, tag, t, fieldName, pinfo)); } if (!isPropName && Reflector.GetArityZeroMethod(t, fieldName, true) != null) { return(new StaticMethodExpr(source, spanMap, tag, t, fieldName, null, new List <HostArg>())); } throw new MissingMemberException(t.Name, fieldName); } else if (instance != null && instance.HasClrType && instance.ClrType != null) { Type instanceType = instance.ClrType; if ((finfo = Reflector.GetField(instanceType, fieldName, false)) != null) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, finfo)); } if ((pinfo = Reflector.GetProperty(instanceType, fieldName, false)) != null) { return(new InstancePropertyExpr(source, spanMap, tag, instance, fieldName, pinfo)); } if (!isPropName && Reflector.GetArityZeroMethod(instanceType, fieldName, false) != null) { return(new InstanceMethodExpr(source, spanMap, tag, instance, fieldName, null, new List <HostArg>())); } if (pcon.IsAssignContext) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null } else { return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName)); } } else { // t is null, so we know this is not a static call // If instance is null, we are screwed anyway. // If instance is not null, then we don't have a type. // So we must be in an instance call to a property, field, or 0-arity method. // The code generated by InstanceFieldExpr/InstancePropertyExpr with a null FieldInfo/PropertyInfo // will generate code to do a runtime call to a Reflector method that will check all three. //return new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null); // same as InstancePropertyExpr when last arg is null //return new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName); if (pcon.IsAssignContext) { return(new InstanceFieldExpr(source, spanMap, tag, instance, fieldName, null)); // same as InstancePropertyExpr when last arg is null } else { return(new InstanceZeroArityCallExpr(source, spanMap, tag, instance, fieldName)); } } } //ISeq call = RT.third(form) is ISeq ? (ISeq)RT.third(form) : RT.next(RT.next(form)); ISeq call; List <Type> typeArgs = null; object fourth = RT.fourth(sform); if (fourth is ISeq && RT.first(fourth) is Symbol && ((Symbol)RT.first(fourth)).Equals(TypeArgsSym)) { // We have a type args supplied for a generic method call // (. thing methodname (type-args type1 ... ) args ...) typeArgs = ParseGenericMethodTypeArgs(RT.next(fourth)); call = RT.listStar(RT.third(sform), RT.next(RT.next(RT.next(RT.next(sform))))); } else { call = RT.third(sform) is ISeq ? (ISeq)RT.third(sform) : RT.next(RT.next(sform)); } if (!(RT.first(call) is Symbol)) { throw new ParseException("Malformed member exception"); } string methodName = Compiler.munge(((Symbol)RT.first(call)).Name); List <HostArg> args = ParseArgs(pcon, RT.next(call)); return(t != null ? (MethodExpr)(new StaticMethodExpr(source, spanMap, tag, t, methodName, typeArgs, args)) : (MethodExpr)(new InstanceMethodExpr(source, spanMap, tag, instance, methodName, typeArgs, args))); }
public Expr Parse(ParserContext pcon, object frm) { return new ImportExpr((string)RT.second(frm)); }
//(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); }
internal static Expr OptionallyGenerateMetaInit(ParserContext pcon, object form, Expr expr) { Expr ret = expr; if ( RT.meta(form) != null ) ret = new MetaExpr(ret, (MapExpr)MapExpr.Parse(pcon.EvalOrExpr(),((IObj)form).meta())); return ret; }
public static Expr Parse(ParserContext pcon, IPersistentMap form) { ParserContext pconToUse = pcon.EvalOrExpr(); bool keysConstant = true; bool valsConstant = true; bool allConstantKeysUnique = true; IPersistentSet constantKeys = PersistentHashSet.EMPTY; IPersistentVector keyvals = PersistentVector.EMPTY; for (ISeq s = RT.seq(form); s != null; s = s.next()) { IMapEntry e = (IMapEntry)s.first(); Expr k = Compiler.Analyze(pconToUse, e.key()); Expr v = Compiler.Analyze(pconToUse, e.val()); keyvals = (IPersistentVector)keyvals.cons(k); keyvals = (IPersistentVector)keyvals.cons(v); if (k is LiteralExpr) { object kval = k.Eval(); if (constantKeys.contains(kval)) { allConstantKeysUnique = false; } else { constantKeys = (IPersistentSet)constantKeys.cons(kval); } } else { keysConstant = false; } if (!(v is LiteralExpr)) { valsConstant = false; } } Expr ret = new MapExpr(keyvals); IObj iobjForm = form as IObj; if (iobjForm != null && iobjForm.meta() != null) { return(Compiler.OptionallyGenerateMetaInit(pcon, form, ret)); } //else if (constant) //{ // This 'optimzation' works, mostly, unless you have nested map values. // The nested map values do not participate in the constants map, so you end up with the code to create the keys. // Result: huge duplication of keyword creation. 3X increase in init time to the REPL. // //IPersistentMap m = PersistentHashMap.EMPTY; // //for (int i = 0; i < keyvals.length(); i += 2) // // m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val); // //return new ConstantExpr(m); // return ret; //} else if (keysConstant) { // TBD: Add more detail to exception thrown below. if (!allConstantKeysUnique) { throw new ArgumentException("Duplicate constant keys in map"); } if (valsConstant) { // This 'optimzation' works, mostly, unless you have nested map values. // The nested map values do not participate in the constants map, so you end up with the code to create the keys. // Result: huge duplication of keyword creation. 3X increase in init time to the REPL. //IPersistentMap m = PersistentArrayMap.EMPTY; //for (int i = 0; i < keyvals.length(); i += 2) // m = m.assoc(((LiteralExpr)keyvals.nth(i)).Val, ((LiteralExpr)keyvals.nth(i + 1)).Val); //return new ConstantExpr(m); return(ret); } else { return(ret); } } else { return(ret); } }