private static void DefineMethod(TypeBuilder proxyTB, IPersistentVector sig) { string mname = (string)sig.nth(0); Type[] paramTypes = GenClass.CreateTypeArray((ISeq)sig.nth(1)); Type retType = (Type)sig.nth(2); MethodBuilder mb = proxyTB.DefineMethod(mname, MethodAttributes.Abstract | MethodAttributes.Public| MethodAttributes.Virtual, retType, paramTypes); }
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; }
internal static Expression[] GenTypedArgs(GenContext context, ParameterInfo[] parms, IPersistentVector args) { Expression[] exprs = new Expression[parms.Length]; for (int i = 0; i < parms.Length; i++) exprs[i] = GenTypedArg(context,parms[i].ParameterType, (Expr)args.nth(i)); return exprs; }
public static Expr Parse(IPersistentVector form) { IPersistentVector args = PersistentVector.EMPTY; for (int i = 0; i < form.count(); i++ ) args = (IPersistentVector)args.cons(Compiler.GenerateAST(form.nth(i),false)); Expr ret = new VectorExpr(args); return Compiler.OptionallyGenerateMetaInit(form, ret); }
public void AssocNChangesForBig() { Range r = new Range(2, 100000); PersistentVector v1 = PersistentVector.create((ISeq)r); IPersistentVector v2 = v1; for (int i = 0; i < 110000; i++) { v2 = v2.assocN(i, i + 20); } for (int i = 0; i < v1.count(); ++i) { Expect(v1.nth(i), EqualTo(i + 2)); } for (int i = 0; i < v2.count(); ++i) { Expect(v2.nth(i), EqualTo(i + 20)); } }
public static Expr Parse(ParserContext pcon, IPersistentVector form) { ParserContext pconToUse = pcon.EvalOrExpr(); 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); IObj iobjForm = form as IObj; if (iobjForm != null && iobjForm.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 static string PrimInterface(IPersistentVector arglist) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < arglist.count(); i++) { sb.Append(TypeChar(Compiler.TagOf(arglist.nth(i)))); } sb.Append(TypeChar(Compiler.TagOf(arglist))); string ret = sb.ToString(); bool prim = ret.Contains("L") || ret.Contains("D"); if (prim && arglist.count() > 4) { throw new ArgumentException("fns taking primitives support only 4 or fewer args"); } if (prim) { return("clojure.lang.primifs." + ret); } return(null); }
public static bool IsPrimInterface(IPersistentVector arglist) { if (arglist.count() > 4) { return(false); } for (int i = 0; i < arglist.count(); i++) { if (IsPrimType(Compiler.TagOf(arglist.nth(i)))) { return(true); } } if (IsPrimType(Compiler.TagOf(arglist))) { return(true); } return(false); }
public static Expr Parse(ParserContext pcon, IPersistentSet form) { ParserContext pconToUse = pcon.EvalOrExpr(); 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); IObj iobjForm = form as IObj; if (iobjForm != null && iobjForm.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 void AssocNChangesForBig() { ISeq r = LongRange.create(2, 100000); PersistentVector v1 = PersistentVector.create(r); IPersistentVector v2 = v1; for (int i = 0; i < 110000; i++) { v2 = v2.assocN(i, i + 20L); } for (int i = 0; i < v1.count(); ++i) { Expect((long)v1.nth(i)).To.Equal(i + 2L); } for (int i = 0; i < v2.count(); ++i) { object o = v2.nth(i); Expect(o).To.Be.An.Instance.Of <long>(); Expect((long)o).To.Equal(i + 20L); } }
public static Expr Parse(ParserContext pcon, IPersistentVector form) { ParserContext pconToUse = pcon.EvalOrExpr(); 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 iobjForm && iobjForm.meta() != null) { return(Compiler.OptionallyGenerateMetaInit(pcon, form, ret)); }
public object Eval() { try { IFn fn = (IFn)_fexpr.Eval(); IPersistentVector argvs = PersistentVector.EMPTY; for (int i = 0; i < _args.count(); i++) { argvs = (IPersistentVector)argvs.cons(((Expr)_args.nth(i)).Eval()); } return(fn.applyTo(RT.seq(Util.Ret1(argvs, argvs = null)))); } catch (Compiler.CompilerException) { throw; } catch (Exception e) { throw new Compiler.CompilerException(_source, Compiler.GetLineFromSpanMap(_spanMap), e); } }
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 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); }
static bool doEquiv(IPersistentVector v, object obj) { if (obj is IList || obj is IPersistentVector) { ICollection ma = (ICollection)obj; if (ma.Count != v.count()) return false; IEnumerator ima = ma.GetEnumerator(); foreach (object ov in ((IList)v)) { ima.MoveNext(); if (!Util.equiv(ov, ima.Current)) return false; } return true; } else { // Example in Java of Sequential / IPersistentCollection conflation //if (!(obj is Sequential)) // return false; //ISeq ms = ((IPersistentCollection)obj).seq(); ISeq ms = obj as ISeq; if (ms == null) { IPersistentCollection mc = obj as IPersistentCollection; if (mc == null) return false; ms = mc.seq(); } // Once we have the ISeq, we're ready to go. for (int i = 0; i < v.count(); i++, ms = ms.rest()) { if (ms == null || !Util.equiv(v.nth(i), ms.first())) return false; } if (ms != null) return false; } return true; }
static string[] InterfaceNames(IPersistentVector interfaces) { int icnt = interfaces.count(); string[] inames = icnt > 0 ? new string[icnt] : null; for (int i = 0; i < icnt; i++) inames[i] = SlashName((Type)interfaces.nth(i)); return inames; }
public void NthOutOfRangeLowFails() { IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3); Expect(v.nth(-4)).To.Equal(1); }
// There is a tremendous overlap between this and GenerateFnExpr+GenerateFnMethod. TODO: DRY it. private static LambdaExpression GenerateTypedDelegateExpression(Type delegateType, Symbol name, IPersistentVector parms, ISeq body) { // Create the form that is more or less correct ISeq form = (name == null) ? RT.cons(Compiler.FN, RT.cons(parms, body)) : RT.cons(Compiler.FN, RT.cons(name, RT.cons(parms, body))); FnDef fnDef = new FnDef(null); // compute tag from delegateType? fnDef.ComputeNames(form); MethodDef methodDef = new MethodDef(fnDef, (MethodDef)METHODS.deref()); try { LabelTarget loopLabel = Expression.Label(); Var.pushThreadBindings(PersistentHashMap.create( METHODS, methodDef, LOOP_LABEL, loopLabel, LOCAL_ENV, LOCAL_ENV.deref(), LOOP_LOCALS, null)); // register 'this' as local 0 LocalBinding thisB = RegisterLocal(Symbol.intern(fnDef.ThisName ?? "fn__" + RT.nextID()), null, null); thisB.ParamExpression = fnDef.ThisParam; IPersistentVector argLocals = PersistentVector.EMPTY; int parmsCount = parms.count(); ParamParseState paramState = ParamParseState.Required; for (int i = 0; i < parmsCount; i++) { if (!(parms.nth(i) is Symbol)) throw new ArgumentException("fn params must be Symbols"); Symbol p = parms.nth(i) as Symbol; if (p.Namespace != null) throw new Exception("Can't use qualified name as parameter: " + p); if (p.Equals(Compiler._AMP_)) { if (paramState == ParamParseState.Required) paramState = ParamParseState.Rest; else throw new Exception("Invalid parameter list"); } else { // TODO: Need more type inferencing to make this work. //LocalBinding b = RegisterLocal(p, paramState == ParamParseState.Rest ? ISEQ : TagOf(p), null); LocalBinding b = RegisterLocal(p, TagOf(p), null); argLocals = argLocals.cons(b); switch (paramState) { case ParamParseState.Required: methodDef.ReqParms = methodDef.ReqParms.cons(b); break; case ParamParseState.Rest: methodDef.RestParm = b; paramState = ParamParseState.Done; break; default: throw new Exception("Unexpected parameter"); } } } MethodInfo invokeMI = delegateType.GetMethod("Invoke"); Type returnType = invokeMI.ReturnType; ParameterInfo[] delParams = invokeMI.GetParameters(); bool isVariadic = (invokeMI.CallingConvention & CallingConventions.VarArgs) != 0; if (isVariadic != methodDef.IsVariadic) throw new ArgumentException("Arglist and delegate type must agree on being variadic."); if (delParams.Length != argLocals.count() ) throw new ArgumentException("Wrong number of parameters to generate typed delegate"); if (methodDef.NumParams > MAX_POSITIONAL_ARITY) throw new Exception(string.Format("Can't specify more than {0} parameters",MAX_POSITIONAL_ARITY)); LOOP_LOCALS.set(argLocals); methodDef.ArgLocals = argLocals; List<ParameterExpression> parmExprs = new List<ParameterExpression>(argLocals.count()); for (int i = 0; i < argLocals.count(); i++) { LocalBinding b = (LocalBinding)argLocals.nth(i); ParameterExpression pexpr = Expression.Parameter(delParams[i].ParameterType, b.Name); //asdf-tag b.ParamExpression = pexpr; parmExprs.Add(pexpr); } methodDef.Lambda = Expression.Lambda( delegateType, Expression.Block( Expression.Label(loopLabel), Expression.Convert(GenerateBodyExpr(body),returnType)), fnDef.Name, parmExprs); return methodDef.Lambda; } finally { Var.popThreadBindings(); } }
internal static Expression GenArgArray(GenContext context, IPersistentVector args) { Expression[] exprs = new Expression[args.count()]; for (int i = 0; i < args.count(); i++) { Expr arg = (Expr)args.nth(i); exprs[i] = Compiler.MaybeBox(arg.GenDlr(context)); } Expression argArray = Expression.NewArrayInit(typeof(object), exprs); return argArray; }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (CompiledType != null) { return(CompiledType); } string publicTypeName = IsDefType /* || (CanBeDirect && Compiler.IsCompiling) */ ? InternalName : InternalName + "__" + RT.nextID(); TypeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(TypeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) { TypeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } } ObjExpr.MarkAsSerializable(TypeBuilder); GenInterface.SetCustomAttributes(TypeBuilder, ClassMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(TypeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType, Compiler.CompilingDefTypeVar, true )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(TypeBuilder); EmitKeywordCallsiteDefs(TypeBuilder); DefineStaticConstructor(TypeBuilder); if (SupportsMeta) { MetaField = TypeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); } // If this IsDefType, then it has already emitted the closed-over fields on the base class. if (!IsDefType) { EmitClosedOverFields(TypeBuilder); } EmitProtocolCallsites(TypeBuilder); CtorInfo = EmitConstructor(TypeBuilder, superType); if (AltCtorDrops > 0) { EmitFieldOnlyConstructors(TypeBuilder, superType); } if (SupportsMeta) { EmitNonMetaConstructor(TypeBuilder, superType); EmitMetaFunctions(TypeBuilder); } EmitStatics(TypeBuilder); EmitMethods(TypeBuilder); CompiledType = TypeBuilder.CreateType(); if (context.DynInitHelper != null) { context.DynInitHelper.FinalizeType(); } CtorInfo = GetConstructorWithArgCount(CompiledType, CtorTypes().Length); return(CompiledType); } finally { if (IsDefType) { Var.popThreadBindings(); } } } finally { Var.popThreadBindings(); } }
static bool doEquiv(IPersistentVector v, object obj) { if (obj is IList || obj is IPersistentVector) { ICollection ma = (ICollection)obj; if (ma.Count != v.count()) return false; IEnumerator ima = ma.GetEnumerator(); foreach (object ov in ((IList)v)) { ima.MoveNext(); if (!Util.equiv(ov, ima.Current)) return false; } return true; } else { if (!(obj is Sequential)) return false; ISeq ms = RT.seq(obj); for (int i = 0; i < v.count(); i++, ms = ms.next()) { if (ms == null || !Util.equiv(v.nth(i), ms.first())) return false; } if (ms != null) return false; } return true; }
private static void DefineMethod(TypeBuilder proxyTB, IPersistentVector sig) { Symbol mname = (Symbol)sig.nth(0); Type[] paramTypes = GenClass.CreateTypeArray((ISeq)sig.nth(1)); Type retType = (Type)sig.nth(2); ISeq pmetas = (ISeq)(sig.count() >= 4 ? sig.nth(3) : null); MethodBuilder mb = proxyTB.DefineMethod(mname.Name, MethodAttributes.Abstract | MethodAttributes.Public| MethodAttributes.Virtual, retType, paramTypes); SetCustomAttributes(mb, GenInterface.ExtractAttributes(RT.meta(mname))); int i=1; for (ISeq s = pmetas; s != null; s = s.next(), i++) { IPersistentMap meta = GenInterface.ExtractAttributes((IPersistentMap)s.first()); if (meta != null && meta.count() > 0) { ParameterBuilder pb = mb.DefineParameter(i, ParameterAttributes.None, String.Format("p_{0}",i)); GenInterface.SetCustomAttributes(pb, meta); } } }
/// <summary> /// Compares an <see cref="IPersistentVector">IPersistentVector</see> to another object for equality. /// </summary> /// <param name="v">The <see cref="IPersistentVector">IPersistentVector</see> to compare.</param> /// <param name="obj">The other object to compare.</param> /// <returns><value>true</value> if the specified Object is equal to the current Object; /// otherwise, <value>false</value>. /// </returns> public static bool doEquals(IPersistentVector v, object obj) { if (obj is IList || obj is IPersistentVector) { IList ma = obj as IList; if (ma.Count != v.count() || ma.GetHashCode() != v.GetHashCode()) return false; for (int i = 0; i < v.count(); i++) { if (!Util.equals(v.nth(i), ma[i])) return false; } return true; } else { if (!(obj is Sequential)) return false; ISeq ms = RT.seq(obj); for (int i = 0; i < v.count(); i++, ms = ms.next()) { if (ms == null || !Util.equals(v.nth(i), ms.first())) return false; } if (ms != null) return false; } return true; }
public static string PrimInterface(IPersistentVector arglist) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < arglist.count(); i++) sb.Append(TypeChar(Compiler.TagOf(arglist.nth(i)))); sb.Append(TypeChar(Compiler.TagOf(arglist))); string ret = sb.ToString(); bool prim = ret.Contains("L") || ret.Contains("D"); if (prim && arglist.count() > 4) throw new ArgumentException("fns taking primitives support only 4 or fewer args"); if (prim) return "clojure.lang.primifs." + ret; return null; }
public static bool IsPrimInterface(IPersistentVector arglist) { if (arglist.count() > 4) return false; for (int i = 0; i < arglist.count(); i++) if (IsPrimType(Compiler.TagOf(arglist.nth(i)))) return true; if (IsPrimType(Compiler.TagOf(arglist))) return true; return false; }
public static NewInstanceMethod Parse(ObjExpr objx, ISeq form, Symbol thisTag, Dictionary <IPersistentVector, IList <MethodInfo> > overrideables, Dictionary <IPersistentVector, IList <MethodInfo> > explicits) { // (methodname [this-name args*] body...) // this-name might be nil NewInstanceMethod method = new NewInstanceMethod(objx, (ObjMethod)Compiler.MethodVar.deref()); Symbol dotName = (Symbol)RT.first(form); Symbol name; string methodName; int idx = dotName.Name.LastIndexOf("."); if (idx >= 0) { // we have an explicit interface implementation string dotNameStr = dotName.Name; string interfaceName = dotNameStr.Substring(0, idx); method.ExplicitInterface = RT.classForName(interfaceName); if (method.ExplicitInterface == null) { throw new ParseException(String.Format("Unable to find interface {0} for explicit method implemntation: {1}", interfaceName, dotNameStr)); } methodName = dotNameStr.Substring(idx + 1); name = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName)); } else { name = (Symbol)Symbol.intern(null, Compiler.munge(dotName.Name)).withMeta(RT.meta(dotName)); methodName = name.Name; } IPersistentVector parms = (IPersistentVector)RT.second(form); if (parms.count() == 0 || !(parms.nth(0) is Symbol)) { throw new ParseException("Must supply at least one argument for 'this' in: " + dotName); } Symbol thisName = (Symbol)parms.nth(0); parms = RT.subvec(parms, 1, parms.count()); ISeq body = RT.next(RT.next(form)); try { method.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref(); // register as the current method and set up a new env frame // PathNode pnade = new PathNode(PATHTYPE.PATH, (PathNode) CLEAR_PATH.get()); Var.pushThreadBindings( RT.mapUniqueKeys( Compiler.MethodVar, method, Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.LoopLocalsVar, null, Compiler.NextLocalNumVar, 0 // CLEAR_PATH, pnode, // CLEAR_ROOT, pnode, // CLEAR_SITES, PersistentHashMap.EMPTY )); // register 'this' as local 0 //method._thisBinding = Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null); Compiler.RegisterLocalThis(((thisName == null) ? dummyThis : thisName), thisTag, null); IPersistentVector argLocals = PersistentVector.EMPTY; method._retType = Compiler.TagType(Compiler.TagOf(name)); method._argTypes = new Type[parms.count()]; bool hinted = Compiler.TagOf(name) != null; Type[] pTypes = new Type[parms.count()]; Symbol[] pSyms = new Symbol[parms.count()]; bool[] pRefs = new bool[parms.count()]; for (int i = 0; i < parms.count(); i++) { // Param should be symbol or (by-ref symbol) Symbol p; bool isByRef = false; object pobj = parms.nth(i); if (pobj is Symbol) { p = (Symbol)pobj; } else if (pobj is ISeq) { ISeq pseq = (ISeq)pobj; object first = RT.first(pseq); object second = RT.second(pseq); if (!(first is Symbol && ((Symbol)first).Equals(HostExpr.ByRefSym))) { throw new ParseException("First element in parameter pair must be by-ref"); } if (!(second is Symbol)) { throw new ParseException("Params must be Symbols"); } isByRef = true; p = (Symbol)second; hinted = true; } else { throw new ParseException("Params must be Symbols or of the form (by-ref Symbol)"); } object tag = Compiler.TagOf(p); if (tag != null) { hinted = true; } if (p.Namespace != null) { p = Symbol.intern(p.Name); } Type pType = Compiler.TagType(tag); if (isByRef) { pType = pType.MakeByRefType(); } pTypes[i] = pType; pSyms[i] = p; pRefs[i] = isByRef; } Dictionary <IPersistentVector, IList <MethodInfo> > matches = method.IsExplicit ? FindMethodsWithNameAndArity(method.ExplicitInterface, methodName, parms.count(), overrideables, explicits) : FindMethodsWithNameAndArity(methodName, parms.count(), overrideables); IPersistentVector mk = MSig(methodName, pTypes, method._retType); IList <MethodInfo> ms = null; if (matches.Count > 0) { // multiple matches if (matches.Count > 1) { // must be hinted and match one method if (!hinted) { throw new ParseException("Must hint overloaded method: " + name.Name); } if (!matches.TryGetValue(mk, out ms)) { throw new ParseException("Can't find matching overloaded method: " + name.Name); } method._minfos = ms; } else // one match { // if hinted, validate match, if (hinted) { if (!matches.TryGetValue(mk, out ms)) { throw new ParseException("Can't find matching method: " + name.Name + ", leave off hints for auto match."); } method._minfos = ms; //if (m.ReturnType != method._retType) // throw new ArgumentException(String.Format("Mismatched return type: {0}, expected {1}, had: {2}", // name.Name, m.ReturnType.Name, method._retType.Name)); } else // adopt found method sig { using (var e = matches.GetEnumerator()) { e.MoveNext(); mk = e.Current.Key; ms = e.Current.Value; } MethodInfo m = ms[0]; method._retType = m.ReturnType; pTypes = Compiler.GetTypes(m.GetParameters()); method._minfos = ms; } } } else { throw new ParseException("Can't define method not in interfaces: " + name.Name); } if (method.IsExplicit) { method.ExplicitMethodInfo = ms[0]; } // validate unique name + arity among additional methods for (int i = 0; i < parms.count(); i++) { LocalBinding lb = Compiler.RegisterLocal(pSyms[i], null, new MethodParamExpr(pTypes[i]), true, pRefs[i]); argLocals = argLocals.assocN(i, lb); method._argTypes[i] = pTypes[i]; } Compiler.LoopLocalsVar.set(argLocals); method._name = name.Name; method.MethodMeta = GenInterface.ExtractAttributes(RT.meta(name)); method.Parms = parms; method.ArgLocals = argLocals; method.Body = (new BodyExpr.Parser()).Parse(new ParserContext(RHC.Return), body); return(method); } finally { Var.popThreadBindings(); } }
public Expr Parse(object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LOOP); IPersistentVector bindings = RT.second(form) as IPersistentVector; if (bindings == null) { throw new ArgumentException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ArgumentException("Bad binding form, expected matched symbol/value pairs."); } ISeq body = RT.next(RT.next(form)); // TODO: This is one place where context makes a difference. Need to figure this out. // Second test clause added in Rev 1216. // if (ctxt == C.EVAL || (context == c.EXPRESSION && isLoop)) // return Generate(RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form))); // As of Rev 1216, I tried tjos out. // However, it goes into an infinite loop. Still need to figure this out. //if (isLoop) // Generate(RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form))); IPersistentMap dynamicBindings = RT.map( Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.NEXT_LOCAL_NUM, Compiler.NEXT_LOCAL_NUM.deref()); if (isLoop) { dynamicBindings = dynamicBindings.assoc(Compiler.LOOP_LOCALS, null); } try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) { throw new ArgumentException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new Exception("Can't let qualified name: " + sym); } Expr init = Compiler.GenerateAST(bindings.nth(i + 1)); // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) { loopLocals = loopLocals.cons(b); } } if (isLoop) { Compiler.LOOP_LOCALS.set(loopLocals); } return(new LetExpr(bindingInits, new BodyExpr.Parser().Parse(body), isLoop)); } finally { Var.popThreadBindings(); } }
//(case* expr shift mask default map<minhash, [test then]> table-type test-type skip-check?) //prepared by case macro and presumed correct //case macro binds actual expr in let so expr is always a local, //no need to worry about multiple evaluation public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "case__" + RT.nextID())); } IPersistentVector args = LazilyPersistentVector.create(form.next()); object exprForm = args.nth(0); int shift = Util.ConvertToInt(args.nth(1)); int mask = Util.ConvertToInt(args.nth(2)); object defaultForm = args.nth(3); IPersistentMap caseMap = (IPersistentMap)args.nth(4); Keyword switchType = (Keyword)args.nth(5); Keyword testType = (Keyword)args.nth(6); IPersistentSet skipCheck = RT.count(args) < 8 ? null : (IPersistentSet)args.nth(7); ISeq keys = RT.keys(caseMap); int low = Util.ConvertToInt(RT.first(keys)); int high = Util.ConvertToInt(RT.nth(keys, RT.count(keys) - 1)); LocalBindingExpr testexpr = (LocalBindingExpr)Compiler.Analyze(pcon.SetRhc(RHC.Expression), exprForm); SortedDictionary <int, Expr> tests = new SortedDictionary <int, Expr>(); Dictionary <int, Expr> thens = new Dictionary <int, Expr>(); foreach (IMapEntry me in caseMap) { int minhash = Util.ConvertToInt(me.key()); object pair = me.val(); // [test-val then-expr] object first = RT.first(pair); Expr testExpr = testType == _intKey ? NumberExpr.Parse(Util.ConvertToInt(first)) : (first == null ? Compiler.NilExprInstance : new ConstantExpr(first)); tests[minhash] = testExpr; Expr thenExpr; thenExpr = Compiler.Analyze(pcon, RT.second(pair)); thens[minhash] = thenExpr; } Expr defaultExpr; defaultExpr = Compiler.Analyze(pcon, defaultForm); return(new CaseExpr( (IPersistentMap)Compiler.SourceSpanVar.deref(), testexpr, shift, mask, low, high, defaultExpr, tests, thens, switchType, testType, skipCheck)); }
static public bool doEquals(IPersistentVector v, object obj) { if (v == obj) { return(true); } IPersistentVector ipv = obj as IPersistentVector; if (ipv != null) { if (ipv.count() != v.count()) { return(false); } for (int i = 0; i < v.count(); i++) { if (!Util.equals(v.nth(i), ipv.nth(i))) { return(false); } } return(true); } IList ilist = obj as IList; if (ilist != null) { if (ilist.Count != v.count()) // THis test in the JVM code can't be right: || ma.GetHashCode() != v.GetHashCode()) { return(false); } for (int i = 0; i < v.count(); i++) { if (!Util.equals(v.nth(i), ilist[i])) { return(false); } } return(true); } if (!(obj is Sequential)) { return(false); } ISeq ms = RT.seq(obj); for (int i = 0; i < v.count(); i++, ms = ms.next()) { if (ms == null || !Util.equals(v.nth(i), ms.first())) { return(false); } } if (ms != null) { return(false); } return(true); }
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); }
/// <summary> /// Gets the first item. /// </summary> /// <returns>The first item.</returns> public override object first() { return(_v.nth(_i)); }
MethodBuilder GenerateStaticMethod(ObjExpr objx, GenContext context) { string methodName = StaticMethodName; TypeBuilder tb = objx.TypeBuilder; List <ParameterExpression> parms = new List <ParameterExpression>(_argLocals.count() + 1); List <Type> parmTypes = new List <Type>(_argLocals.count() + 1); ParameterExpression thisParm = Expression.Parameter(objx.BaseType, "this"); if (_thisBinding != null) { _thisBinding.ParamExpression = thisParm; _thisBinding.Tag = Symbol.intern(null, objx.BaseType.FullName); } objx.ThisParam = thisParm; parms.Add(thisParm); parmTypes.Add(objx.BaseType); try { LabelTarget loopLabel = Expression.Label("top"); Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this)); Type[] argTypes = StaticMethodArgTypes; for (int i = 0; i < _argLocals.count(); i++) { LocalBinding lb = (LocalBinding)_argLocals.nth(i); ParameterExpression parm = Expression.Parameter(argTypes[i], lb.Name); lb.ParamExpression = parm; parms.Add(parm); parmTypes.Add(argTypes[i]); } Expression body = Expression.Block( //maybeLoadVarsExpr, Expression.Label(loopLabel), GenBodyCode(StaticReturnType, objx, context)); //Expression convBody = Compiler.MaybeConvert(body, ReturnType); Expression convBody = HostExpr.GenUnboxArg(body, StaticReturnType); LambdaExpression lambda = Expression.Lambda(convBody, parms); // JVM: Clears locals here. // TODO: Cache all the CreateObjectTypeArray values MethodBuilder mb = tb.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, StaticReturnType, parmTypes.ToArray()); //Console.Write("StMd: {0} {1}(", ReturnType.Name, methodName); //foreach (Type t in parmTypes) // Console.Write("{0}, ", t.Name); //Console.WriteLine(")"); lambda.CompileToMethod(mb, context.IsDebuggable); _staticMethodBuilder = mb; return(mb); } finally { Var.popThreadBindings(); } }
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; }
private static Expression GenerateVectorExpr(IPersistentVector v) { int n = v.count(); Expression[] args = new Expression[v.count()]; for (int i = 0; i < n; i++) args[i] = Generate(v.nth(i)); Expression arrayExpr = Expression.NewArrayInit(typeof(object), MaybeBox(args)); Expression ret = Expression.Call(Method_RT_vector, arrayExpr); ret = OptionallyGenerateMetaInit(v,ret); return ret; }
object DrawStaticWidget(object key, object val) { if (val is string) { return(EditorGUILayout.TextField(key.ToString(), (string)val)); } else if (val is bool) { return(EditorGUILayout.Toggle(key.ToString(), (bool)val)); } else if (val is int) { return(EditorGUILayout.IntField(key.ToString(), (int)val)); } else if (val is long) { return(EditorGUILayout.IntField(key.ToString(), (int)(long)val)); } else if (val is Vector2) { return(EditorGUILayout.Vector2Field(key.ToString(), (Vector2)val)); } else if (val is Vector3) { return(EditorGUILayout.Vector3Field(key.ToString(), (Vector3)val)); } else if (val is Vector4) { return(EditorGUILayout.Vector4Field(key.ToString(), (Vector4)val)); } else if (val is float) { return(EditorGUILayout.FloatField(key.ToString(), (float)val)); } else if (val is double) { return(EditorGUILayout.FloatField(key.ToString(), (float)(double)val)); } else if (val is Symbol) { return(Symbol.intern(EditorGUILayout.TextField(key.ToString(), val.ToString()))); } else if (val is Keyword) { return(Keyword.intern(EditorGUILayout.TextField(key.ToString(), ((Keyword)val).ToString().Substring(1)))); } else if (val is IPersistentMap) { IPersistentMap map = val as IPersistentMap; EditorGUILayout.LabelField(key.ToString(), "{"); EditorGUI.indentLevel++; foreach (var entry in map) { map = map.assoc(entry.key(), DrawStaticWidget(entry.key(), entry.val())); } // EditorGUILayout.LabelField("", "}"); EditorGUI.indentLevel--; return(map); } else if (val is IPersistentVector) { IPersistentVector vector = val as IPersistentVector; EditorGUILayout.LabelField(key.ToString(), "["); EditorGUI.indentLevel++; for (int i = 0; i < vector.count(); i++) { vector = vector.assocN(i, DrawStaticWidget(i.ToString(), vector.nth(i))); } // EditorGUILayout.LabelField("", "]"); EditorGUI.indentLevel--; return(vector); } else { EditorGUILayout.LabelField(key.ToString(), "val.GetType().ToString()"); return(val); } }
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(); } }
public Expr Parse(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 ArgumentException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ArgumentException("Bad binding form, expected matched symbol/value pairs."); } ISeq body = RT.next(RT.next(form)); // TODO: This is one place where context makes a difference. Need to figure this out. // if (ctxt == C.EVAL) // return Generate(RT.list(RT.list(Compiler.FN, PersistentVector.EMPTY, form))); IPersistentMap dynamicBindings = RT.map( Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.NEXT_LOCAL_NUM, Compiler.NEXT_LOCAL_NUM.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 ArgumentException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new Exception("Can't let qualified name: " + sym); } LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), null); 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.GenerateAST(bindings.nth(i + 1), sym.Name); // Sequential enhancement of env (like Lisp let*) 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(body))); } finally { Var.popThreadBindings(); } }
/// <summary> /// Compares an <see cref="IPersistentVector">IPersistentVector</see> to another object for equality. /// </summary> /// <param name="v">The <see cref="IPersistentVector">IPersistentVector</see> to compare.</param> /// <param name="obj">The other object to compare.</param> /// <returns><value>true</value> if the specified Object is equal to the current Object; /// otherwise, <value>false</value>. /// </returns> public static bool doEquals(IPersistentVector v, object obj) { if ( obj is IList || obj is IPersistentVector ) { IList ma = obj as IList; if (ma.Count != v.count() || ma.GetHashCode() != v.GetHashCode()) return false; for ( int i=0; i<v.count(); i++ ) { if (!Util.equals(v.nth(i), ma[i])) return false; } return true; } // Example in original code of Sequential/IPersistentVector conflation. //if(!(obj instanceof Sequential)) // return false; // ISeq ms = ((IPersistentCollection) obj).seq(); // for(int i = 0; i < v.count(); i++, ms = ms.rest()) // { // if(ms == null || !Util.equals(v.nth(i), ms.first())) // return false; // } // if(ms != null) // return false; // } //return true; ISeq ms = obj as ISeq; if (ms == null) { IPersistentCollection mc = obj as IPersistentCollection; if (mc == null) return false; ms = mc.seq(); } // Once we have the ISeq, we're ready to go. for (int i = 0; i < v.count(); i++, ms = ms.rest()) { if (ms == null || !Util.equals(v.nth(i), ms.first())) return false; } if (ms != null) return false; return true; }
internal static FnMethod Parse(FnExpr fn, ISeq form) { // ([args] body ... ) IPersistentVector parms = (IPersistentVector)RT.first(form); ISeq body = RT.next(form); try { FnMethod method = new FnMethod(fn, (FnMethod)Compiler.METHODS.deref()); // TODO: method.line = (Integer) LINE.deref(); Var.pushThreadBindings(RT.map( Compiler.METHODS, method, Compiler.LOCAL_ENV, Compiler.LOCAL_ENV.deref(), Compiler.LOOP_LOCALS, null, Compiler.NEXT_LOCAL_NUM, 0)); // register 'this' as local 0 method._thisBinding = Compiler.RegisterLocal(Symbol.intern(fn.ThisName ?? "fn__" + RT.nextID()), null, null); ParamParseState paramState = ParamParseState.Required; IPersistentVector argLocals = PersistentVector.EMPTY; int parmsCount = parms.count(); for (int i = 0; i < parmsCount; i++) { if (!(parms.nth(i) is Symbol)) { throw new ArgumentException("fn params must be Symbols"); } Symbol p = (Symbol)parms.nth(i); if (p.Namespace != null) { throw new Exception("Can't use qualified name as parameter: " + p); } if (p.Equals(Compiler._AMP_)) { if (paramState == ParamParseState.Required) { paramState = ParamParseState.Rest; } else { throw new Exception("Invalid parameter list"); } } else { LocalBinding b = Compiler.RegisterLocal(p, paramState == ParamParseState.Rest ? Compiler.ISEQ : Compiler.TagOf(p), null); // asdf-tag 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 Exception("Unexpected parameter"); } } } if (method.NumParams > Compiler.MAX_POSITIONAL_ARITY) { throw new Exception(string.Format("Can't specify more than {0} parameters", Compiler.MAX_POSITIONAL_ARITY)); } Compiler.LOOP_LOCALS.set(argLocals); method._argLocals = argLocals; method._body = (new BodyExpr.Parser()).Parse(body); return(method); } finally { Var.popThreadBindings(); } }
private static Type[] SeqToTypeArray(IPersistentVector interfaces) { Type[] types = new Type[interfaces.count()]; for (int i = 0; i < interfaces.count(); i++) types[i] = (Type)interfaces.nth(i); return types; }
public static void EmitTypedArgs(ObjExpr objx, CljILGen ilg, ParameterInfo[] parms, IPersistentVector args) { for (int i = 0; i < parms.Length; i++) EmitTypedArg(objx, ilg, parms[i].ParameterType, (Expr)args.nth(i)); }
public void NthOutOfRangeHighFails() { IPersistentVector v = LazilyPersistentVector.createOwning(1, 2, 3); Expect(v.nth(4), EqualTo(1)); }
internal static void EmitArgsAsArray(IPersistentVector args, ObjExpr objx, CljILGen ilg) { ilg.EmitInt(args.count()); ilg.Emit(OpCodes.Newarr, typeof(Object)); for (int i = 0; i < args.count(); i++) { ilg.Emit(OpCodes.Dup); ilg.EmitInt(i); ((Expr)args.nth(i)).Emit(RHC.Expression, objx, ilg); ilg.Emit(OpCodes.Stelem_Ref); } }
internal static Expression[] GenTypedArgs(ObjExpr objx, GenContext context, Type[] paramTypes, IPersistentVector args) { Expression[] exprs = new Expression[paramTypes.Length]; for (int i = 0; i < paramTypes.Length; i++) exprs[i] = GenTypedArg(objx, context, paramTypes[i], (Expr)args.nth(i)); return exprs; }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (_compiledType != null) return _compiledType; string publicTypeName = IsDefType || (_isStatic && Compiler.IsCompiling) ? InternalName : InternalName + "__" + RT.nextID(); _typeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(_typeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) _typeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } ObjExpr.MarkAsSerializable(_typeBuilder); GenInterface.SetCustomAttributes(_typeBuilder, _classMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(_typeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(_typeBuilder); EmitKeywordCallsiteDefs(_typeBuilder); DefineStaticConstructor(_typeBuilder); if (SupportsMeta) _metaField = _typeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); // If this IsDefType, then it has already emitted the closed-over fields on the base class. if ( ! IsDefType ) EmitClosedOverFields(_typeBuilder); EmitProtocolCallsites(_typeBuilder); _ctorInfo = EmitConstructor(_typeBuilder, superType); if (_altCtorDrops > 0) EmitFieldOnlyConstructor(_typeBuilder, superType); if (SupportsMeta) { EmitNonMetaConstructor(_typeBuilder, superType); EmitMetaFunctions(_typeBuilder); } EmitStatics(_typeBuilder); EmitMethods(_typeBuilder); //if (KeywordCallsites.count() > 0) // EmitSwapThunk(_typeBuilder); _compiledType = _typeBuilder.CreateType(); if (context.DynInitHelper != null) context.DynInitHelper.FinalizeType(); _ctorInfo = GetConstructorWithArgCount(_compiledType, CtorTypes().Length); return _compiledType; } finally { if (IsDefType) Var.popThreadBindings(); } } finally { Var.popThreadBindings(); } }
private static object[] GetCtorArgs(IPersistentVector v) { object[] args = new object[v.length()]; for (int i = 0; i < v.length(); i++) args[i] = v.nth(i); return args; }
public Expr Parse(ParserContext pcon, object frm) { ISeq form = (ISeq)frm; // form => (let [var1 val1 var2 val2 ... ] body ... ) // or (loop [var1 val1 var2 val2 ... ] body ... ) bool isLoop = RT.first(form).Equals(Compiler.LoopSym); if (!(RT.second(form) is IPersistentVector bindings)) { throw new ParseException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ParseException("Bad binding form, expected matched symbol/value pairs."); } ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval || (pcon.Rhc == RHC.Expression && isLoop)) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "let__" + RT.nextID())); } ObjMethod method = (ObjMethod)Compiler.MethodVar.deref(); IPersistentMap backupMethodLocals = method.Locals; IPersistentMap backupMethodIndexLocals = method.IndexLocals; IPersistentVector recurMismatches = PersistentVector.EMPTY; for (int i = 0; i < bindings.count() / 2; i++) { recurMismatches = recurMismatches.cons(false); } // may repeat once for each binding with a mismatch, return breaks while (true) { IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); method.SetLocals(backupMethodLocals, backupMethodIndexLocals); if (isLoop) { dynamicBindings = dynamicBindings.assoc(Compiler.LoopLocalsVar, null); } try { Var.pushThreadBindings(dynamicBindings); IPersistentVector bindingInits = PersistentVector.EMPTY; IPersistentVector loopLocals = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) { throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new ParseException("Can't let qualified name: " + sym); } Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression).SetAssign(false), bindings.nth(i + 1), sym.Name); if (isLoop) { if (recurMismatches != null && RT.booleanCast(recurMismatches.nth(i / 2))) { HostArg ha = new HostArg(HostArg.ParameterType.Standard, init, null); List <HostArg> has = new List <HostArg>(1) { ha }; init = new StaticMethodExpr("", PersistentArrayMap.EMPTY, null, typeof(RT), "box", null, has, false); if (RT.booleanCast(RT.WarnOnReflectionVar.deref())) { RT.errPrintWriter().WriteLine("Auto-boxing loop arg: " + sym); } } else if (Compiler.MaybePrimitiveType(init) == typeof(int)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "longCast", null, args, false); } else if (Compiler.MaybePrimitiveType(init) == typeof(float)) { List <HostArg> args = new List <HostArg> { new HostArg(HostArg.ParameterType.Standard, init, null) }; init = new StaticMethodExpr("", null, null, typeof(RT), "doubleCast", null, args, false); } } // Sequential enhancement of env (like Lisp let*) LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), init, typeof(Object), false); BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); if (isLoop) { loopLocals = loopLocals.cons(b); } } if (isLoop) { Compiler.LoopLocalsVar.set(loopLocals); } Expr bodyExpr; bool moreMismatches = false; try { if (isLoop) { object methodReturnContext = pcon.Rhc == RHC.Return ? Compiler.MethodReturnContextVar.deref() : null; // stuff with clear paths, Var.pushThreadBindings(RT.map(Compiler.NoRecurVar, null, Compiler.MethodReturnContextVar, methodReturnContext)); } bodyExpr = new BodyExpr.Parser().Parse(isLoop ? pcon.SetRhc(RHC.Return) : pcon, body); } finally { if (isLoop) { Var.popThreadBindings(); for (int i = 0; i < loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)loopLocals.nth(i); if (lb.RecurMismatch) { recurMismatches = (IPersistentVector)recurMismatches.assoc(i, true); moreMismatches = true; } } } } if (!moreMismatches) { return(new LetExpr(bindingInits, bodyExpr, isLoop)); } } finally { Var.popThreadBindings(); } } }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (_compiledType != null) return _compiledType; string publicTypeName = IsDefType || (_isStatic && Compiler.IsCompiling) ? InternalName : InternalName + "__" + RT.nextID(); //Console.WriteLine("DefFn {0}, {1}", publicTypeName, context.AssemblyBuilder.GetName().Name); _typeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(_typeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) _typeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } ObjExpr.MarkAsSerializable(_typeBuilder); GenInterface.SetCustomAttributes(_typeBuilder, _classMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(_typeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(_typeBuilder); EmitKeywordCallsiteDefs(_typeBuilder); DefineStaticConstructor(_typeBuilder); if (SupportsMeta) _metaField = _typeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); EmitClosedOverFields(_typeBuilder); EmitProtocolCallsites(_typeBuilder); _ctorInfo = EmitConstructor(_typeBuilder, superType); if (_altCtorDrops > 0) EmitFieldOnlyConstructor(_typeBuilder, superType); if (SupportsMeta) { EmitNonMetaConstructor(_typeBuilder, superType); EmitMetaFunctions(_typeBuilder); } EmitStatics(_typeBuilder); EmitMethods(_typeBuilder); //if (KeywordCallsites.count() > 0) // EmitSwapThunk(_typeBuilder); _compiledType = _typeBuilder.CreateType(); if (context.DynInitHelper != null) context.DynInitHelper.FinalizeType(); // If we don't pick up the ctor after we finalize the type, // we sometimes get a ctor which is not a RuntimeConstructorInfo // This causes System.DynamicILGenerator.Emit(opcode,ContructorInfo) to blow up. // The error says the ConstructorInfo is null, but there is a second case in the code. // Thank heavens one can run Reflector on mscorlib. ConstructorInfo[] cis = _compiledType.GetConstructors(); foreach (ConstructorInfo ci in cis) { if (ci.GetParameters().Length == CtorTypes().Length) { _ctorInfo = ci; break; } } return _compiledType; } finally { if (IsDefType) Var.popThreadBindings(); } } finally { Var.popThreadBindings(); } }
private void GenerateFnClass(IPersistentVector interfaces, GenContext context) { string publicTypeName = IsDefType || (IsStatic && Compiler.IsCompiling) ? _internalName : _internalName + "__" + RT.nextID(); //Console.WriteLine("DefFn {0}, {1}", publicTypeName, context.AssemblyBuilder.GetName().Name); _typeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, _baseType, true); for (int i = 0; i < interfaces.count(); i++) _typeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); MarkAsSerializable(_typeBuilder); GenInterface.SetCustomAttributes(_typeBuilder, _classMeta); GenerateStaticConstructor(_typeBuilder, _baseType, context.IsDebuggable); _ctorInfo = GenerateConstructor(_typeBuilder, _baseType); if (_altCtorDrops > 0) GenerateFieldOnlyConstructor(_typeBuilder, _baseType); if (SupportsMeta) { _nonmetaCtorInfo = GenerateNonMetaConstructor(_typeBuilder, _baseType); } GenerateMetaFunctions(_typeBuilder); //GenerateReloadVarsMethod(_typeBuilder, context); // The incoming context holds info on the containing function. // That is the one that holds the closed-over variable values. //GenContext newContext = CreateContext(context, _typeBuilder, _baseType); //GenerateMethods(newContext); GenerateStatics(context); GenerateMethods(context); }
internal static Expression[] GenTypedArgArray(GenContext context, ParameterInfo[] infos, IPersistentVector args) { Expression[] exprs = new Expression[args.count()]; for (int i = 0; i < infos.Length; i++) { Expr e = (Expr)args.nth(i); // Java: this is in a try/catch, where the catch prints a stack trace if (MaybePrimitiveType(e) == infos[i].ParameterType) exprs[i] = ((MaybePrimitiveExpr)e).GenDlrUnboxed(context); else // Java follows this with: HostExpr.emitUnboxArg(fn, gen, parameterTypes[i]); //exprs[i] = e.GenDlr(context); exprs[i] = Expression.Convert(e.GenDlr(context), infos[i].ParameterType); ; } return exprs; }
protected void EmitValue(object value, CljILGen ilg) { bool partial = true; if (value == null) ilg.Emit(OpCodes.Ldnull); else if (value is String) ilg.Emit(OpCodes.Ldstr, (String)value); else if (value is Boolean) { ilg.EmitBoolean((Boolean)value); ilg.Emit(OpCodes.Box,typeof(bool)); } else if (value is Int32) { ilg.EmitInt((int)value); ilg.Emit(OpCodes.Box, typeof(int)); } else if (value is Int64) { ilg.EmitLong((long)value); ilg.Emit(OpCodes.Box, typeof(long)); } else if (value is Double) { ilg.EmitDouble((double)value); ilg.Emit(OpCodes.Box, typeof(double)); } else if (value is Char) { ilg.EmitChar((char)value); ilg.Emit(OpCodes.Box,typeof(char)); } else if (value is Type) { Type t = (Type)value; if (t.IsValueType) ilg.EmitType(t); else { //ilg.EmitString(Compiler.DestubClassName(((Type)value).FullName)); ilg.EmitString(((Type)value).FullName); ilg.EmitCall(Compiler.Method_RT_classForName); } } else if (value is Symbol) { Symbol sym = (Symbol)value; if (sym.Namespace == null) ilg.EmitNull(); else ilg.EmitString(sym.Namespace); ilg.EmitString(sym.Name); ilg.EmitCall(Compiler.Method_Symbol_intern2); } else if (value is Keyword) { Keyword keyword = (Keyword)value; if (keyword.Namespace == null) ilg.EmitNull(); else ilg.EmitString(keyword.Namespace); ilg.EmitString(keyword.Name); ilg.EmitCall(Compiler.Method_RT_keyword); } else if (value is Var) { Var var = (Var)value; ilg.EmitString(var.Namespace.Name.ToString()); ilg.EmitString(var.Symbol.Name.ToString()); ilg.EmitCall(Compiler.Method_RT_var2); } else if (value is IType) { IPersistentVector fields = (IPersistentVector)Reflector.InvokeStaticMethod(value.GetType(), "getBasis", Type.EmptyTypes); for (ISeq s = RT.seq(fields); s != null; s = s.next()) { Symbol field = (Symbol)s.first(); Type k = Compiler.TagType(Compiler.TagOf(field)); object val = Reflector.GetInstanceFieldOrProperty(value, Compiler.munge(field.Name)); EmitValue(val, ilg); if (k.IsPrimitive) { ilg.Emit(OpCodes.Castclass, k); } } ConstructorInfo cinfo = value.GetType().GetConstructors()[0]; ilg.EmitNew(cinfo); } else if (value is IRecord) { //MethodInfo[] minfos = value.GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); EmitValue(PersistentArrayMap.create((IDictionary)value), ilg); MethodInfo createMI = value.GetType().GetMethod("create", BindingFlags.Static | BindingFlags.Public, null, CallingConventions.Standard, new Type[] { typeof(IPersistentMap) }, null); ilg.EmitCall(createMI); } else if (value is IPersistentMap) { IPersistentMap map = (IPersistentMap)value; List<object> entries = new List<object>(map.count() * 2); foreach (IMapEntry entry in map) { entries.Add(entry.key()); entries.Add(entry.val()); } EmitListAsObjectArray(entries, ilg); ilg.EmitCall(Compiler.Method_RT_map); } else if (value is IPersistentVector) { IPersistentVector args = (IPersistentVector)value; if (args.count() <= Tuple.MAX_SIZE) { for (int i = 0; i < args.count(); i++) EmitValue(args.nth(i), ilg); ilg.Emit(OpCodes.Call, Compiler.Methods_CreateTuple[args.count()]); } else { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_RT_vector); } } else if (value is PersistentHashSet) { ISeq vs = RT.seq(value); if (vs == null) ilg.EmitFieldGet(Compiler.Method_PersistentHashSet_EMPTY); else { EmitListAsObjectArray(vs, ilg); ilg.EmitCall(Compiler.Method_PersistentHashSet_create); } } else if (value is ISeq || value is IPersistentList) { EmitListAsObjectArray(value, ilg); ilg.EmitCall(Compiler.Method_PersistentList_create); } else if (value is Regex) { ilg.EmitString(((Regex)value).ToString()); ilg.EmitNew(Compiler.Ctor_Regex_1); } else { string cs = null; try { cs = RT.printString(value); } catch (Exception) { throw new InvalidOperationException(String.Format("Can't embed object in code, maybe print-dup not defined: {0}", value)); } if (cs.Length == 0) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + value)); if (cs.StartsWith("#<")) throw new InvalidOperationException(String.Format("Can't embed unreadable object in code: " + cs)); ilg.EmitString(cs); ilg.EmitCall(Compiler.Method_RT_readString); partial = false; } if (partial) { if (value is IObj && RT.count(((IObj)value).meta()) > 0) { ilg.Emit(OpCodes.Castclass, typeof(IObj)); Object m = ((IObj)value).meta(); EmitValue(Compiler.ElideMeta(m), ilg); ilg.Emit(OpCodes.Castclass, typeof(IPersistentMap)); ilg.Emit(OpCodes.Callvirt, Compiler.Method_IObj_withMeta); } } }
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; // form => (letfn* [var1 (fn [args] body) ... ] body ... ) if (!(RT.second(form) is IPersistentVector bindings)) { throw new ParseException("Bad binding form, expected vector"); } if ((bindings.count() % 2) != 0) { throw new ParseException("Bad binding form, expected matched symbol/expression pairs."); } ISeq body = RT.next(RT.next(form)); if (pcon.Rhc == RHC.Eval) { return(Compiler.Analyze(pcon, RT.list(RT.list(Compiler.FnOnceSym, PersistentVector.EMPTY, form)), "letfn__" + RT.nextID())); } IPersistentMap dynamicBindings = RT.map( Compiler.LocalEnvVar, Compiler.LocalEnvVar.deref(), Compiler.NextLocalNumVar, Compiler.NextLocalNumVar.deref()); try { Var.pushThreadBindings(dynamicBindings); // pre-seed env (like Lisp labels) IPersistentVector lbs = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { if (!(bindings.nth(i) is Symbol)) { throw new ParseException("Bad binding form, expected symbol, got " + bindings.nth(i)); } Symbol sym = (Symbol)bindings.nth(i); if (sym.Namespace != null) { throw new ParseException("Can't let qualified name: " + sym); } LocalBinding b = Compiler.RegisterLocal(sym, Compiler.TagOf(sym), null, typeof(Object), false); // b.CanBeCleared = false; lbs = lbs.cons(b); } IPersistentVector bindingInits = PersistentVector.EMPTY; for (int i = 0; i < bindings.count(); i += 2) { Symbol sym = (Symbol)bindings.nth(i); Expr init = Compiler.Analyze(pcon.SetRhc(RHC.Expression), bindings.nth(i + 1), sym.Name); LocalBinding b = (LocalBinding)lbs.nth(i / 2); b.Init = init; BindingInit bi = new BindingInit(b, init); bindingInits = bindingInits.cons(bi); } return(new LetFnExpr(bindingInits, new BodyExpr.Parser().Parse(pcon, body))); } finally { Var.popThreadBindings(); } }
public Type Compile(Type superType, Type stubType, IPersistentVector interfaces, bool onetimeUse, GenContext context) { if (_compiledType != null) { return(_compiledType); } string publicTypeName = IsDefType || (_isStatic && Compiler.IsCompiling) ? InternalName : InternalName + "__" + RT.nextID(); //Console.WriteLine("DefFn {0}, {1}", publicTypeName, context.AssemblyBuilder.GetName().Name); _typeBuilder = context.AssemblyGen.DefinePublicType(publicTypeName, superType, true); context = context.WithNewDynInitHelper().WithTypeBuilder(_typeBuilder); Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, context)); try { if (interfaces != null) { for (int i = 0; i < interfaces.count(); i++) { _typeBuilder.AddInterfaceImplementation((Type)interfaces.nth(i)); } } ObjExpr.MarkAsSerializable(_typeBuilder); GenInterface.SetCustomAttributes(_typeBuilder, _classMeta); try { if (IsDefType) { Compiler.RegisterDuplicateType(_typeBuilder); Var.pushThreadBindings(RT.map( Compiler.CompileStubOrigClassVar, stubType )); //, //Compiler.COMPILE_STUB_CLASS, _baseType)); } EmitConstantFieldDefs(_typeBuilder); EmitKeywordCallsiteDefs(_typeBuilder); DefineStaticConstructor(_typeBuilder); if (SupportsMeta) { _metaField = _typeBuilder.DefineField("__meta", typeof(IPersistentMap), FieldAttributes.Public | FieldAttributes.InitOnly); } EmitClosedOverFields(_typeBuilder); EmitProtocolCallsites(_typeBuilder); _ctorInfo = EmitConstructor(_typeBuilder, superType); if (_altCtorDrops > 0) { EmitFieldOnlyConstructor(_typeBuilder, superType); } if (SupportsMeta) { EmitNonMetaConstructor(_typeBuilder, superType); EmitMetaFunctions(_typeBuilder); } EmitStatics(_typeBuilder); EmitMethods(_typeBuilder); //if (KeywordCallsites.count() > 0) // EmitSwapThunk(_typeBuilder); _compiledType = _typeBuilder.CreateType(); if (context.DynInitHelper != null) { context.DynInitHelper.FinalizeType(); } // If we don't pick up the ctor after we finalize the type, // we sometimes get a ctor which is not a RuntimeConstructorInfo // This causes System.DynamicILGenerator.Emit(opcode,ContructorInfo) to blow up. // The error says the ConstructorInfo is null, but there is a second case in the code. // Thank heavens one can run Reflector on mscorlib. ConstructorInfo[] cis = _compiledType.GetConstructors(); foreach (ConstructorInfo ci in cis) { if (ci.GetParameters().Length == CtorTypes().Length) { _ctorInfo = ci; break; } } return(_compiledType); } finally { if (IsDefType) { Var.popThreadBindings(); } } } finally { Var.popThreadBindings(); } }
public Expression GenCode(RHC rhc, ObjExpr objx, GenContext context) { LabelTarget loopLabel = (LabelTarget)Compiler.LoopLabelVar.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. for (int i = 0; i < _loopLocals.count(); i++) { LocalBinding lb = (LocalBinding)_loopLocals.nth(i); Expr arg = (Expr)_args.nth(i); ParameterExpression tempVar; Expression valExpr; Type primt = lb.PrimitiveType; if (primt != null) { tempVar = Expression.Parameter(primt, "__local__" + i); MaybePrimitiveExpr mpeArg = arg as MaybePrimitiveExpr; Type pt = Compiler.MaybePrimitiveType(arg); if (pt == primt) { valExpr = mpeArg.GenCodeUnboxed(RHC.Expression, objx, context); // do nothing } else if (primt == typeof(long) && pt == typeof(int)) { valExpr = mpeArg.GenCodeUnboxed(RHC.Expression, objx, context); valExpr = Expression.Convert(valExpr, primt); } else if (primt == typeof(double) && pt == typeof(float)) { valExpr = mpeArg.GenCodeUnboxed(RHC.Expression, objx, context); valExpr = Expression.Convert(valExpr, primt); } else if (primt == typeof(int) && pt == typeof(long)) { valExpr = mpeArg.GenCodeUnboxed(RHC.Expression, objx, context); valExpr = Expression.Convert(valExpr, primt); } else if (primt == typeof(float) && pt == typeof(double)) { valExpr = mpeArg.GenCodeUnboxed(RHC.Expression, objx, context); valExpr = Expression.Convert(valExpr, primt); } else { //if (true) //RT.booleanCast(RT.WARN_ON_REFLECTION.deref())) //RT.errPrintWriter().WriteLine 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)); //valExpr = arg.GenCode(RHC.Expression, objx, context); // valExpr = Expression.Convert(valExpr, primt); } } else { tempVar = Expression.Parameter(lb.ParamExpression.Type, "__local__" + i); valExpr = arg.GenCode(RHC.Expression, objx, context); } //ParameterExpression tempVar = Expression.Parameter(lb.ParamExpression.Type, "__local__" + i); //Expression valExpr = ((Expr)_args.nth(i)).GenCode(RHC.Expression, objx, 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))); if (valExpr.Type.IsPrimitive && !tempVar.Type.IsPrimitive) { tempAssigns.Add(Expression.Assign(tempVar, Compiler.MaybeBox(valExpr))); } else if (!valExpr.Type.IsPrimitive && tempVar.Type.IsPrimitive) { tempAssigns.Add(Expression.Assign(tempVar, HostExpr.GenUnboxArg(valExpr, tempVar.Type))); } else { tempAssigns.Add(Expression.Assign(tempVar, valExpr)); } finalAssigns.Add(Expression.Assign(lb.ParamExpression, tempVar)); } 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)); }