internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = ClosedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
void EmitClosedOverFields(TypeBuilder tb) { _closedOverFields = new List <FieldBuilder>(Closes.count()); _closedOverFieldsMap = new Dictionary <LocalBinding, FieldBuilder>(Closes.count()); // closed-overs map to instance fields. for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); FieldAttributes attributes = FieldAttributes.Public; bool markVolatile = IsVolatile(lb); if (IsDefType) { if (!IsMutable(lb)) { attributes |= FieldAttributes.InitOnly; } } Type type = lb.PrimitiveType ?? typeof(object); FieldBuilder fb = markVolatile ? tb.DefineField(lb.Name, type, new Type[] { typeof(IsVolatile) }, Type.EmptyTypes, attributes) : tb.DefineField(lb.Name, type, attributes); GenInterface.SetCustomAttributes(fb, GenInterface.ExtractAttributes(RT.meta(lb.Symbol))); _closedOverFields.Add(fb); _closedOverFieldsMap[lb] = fb; } }
internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals) { if (_typeBuilder != null) { // Full compile ilg.Emit(OpCodes.Castclass, _typeBuilder); for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (letFnLocals.contains(lb)) { FieldBuilder fb; _closedOverFieldsMap.TryGetValue(lb, out fb); Type primt = lb.PrimitiveType; ilg.Emit(OpCodes.Dup); // this if (primt != null) { objx.EmitUnboxedLocal(ilg, lb); ilg.Emit(OpCodes.Stfld, fb); } else { objx.EmitLocal(ilg, lb); ilg.Emit(OpCodes.Stfld, fb); } } } ilg.Emit(OpCodes.Pop); } }
Expression GenDlrForFile(GenContext context) { EnsureTypeBuilt(context); //ConstructorInfo ctorInfo = _ctorInfo; ConstructorInfo ctorInfo = _fnType.GetConstructors()[0]; // The incoming context holds info on the containing function. // That is the one that holds the closed-over variable values. List <Expression> args = new List <Expression>(_closes.count()); for (ISeq s = RT.keys(_closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (lb.PrimitiveType != null) { args.Add(context.FnExpr.GenUnboxedLocal(context, lb)); } else { args.Add(context.FnExpr.GenLocal(context, lb)); } } return(Expression.New(ctorInfo, args)); }
public virtual void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any //objx arg is enclosing objx, not this if (IsDefType) ilg.Emit(OpCodes.Ldnull); else { if (SupportsMeta) { ilg.Emit(OpCodes.Ldnull); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); } for (ISeq s = RT.keys(Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (lb.PrimitiveType != null) objx.EmitUnboxedLocal(ilg, lb); else objx.EmitLocal(ilg, lb); } ilg.Emit(OpCodes.Newobj, CtorInfo); } if (rhc == RHC.Statement) ilg.Emit(OpCodes.Pop); }
public virtual Expression GenCode(RHC rhc, ObjExpr objx, GenContext context) { if (IsDefType) { return(Expression.Constant(null)); } List <Expression> args = new List <Expression>(_closes.count() + 1); if (SupportsMeta) { args.Add(Expression.Constant(null, typeof(IPersistentMap))); // meta } for (ISeq s = RT.keys(_closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); if (lb.PrimitiveType != null) { args.Add(objx.GenUnboxedLocal(context, lb)); } else { args.Add(objx.GenLocal(context, lb)); } } Expression newExpr = Expression.New(_ctorInfo, args); return(newExpr); }
internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val) { if (!IsMutable(lb)) throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name); FieldBuilder fb = null; bool hasField = ClosedOverFieldsMap.TryGetValue(lb, out fb); ilg.Emit(OpCodes.Ldarg_0); // this Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr; if (!(mbe != null && mbe.CanEmitPrimitive)) throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name); mbe.EmitUnboxed(RHC.Expression, this, ilg); } else { val.Emit(RHC.Expression, this, ilg); } if (hasField) { ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else ilg.Emit(OpCodes.Stloc, lb.LocalVar); }
public LocalBindingExpr(LocalBinding b, Symbol tag) { if (b.PrimitiveType != null && _tag != null) throw new InvalidOperationException("Can't type hint a primitive local"); _b = b; _tag = tag; }
public LocalBindingExpr(LocalBinding b, Symbol tag) { if (b.PrimitiveType != null && _tag != null) { throw new InvalidOperationException("Can't type hint a primitive local"); } _b = b; _tag = tag; }
bool IsMutable(LocalBinding lb) { return(IsVolatile(lb) || RT.booleanCast(RT.contains(Fields, lb.Symbol)) && RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("unsynchronized-mutable"))) || lb.IsByRef); }
private void GenerateClosedOverFields(TypeBuilder baseTB) { _closedOverFields = new List <FieldBuilder>(_closes.count()); // closed-overs map to instance fields. for (ISeq s = RT.keys(_closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); Type type = lb.PrimitiveType ?? typeof(object); _closedOverFields.Add(baseTB.DefineField(lb.Name, type, FieldAttributes.FamORAssem)); } }
internal Expression GenUnboxedLocal(GenContext context, LocalBinding lb) { Type primType = lb.PrimitiveType; if (context.Mode == CompilerMode.File && _closes.containsKey(lb)) { return(Expression.Convert(Expression.Field(_thisParam, lb.Name), primType)); } else { return(lb.ParamExpression); } }
MethodBuilder GenerateStaticMethod(GenContext context) { string methodName = GetStaticMethodName(); FnExpr fn = context.FnExpr; TypeBuilder tb = fn.TypeBuilder; List <ParameterExpression> parms = new List <ParameterExpression>(_argLocals.count() + 1); ParameterExpression thisParm = Expression.Parameter(fn.BaseType, "this"); _thisBinding.ParamExpression = thisParm; fn.ThisParam = thisParm; parms.Add(thisParm); try { LabelTarget loopLabel = Expression.Label("top"); Var.pushThreadBindings(RT.map(Compiler.LOOP_LABEL, loopLabel, Compiler.METHODS, this)); for (int i = 0; i < _argLocals.count(); i++) { LocalBinding lb = (LocalBinding)_argLocals.nth(i); ParameterExpression parm = Expression.Parameter(typeof(object), lb.Name); lb.ParamExpression = parm; parms.Add(parm); } Expression body = Expression.Block( Expression.Label(loopLabel), Compiler.MaybeBox(_body.GenDlr(context))); LambdaExpression lambda = Expression.Lambda(body, parms); // TODO: Figure out why the Java code nulls all the local variables here. // TODO: Cache all the CreateObjectTypeArray values MethodBuilder mb = tb.DefineMethod(methodName, MethodAttributes.Static, typeof(object), Compiler.CreateObjectTypeArray(NumParams)); lambda.CompileToMethod(mb); //lambda.CompileToMethod(mb, true); return(mb); } finally { Var.popThreadBindings(); } }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]); if (primType != null) { HostExpr.EmitBoxReturn(this, ilg, primType); } // TODO: ONCEONLY? } else // FnMode.Light { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); } } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) { HostExpr.EmitBoxReturn(this, ilg, primType); } } }
internal Type[] CtorTypes() { int i = !SupportsMeta ? 0 : 1; Type[] ret = new Type[Closes.count() + i]; if (SupportsMeta) ret[0] = typeof(IPersistentMap); for (ISeq s = RT.keys(Closes); s != null; s = s.next(), i++) { LocalBinding lb = (LocalBinding)s.first(); ret[i] = lb.PrimitiveType ?? typeof(object); } return ret; }
internal Expression GenAssignLocal(GenContext context, LocalBinding lb, Expr val) { if (!IsMutable(lb)) { throw new ArgumentException("Cannot assign to non-mutable: " + lb.Name); } FieldBuilder fb; if (_closedOverFieldsMap.TryGetValue(lb, out fb)) { return(Expression.Assign(Expression.Field(_thisParam, _closedOverFieldsMap[lb]), val.GenCode(RHC.Expression, this, context))); } return(Expression.Assign(lb.ParamExpression, val.GenCode(RHC.Expression, this, context))); }
internal LambdaExpression GenerateImmediateLambda(RHC rhc, ObjExpr objx, GenContext context) { List <ParameterExpression> parmExprs = new List <ParameterExpression>(_argLocals.count()); if (_thisBinding != null) { _thisBinding.ParamExpression = objx.ThisParam; } try { LabelTarget loopLabel = Expression.Label("top"); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); for (int i = 0; i < _argLocals.count(); i++) { LocalBinding b = (LocalBinding)_argLocals.nth(i); ParameterExpression pexpr = Expression.Parameter(typeof(object), b.Name); b.ParamExpression = pexpr; parmExprs.Add(pexpr); } List <Expression> bodyExprs = new List <Expression>(); //bodyExprs.AddRange(typedParmInitExprs); bodyExprs.Add(Expression.Label(loopLabel)); bodyExprs.Add(Compiler.MaybeBox(_body.GenCode(rhc, objx, context))); Expression block; //if (typedParmExprs.Count > 0) // block = Expression.Block(typedParmExprs, bodyExprs); //else block = Expression.Block(bodyExprs); return(Expression.Lambda( FuncTypeHelpers.GetFFuncType(parmExprs.Count), block, Objx.ThisName, parmExprs)); } finally { Var.popThreadBindings(); } }
internal Expression GenLocal(GenContext context, LocalBinding lb) { if (context.Mode == CompilerMode.File && _closes.containsKey(lb)) { Expression expr = Expression.Field(_thisParam, lb.Name); Type primtType = lb.PrimitiveType; if (primtType != null) { expr = Compiler.MaybeBox(Expression.Convert(expr, primtType)); } return(expr); } else { return(lb.ParamExpression); } }
private Type[] CtorTypes() { if (_closes.count() == 0) { return(EMPTY_TYPE_ARRAY); } Type[] ret = new Type[_closes.count()]; int i = 0; for (ISeq s = RT.keys(_closes); s != null; s = s.next(), i++) { LocalBinding lb = (LocalBinding)s.first(); ret[i] = lb.PrimitiveType ?? typeof(object); } return(ret); }
public override Expression GenDlr(GenContext context) { LabelTarget loopLabel = (LabelTarget)Compiler.LOOP_LABEL.deref(); if (loopLabel == null) { throw new InvalidOperationException("Recur not in proper context."); } int argCount = _args.count(); List <ParameterExpression> tempVars = new List <ParameterExpression>(argCount); List <Expression> tempAssigns = new List <Expression>(argCount); List <Expression> finalAssigns = new List <Expression>(argCount); // Evaluate all the init forms into local variables. // TODO: Check the typing here. for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding b = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); ParameterExpression tempVar = Expression.Parameter(b.ParamExpression.Type, "__local__" + i); //asdf-tag Expression valExpr = ((Expr)_args.nth(i)).GenDlr(context); tempVars.Add(tempVar); if (tempVar.Type == typeof(Object)) { tempAssigns.Add(Expression.Assign(tempVar, Compiler.MaybeBox(valExpr))); } else { tempAssigns.Add(Expression.Assign(tempVar, Expression.Convert(valExpr, tempVar.Type))); //asdf-tag } finalAssigns.Add(Expression.Assign(b.ParamExpression, tempVar)); //asdf-tag } List <Expression> exprs = tempAssigns; exprs.AddRange(finalAssigns); exprs.Add(Expression.Goto(loopLabel)); // need to do this to get a return value in the type inferencing -- else can't use this in a then or else clause. exprs.Add(Expression.Constant(null)); return(Expression.Block(tempVars, exprs)); }
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; ISeq argAsSeq = arg as ISeq; if (argAsSeq != null) { Symbol op = RT.first(argAsSeq) as Symbol; if (op != null && op.Equals(ByRefSym)) { if (RT.Length(argAsSeq) != 2) { throw new ArgumentException("Wrong number of arguments to {0}", op.Name); } object localArg = RT.second(argAsSeq); Symbol symLocalArg = localArg as Symbol; if (symLocalArg == null || (lb = Compiler.ReferenceLocal(symLocalArg)) == null) { throw new ArgumentException("Argument to {0} must be a local variable.", op.Name); } paramType = HostArg.ParameterType.ByRef; arg = localArg; } } Expr expr = Compiler.Analyze(pcon.EvalOrExpr(), arg); args.Add(new HostArg(paramType, expr, lb)); } return(args); }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = ClosedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); if (lb.PrimitiveType != null) { ilg.Emit(OpCodes.Unbox, lb.PrimitiveType); } } } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } }
//private MethodBuilder GenerateConstants(TypeBuilder fnTB, Type baseType) //{ // try // { // Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T)); // List<Expression> inits = new List<Expression>(); // for (int i = 0; i < _constants.count(); i++) // { // object o = _constants.nth(i); // string stringValue = null; // if (o is string) // stringValue = (string)o; // else // { // try // { // stringValue = RT.printString(o); // } // catch (Exception) // { // throw new Exception(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", o)); // } // if (stringValue.Length == 0) // throw new Exception(String.Format("Can't embed unreadable object in code: " + o)); // if (stringValue.StartsWith("#<")) // throw new Exception(String.Format("Can't embed unreadable object in code: " + stringValue)); // } // Expression init = // Expression.Assign( // Expression.Field(null, baseType, ConstantName(i)), // Expression.Convert(Expression.Call(Compiler.Method_RT_readString, Expression.Constant(stringValue)), // ConstantType(i))); // inits.Add(init); // } // inits.Add(Expression.Default(typeof(void))); // Expression block = Expression.Block(inits); // LambdaExpression lambda = Expression.Lambda(block); // MethodBuilder methodBuilder = fnTB.DefineMethod(STATIC_CTOR_HELPER_NAME, MethodAttributes.Private | MethodAttributes.Static); // lambda.CompileToMethod(methodBuilder); // return methodBuilder; // } // finally // { // Var.popThreadBindings(); // } //} private ConstructorBuilder GenerateConstructor(TypeBuilder fnTB, Type baseType) { ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes()); ILGenerator gen = cb.GetILGenerator(); //Call base constructor ConstructorInfo baseCtorInfo = baseType.GetConstructor(EMPTY_TYPE_ARRAY); gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Call, baseCtorInfo); int a = 0; for (ISeq s = RT.keys(_closes); s != null; s = s.next(), a++) { LocalBinding lb = (LocalBinding)s.first(); FieldBuilder fb = _closedOverFields[a]; gen.Emit(OpCodes.Ldarg_0); gen.Emit(OpCodes.Ldarg, a + 1); gen.Emit(OpCodes.Stfld, fb); } gen.Emit(OpCodes.Ret); return(cb); }
internal bool IsMutable(LocalBinding lb) { return IsVolatile(lb) || RT.booleanCast(RT.contains(Fields, lb.Symbol)) && RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("unsynchronized-mutable"))) || lb.IsByRef; }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
internal static ObjExpr Build( IPersistentVector interfaceSyms, IPersistentVector fieldSyms, Symbol thisSym, string tagName, Symbol className, Symbol typeTag, ISeq methodForms, Object frm, IPersistentMap opts) { NewInstanceExpr ret = new NewInstanceExpr(null); ret.Src = frm; ret.Name = className.ToString(); ret.ClassMeta = GenInterface.ExtractAttributes(RT.meta(className)); ret.InternalName = ret.Name; // ret.Name.Replace('.', '/'); // Java: ret.objtype = Type.getObjectType(ret.internalName); ret.Opts = opts; if (thisSym != null) ret.ThisName = thisSym.Name; if (fieldSyms != null) { IPersistentMap fmap = PersistentHashMap.EMPTY; object[] closesvec = new object[2 * fieldSyms.count()]; for (int i = 0; i < fieldSyms.count(); i++) { Symbol sym = (Symbol)fieldSyms.nth(i); LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false, false); fmap = fmap.assoc(sym, lb); closesvec[i * 2] = lb; closesvec[i * 2 + 1] = lb; } // Java TODO: inject __meta et al into closes - when? // use array map to preserve ctor order ret.Closes = new PersistentArrayMap(closesvec); ret.Fields = fmap; for (int i = fieldSyms.count() - 1; i >= 0 && (((Symbol)fieldSyms.nth(i)).Name.Equals("__meta") || ((Symbol)fieldSyms.nth(i)).Name.Equals("__extmap")); --i) ret.AltCtorDrops++; } // Java TODO: set up volatiles //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey))); IPersistentVector interfaces = PersistentVector.EMPTY; for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next()) { Type t = (Type)Compiler.Resolve((Symbol)s.first()); if (!t.IsInterface) throw new ParseException("only interfaces are supported, had: " + t.Name); interfaces = interfaces.cons(t); } Type superClass = typeof(Object); Dictionary<IPersistentVector, IList<MethodInfo>> overrideables; Dictionary<IPersistentVector, IList<MethodInfo>> explicits; GatherMethods(superClass, RT.seq(interfaces), out overrideables, out explicits); ret._methodMap = overrideables; GenContext context = Compiler.IsCompiling ? Compiler.CompilerContextVar.get() as GenContext : (ret.IsDefType ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true) : (Compiler.CompilerContextVar.get() as GenContext ?? Compiler.EvalContext)); GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString()); Type baseClass = ret.CompileBaseClass(genC, superClass, SeqToTypeArray(interfaces), frm); Symbol thisTag = Symbol.intern(null, baseClass.FullName); 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, Compiler.CompilerContextVar, genC )); if (ret.IsDefType) { Var.pushThreadBindings( RT.mapUniqueKeys( Compiler.MethodVar, null, Compiler.LocalEnvVar, ret.Fields, Compiler.CompileStubSymVar, Symbol.intern(null, tagName), Compiler.CompileStubClassVar, baseClass )); ret.HintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret.AltCtorDrops); } // now (methodname [args] body)* ret.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); IPersistentCollection methods = null; for (ISeq s = methodForms; s != null; s = RT.next(s)) { NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables, explicits); methods = RT.conj(methods, m); } ret.Methods = methods; ret.Keywords = (IPersistentMap)Compiler.KeywordsVar.deref(); ret.Vars = (IPersistentMap)Compiler.VarsVar.deref(); ret.Constants = (PersistentVector)Compiler.ConstantsVar.deref(); ret.ConstantsID = RT.nextID(); ret.KeywordCallsites = (IPersistentVector)Compiler.KeywordCallsitesVar.deref(); ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref(); ret.VarCallsites = (IPersistentSet)Compiler.VarCallsitesVar.deref(); } finally { if (ret.IsDefType) Var.popThreadBindings(); Var.popThreadBindings(); } // TOD: Really, the first baseclass here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call. // Might be able to flag baseclass classes and not try to convert, leading to a dynsite. ret.Compile(baseClass, baseClass, interfaces, false, genC); Compiler.RegisterDuplicateType(ret.CompiledType); return ret; }
internal void EmitLocal(CljILGen ilg, LocalBinding lb) { Type primType = lb.PrimitiveType; if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); // TODO: ONCEONLY? } else // FnMode.Light { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); } } else { if (lb.IsArg) { //int argOffset = IsStatic ? 1 : 0; //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else { ilg.Emit(OpCodes.Ldloc, lb.LocalVar); } if (primType != null) HostExpr.EmitBoxReturn(this, ilg, primType); } }
public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg) { Label?loopLabel = (Label)Compiler.LoopLabelVar.deref(); if (loopLabel == null) { throw new InvalidOperationException("Recur not in proper context."); } { for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); } else if (primt == typeof(long) && pt == typeof(int)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_I8); } else if (primt == typeof(double) && pt == typeof(float)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R8); } else if (primt == typeof(int) && pt == typeof(long)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.EmitCall(Compiler.Method_RT_intCast_long); } else if (primt == typeof(float) && pt == typeof(double)) { mpeArg.EmitUnboxed(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Conv_R4); } else { throw new ArgumentException(String.Format( "{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, (arg.HasClrType ? arg.ClrType.Name : "Object"), primt.Name)); } } else { arg.Emit(RHC.Expression, objx, ilg); } } } for (int i = _loopLocals.count() - 1; i >= 0; i--) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); //Type primt = lb.PrimitiveType; if (lb.IsArg) { //ilg.Emit(OpCodes.Starg, lb.Index - (objx.IsStatic ? 0 : 1)); ilg.EmitStoreArg(lb.Index); } else { ilg.Emit(OpCodes.Stloc, lb.LocalVar); } } ilg.Emit(OpCodes.Br, loopLabel.Value); }
internal static LocalBinding RegisterLocal(Symbol sym, Symbol tag, Expr init) { int num = GetAndIncLocalNum(); LocalBinding b = new LocalBinding(num,sym, tag, init); IPersistentMap localsMap = (IPersistentMap)LOCAL_ENV.deref(); LOCAL_ENV.set(RT.assoc(localsMap,b.Symbol, b)); FnMethod method = (FnMethod)METHODS.deref(); method.Locals = (IPersistentMap)RT.assoc(method.Locals,b, b); method.IndexLocals = (IPersistentMap)RT.assoc(method.IndexLocals, num, b); return b; }
private static LocalBinding RegisterLocalInternal(Symbol sym, Symbol tag, Expr init, bool isThis, bool isArg, bool isByRef) { int num = GetAndIncLocalNum(); LocalBinding b = new LocalBinding(num, sym, tag, init, isThis, isArg, isByRef); IPersistentMap localsMap = (IPersistentMap)LocalEnvVar.deref(); LocalEnvVar.set(RT.assoc(localsMap, b.Symbol, b)); ObjMethod method = (ObjMethod)MethodVar.deref(); method.AddLocal(num, b); return b; }
internal static ObjExpr Build( IPersistentVector interfaceSyms, IPersistentVector fieldSyms, Symbol thisSym, string tagName, Symbol className, Symbol typeTag, ISeq methodForms, Object frm) { NewInstanceExpr ret = new NewInstanceExpr(null); ret._src = frm; ret._name = className.ToString(); ret._classMeta = GenInterface.ExtractAttributes(RT.meta(className)); ret.InternalName = ret.Name; // ret.Name.Replace('.', '/'); // Java: ret.objtype = Type.getObjectType(ret.internalName); if (thisSym != null) ret._thisName = thisSym.Name; if (fieldSyms != null) { IPersistentMap fmap = PersistentHashMap.EMPTY; object[] closesvec = new object[2 * fieldSyms.count()]; for (int i = 0; i < fieldSyms.count(); i++) { Symbol sym = (Symbol)fieldSyms.nth(i); LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false); fmap = fmap.assoc(sym, lb); closesvec[i * 2] = lb; closesvec[i * 2 + 1] = lb; } // Java TODO: inject __meta et al into closes - when? // use array map to preserve ctor order ret._closes = new PersistentArrayMap(closesvec); ret._fields = fmap; for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i) ret._altCtorDrops++; } // Java TODO: set up volatiles //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey))); IPersistentVector interfaces = PersistentVector.EMPTY; for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next()) { Type t = (Type)Compiler.Resolve((Symbol)s.first()); if (!t.IsInterface) throw new ArgumentException("only interfaces are supported, had: " + t.Name); interfaces = interfaces.cons(t); } Type superClass = typeof(Object); Dictionary<IPersistentVector, List<MethodInfo>> overrideables; GatherMethods(superClass, RT.seq(interfaces), out overrideables); ret._methodMap = overrideables; //string[] inames = InterfaceNames(interfaces); Type stub = CompileStub(superClass, ret, SeqToTypeArray(interfaces),frm); Symbol thisTag = Symbol.intern(null, stub.FullName); //Symbol stubTag = Symbol.intern(null,stub.FullName); //Symbol thisTag = Symbol.intern(null, tagName); // Needs its own GenContext so it has its own DynInitHelper // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition GenContext context = Compiler.COMPILER_CONTEXT.get() as GenContext ?? (ret.IsDefType ? new GenContext("deftype" + RT.nextID().ToString(),".dll",".",true) : Compiler.EvalContext); GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString()); //genC.FnCompileMode = FnMode.Full; 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, PersistentVector.EMPTY, Compiler.COMPILER_CONTEXT, genC )); if (ret.IsDefType) { Var.pushThreadBindings( RT.map( Compiler.METHOD, null, Compiler.LOCAL_ENV, ret._fields, Compiler.COMPILE_STUB_SYM, Symbol.intern(null, tagName), Compiler.COMPILE_STUB_CLASS, stub )); } // now (methodname [args] body)* // TODO: SourceLocation? //ret.line = (Integer)LINE.deref(); IPersistentCollection methods = null; for (ISeq s = methodForms; s != null; s = RT.next(s)) { NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables); methods = RT.conj(methods, m); } ret._methods = methods; ret.Keywords = (IPersistentMap)Compiler.KEYWORDS.deref(); ret.Vars = (IPersistentMap)Compiler.VARS.deref(); ret.Constants = (PersistentVector)Compiler.CONSTANTS.deref(); ret._constantsID = RT.nextID(); ret.KeywordCallsites = (IPersistentVector)Compiler.KEYWORD_CALLSITES.deref(); ret.ProtocolCallsites = (IPersistentVector)Compiler.PROTOCOL_CALLSITES.deref(); ret.VarCallsites = (IPersistentVector)Compiler.VAR_CALLSITES.deref(); } finally { if (ret.IsDefType) Var.popThreadBindings(); Var.popThreadBindings(); } ret.Compile(stub, interfaces, false, genC); Compiler.RegisterDuplicateType(ret.CompiledType); return ret; }
internal static FnMethod Parse(FnExpr fn, ISeq form, object retTag) { // ([args] body ... ) IPersistentVector parms = (IPersistentVector)RT.first(form); ISeq body = RT.next(form); try { FnMethod method = new FnMethod(fn, (ObjMethod)Compiler.MethodVar.deref()); method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); Var.pushThreadBindings(RT.mapUniqueKeys( Compiler.MethodVar, method, Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.LoopLocalsVar, null, Compiler.NextLocalNumVar, 0)); method._prim = PrimInterface(parms); //if (method._prim != null) // method._prim = method._prim.Replace('.', '/'); if (retTag is String) { retTag = Symbol.intern(null, (string)retTag); } if (!(retTag is Symbol)) { retTag = null; } if (retTag != null) { string retStr = ((Symbol)retTag).Name; if (!(retStr.Equals("long") || retStr.Equals("double"))) { retTag = null; } } method._retType = Compiler.TagType(Compiler.TagOf(parms) ?? retTag); if (method._retType.IsPrimitive) { if (!(method._retType == typeof(double) || method._retType == typeof(long))) { throw new ParseException("Only long and double primitives are supported"); } } else { method._retType = typeof(object); } // register 'this' as local 0 Compiler.RegisterLocalThis(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null); ParamParseState paramState = ParamParseState.Required; IPersistentVector argLocals = PersistentVector.EMPTY; List <Type> argTypes = new List <Type>(); int parmsCount = parms.count(); for (int i = 0; i < parmsCount; i++) { if (!(parms.nth(i) is Symbol)) { throw new ParseException("fn params must be Symbols"); } Symbol p = (Symbol)parms.nth(i); if (p.Namespace != null) { throw new ParseException("Can't use qualified name as parameter: " + p); } if (p.Equals(Compiler.AmpersandSym)) { if (paramState == ParamParseState.Required) { paramState = ParamParseState.Rest; } else { throw new ParseException("Invalid parameter list"); } } else { Type pt = Compiler.PrimType(Compiler.TagType(Compiler.TagOf(p))); if (pt.IsPrimitive && !(pt == typeof(double) || pt == typeof(long))) { throw new ParseException("Only long and double primitives are supported: " + p); } if (paramState == ParamParseState.Rest && Compiler.TagOf(p) != null) { throw new ParseException("& arg cannot have type hint"); } if (paramState == ParamParseState.Rest && method.Prim != null) { throw new ParseException("fns taking primitives cannot be variadic"); } if (paramState == ParamParseState.Rest) { pt = typeof(ISeq); } argTypes.Add(pt); LocalBinding b = pt.IsPrimitive ? Compiler.RegisterLocal(p, null, new MethodParamExpr(pt), pt, true) : Compiler.RegisterLocal(p, paramState == ParamParseState.Rest ? Compiler.ISeqSym : Compiler.TagOf(p), null, pt, true); argLocals = argLocals.cons(b); switch (paramState) { case ParamParseState.Required: method._reqParms = method._reqParms.cons(b); break; case ParamParseState.Rest: method._restParm = b; paramState = ParamParseState.Done; break; default: throw new ParseException("Unexpected parameter"); } } } if (method.RequiredArity > Compiler.MaxPositionalArity) { throw new ParseException(string.Format("Can't specify more than {0} parameters", Compiler.MaxPositionalArity)); } Compiler.LoopLocalsVar.set(argLocals); method.ArgLocals = argLocals; method._argTypes = argTypes.ToArray(); method.Body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body); return(method); } finally { Var.popThreadBindings(); } }
internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb) { if (Closes.containsKey(lb)) { if (_fnMode == FnMode.Full) { ilg.Emit(OpCodes.Ldarg_0); // this FieldBuilder fb = _closedOverFieldsMap[lb]; ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Ldfld, fb); } else { ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Castclass, typeof(IFnClosure)); ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure); ilg.EmitFieldGet(Compiler.Field_Closure_Locals); ilg.EmitInt(lb.Index); ilg.EmitLoadElement(typeof(Object)); if (lb.PrimitiveType != null) ilg.Emit(OpCodes.Unbox, lb.PrimitiveType); } } else if (lb.IsArg) { //int argOffset = IsStatic ? 0 : 1; //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset); ilg.EmitLoadArg(lb.Index); } else if (lb.IsThis) { ilg.EmitLoadArg(0); } else ilg.Emit(OpCodes.Ldloc, lb.LocalVar); }
internal Expression GenAssignLocal(GenContext context, LocalBinding lb, Expr val) { if (!IsMutable(lb)) throw new ArgumentException("Cannot assign to non-mutable: " + lb.Name); FieldBuilder fb; if ( _closedOverFieldsMap.TryGetValue(lb,out fb) ) return Expression.Assign(Expression.Field(_thisParam,_closedOverFieldsMap[lb]), val.GenCode(RHC.Expression,this,context)); return Expression.Assign(lb.ParamExpression, val.GenCode(RHC.Expression,this,context)); }
public void AddLocal(int index, LocalBinding lb) { Locals = (IPersistentMap)RT.assoc(Locals, lb, lb); IndexLocals = (IPersistentMap)RT.assoc(IndexLocals, index, lb); }
static void CloseOver(LocalBinding b, ObjMethod method) { if (b != null && method != null) { LocalBinding lb = (LocalBinding)RT.get(method.Locals, b); if (lb == null) { method.Objx.Closes = (IPersistentMap)RT.assoc(method.Objx.Closes, b, b); CloseOver(b, method.Parent); } else { if (lb.Index == 0) method.UsesThis = true; if (InCatchFinallyVar.deref() != null) { method.LocalsUsedInCatchFinally = (PersistentHashSet)method.LocalsUsedInCatchFinally.cons(b.Index); } } } }
internal bool IsVolatile(LocalBinding lb) { return RT.booleanCast(RT.contains(Fields, lb.Symbol)) && RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("volatile-mutable"))); }
static void CloseOver(LocalBinding b, FnMethod method) { if (b != null && method != null) { if (RT.get(method.Locals, b) == null) { method.Fn.Closes = (IPersistentMap)RT.assoc(method.Fn.Closes, b, b); CloseOver(b, method.Parent); } else if (IN_CATCH_FINALLY.deref() != null) { method.LocalsUsedInCatchFinally = (PersistentHashSet)method.LocalsUsedInCatchFinally.cons(b.Index); } } }
internal static ObjExpr Build( IPersistentVector interfaceSyms, IPersistentVector fieldSyms, Symbol thisSym, string tagName, Symbol className, Symbol typeTag, ISeq methodForms, Object frm) { NewInstanceExpr ret = new NewInstanceExpr(null); ret._src = frm; ret._name = className.ToString(); ret._classMeta = GenInterface.ExtractAttributes(RT.meta(className)); ret.InternalName = ret.Name; // ret.Name.Replace('.', '/'); // Java: ret.objtype = Type.getObjectType(ret.internalName); if (thisSym != null) { ret._thisName = thisSym.Name; } if (fieldSyms != null) { IPersistentMap fmap = PersistentHashMap.EMPTY; object[] closesvec = new object[2 * fieldSyms.count()]; for (int i = 0; i < fieldSyms.count(); i++) { Symbol sym = (Symbol)fieldSyms.nth(i); LocalBinding lb = new LocalBinding(-1, sym, null, new MethodParamExpr(Compiler.TagType(Compiler.TagOf(sym))), false, false); fmap = fmap.assoc(sym, lb); closesvec[i * 2] = lb; closesvec[i * 2 + 1] = lb; } // Java TODO: inject __meta et al into closes - when? // use array map to preserve ctor order ret._closes = new PersistentArrayMap(closesvec); ret._fields = fmap; for (int i = fieldSyms.count() - 1; i >= 0 && ((Symbol)fieldSyms.nth(i)).Name.StartsWith("__"); --i) { ret._altCtorDrops++; } } // Java TODO: set up volatiles //ret._volatiles = PersistentHashSet.create(RT.seq(RT.get(ret._optionsMap, volatileKey))); IPersistentVector interfaces = PersistentVector.EMPTY; for (ISeq s = RT.seq(interfaceSyms); s != null; s = s.next()) { Type t = (Type)Compiler.Resolve((Symbol)s.first()); if (!t.IsInterface) { throw new ParseException("only interfaces are supported, had: " + t.Name); } interfaces = interfaces.cons(t); } Type superClass = typeof(Object); Dictionary <IPersistentVector, List <MethodInfo> > overrideables; GatherMethods(superClass, RT.seq(interfaces), out overrideables); ret._methodMap = overrideables; //string[] inames = InterfaceNames(interfaces); Type stub = CompileStub(superClass, ret, SeqToTypeArray(interfaces), frm); Symbol thisTag = Symbol.intern(null, stub.FullName); //Symbol stubTag = Symbol.intern(null,stub.FullName); //Symbol thisTag = Symbol.intern(null, tagName); // Needs its own GenContext so it has its own DynInitHelper // Can't reuse Compiler.EvalContext if it is a DefType because we have to use the given name and will get a conflict on redefinition GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? (ret.IsDefType ? GenContext.CreateWithExternalAssembly("deftype" + RT.nextID().ToString(), ".dll", true) : Compiler.EvalContext); GenContext genC = context.WithNewDynInitHelper(ret.InternalName + "__dynInitHelper_" + RT.nextID().ToString()); //genC.FnCompileMode = FnMode.Full; try { Var.pushThreadBindings( RT.map( 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, Compiler.CompilerContextVar, genC )); if (ret.IsDefType) { Var.pushThreadBindings( RT.map( Compiler.MethodVar, null, Compiler.LocalEnvVar, ret._fields, Compiler.CompileStubSymVar, Symbol.intern(null, tagName), Compiler.CompileStubClassVar, stub )); ret._hintedFields = RT.subvec(fieldSyms, 0, fieldSyms.count() - ret._altCtorDrops); } // now (methodname [args] body)* // TODO: SourceLocation? //ret.line = (Integer)LINE.deref(); IPersistentCollection methods = null; for (ISeq s = methodForms; s != null; s = RT.next(s)) { NewInstanceMethod m = NewInstanceMethod.Parse(ret, (ISeq)RT.first(s), thisTag, overrideables); methods = RT.conj(methods, m); } ret.Methods = methods; ret.Keywords = (IPersistentMap)Compiler.KeywordsVar.deref(); ret.Vars = (IPersistentMap)Compiler.VarsVar.deref(); ret.Constants = (PersistentVector)Compiler.ConstantsVar.deref(); ret._constantsID = RT.nextID(); ret.KeywordCallsites = (IPersistentVector)Compiler.KeywordCallsitesVar.deref(); ret.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref(); ret.VarCallsites = (IPersistentSet)Compiler.VarCallsitesVar.deref(); } finally { if (ret.IsDefType) { Var.popThreadBindings(); } Var.popThreadBindings(); } // TOD: Really, the first stub here should be 'superclass' but can't handle hostexprs nested in method bodies -- reify method compilation takes place before this sucker is compiled, so can't replace the call. // Might be able to flag stub classes and not try to convert, leading to a dynsite. ret.Compile(stub, stub, interfaces, false, genC); Compiler.RegisterDuplicateType(ret.CompiledType); return(ret); }
public CatchClause(Type type, LocalBinding lb, Expr handler) { _type = type; _lb = lb; _handler = handler; }
public HostArg(ParameterType paramType, Expr argExpr, LocalBinding lb) { _paramType = paramType; _argExpr = argExpr; _localBinding = lb; }
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)); }
internal Expression GenUnboxedLocal(GenContext context, LocalBinding lb) { Type primType = lb.PrimitiveType; if (_closes.containsKey(lb) && _fnMode == FnMode.Full) return Expression.Convert(Expression.Field(_thisParam, lb.Name), primType); else return lb.ParamExpression; }
/*** * Current host interop uses reflection, which requires pre-existing classes * Work around this by: * Generate a stub class that has the same interfaces and fields as the class we are generating. * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc) * Unmunge the name (using a magic prefix) on any code gen for classes */ static Type CompileStub(Type super, NewInstanceExpr ret, Type[] interfaces, Object frm) { GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false); TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName, TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces); tb.DefineDefaultConstructor(MethodAttributes.Public); // instance fields for closed-overs for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next()) { LocalBinding lb = (LocalBinding)s.first(); FieldAttributes access = FieldAttributes.Public; // TODO: FIgure out Volatile if (!ret.IsVolatile(lb)) { access |= FieldAttributes.InitOnly; } if (lb.PrimitiveType != null) { tb.DefineField(lb.Name, lb.PrimitiveType, access); } else { tb.DefineField(lb.Name, typeof(Object), access); } } // ctor that takes closed-overs and does nothing if (ret.CtorTypes().Length > 0) { ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes()); ILGen ilg = new ILGen(cb.GetILGenerator()); ilg.EmitLoadArg(0); ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes)); ilg.Emit(OpCodes.Ret); if (ret._altCtorDrops > 0) { Type[] ctorTypes = ret.CtorTypes(); int newLen = ctorTypes.Length - ret._altCtorDrops; if (newLen > 0) { Type[] altCtorTypes = new Type[newLen]; for (int i = 0; i < altCtorTypes.Length; i++) { altCtorTypes[i] = ctorTypes[i]; } ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes); ILGen ilg2 = new ILGen(cb2.GetILGenerator()); ilg2.EmitLoadArg(0); for (int i = 0; i < newLen; i++) { ilg2.EmitLoadArg(i + 1); } for (int i = 0; i < ret._altCtorDrops; i++) { ilg2.EmitNull(); } ilg2.Emit(OpCodes.Call, cb); ilg2.Emit(OpCodes.Ret); } } } Type t = tb.CreateType(); Compiler.RegisterDuplicateType(t); return(t); }
public BindingInit(LocalBinding binding, Expr init) { _binding = binding; _init = init; }
internal bool IsVolatile(LocalBinding lb) { return(RT.booleanCast(RT.contains(Fields, lb.Symbol)) && RT.booleanCast(RT.get(lb.Symbol.meta(), Keyword.intern("volatile-mutable")))); }
internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val) { if (!IsMutable(lb)) throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name); FieldBuilder fb = null; bool hasField = _closedOverFieldsMap.TryGetValue(lb, out fb); ilg.Emit(OpCodes.Ldarg_0); // this Type primt = lb.PrimitiveType; if (primt != null) { MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr; if (!(mbe != null && mbe.CanEmitPrimitive)) throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name); mbe.EmitUnboxed(RHC.Expression, this, ilg); } else { val.Emit(RHC.Expression, this, ilg); } if (hasField) { ilg.MaybeEmitVolatileOp(IsVolatile(lb)); ilg.Emit(OpCodes.Stfld, fb); } else ilg.Emit(OpCodes.Stloc, lb.LocalVar); }
internal Expression GenLocal(GenContext context, LocalBinding lb) { if ( _fnMode == FnMode.Full ) { if (_closes.containsKey(lb)) { Expression expr = Expression.Field(_thisParam, lb.Name); Type primtType = lb.PrimitiveType; if (primtType != null) expr = Compiler.MaybeBox(Expression.Convert(expr, primtType)); return expr; } else return lb.ParamExpression; } else { return lb.ParamExpression; } }