public static Type GenerateClass(string className, Type superClass, ISeq interfaces, // of Types ISeq ctors, ISeq ctorTypes, ISeq methods, IPersistentMap exposesFields, IPersistentMap exposesMethods, string prefix, bool hasMain, string factoryName, string stateName, string initName, string postInitName, string implCname, string implNamespace, bool loadImplNameSpace) { string path = (string)Compiler.COMPILE_PATH.deref(); if ( path == null) throw new Exception("*compile-path* not set"); string extension = hasMain ? ".exe" : ".dll"; //GenContext context = new GenContext(className, extension, path, CompilerMode.File); GenContext context = new GenContext(className, extension, path, true); // define the class List<Type> interfaceTypes = new List<Type>(); for (ISeq s = interfaces; s != null; s = s.next()) interfaceTypes.Add((Type)s.first()); //TypeBuilder proxyTB = context.ModuleBldr.DefineType( TypeBuilder proxyTB = context.ModuleBuilder.DefineType( className, TypeAttributes.Class | TypeAttributes.Public, superClass, interfaceTypes.ToArray()); List<MethodSignature> sigs = GetAllSignatures(superClass,interfaceTypes,methods); Dictionary<string,List<MethodSignature>> overloads = ComputeOverloads(sigs); HashSet<string> varNames = ComputeOverloadNames(overloads); foreach ( MethodSignature sig in sigs ) varNames.Add(sig.Name); if (!String.IsNullOrEmpty(initName)) varNames.Add(initName); if (!String.IsNullOrEmpty(postInitName)) varNames.Add(postInitName); if (hasMain) varNames.Add(_mainName); Dictionary<string, FieldBuilder> varMap = DefineStaticFields(proxyTB, varNames); FieldBuilder stateFB = String.IsNullOrEmpty(stateName) ? null : DefineStateField(proxyTB, stateName); DefineStaticCtor(proxyTB,prefix,varMap,loadImplNameSpace,implNamespace,implCname); FieldBuilder initFB = null; FieldBuilder postInitFB = null; FieldBuilder mainFB = null; varMap.TryGetValue(initName, out initFB); varMap.TryGetValue(postInitName, out postInitFB); varMap.TryGetValue(_mainName, out mainFB); DefineCtors(proxyTB, superClass, implNamespace + "." + prefix + initName, implNamespace + "." + prefix + postInitName, ctorTypes, initFB, postInitFB, stateFB, factoryName); EmitMethods(proxyTB, sigs, overloads, varMap, exposesMethods); EmitExposers(proxyTB, superClass, exposesFields); if (hasMain) EmitMain(context, proxyTB, implNamespace + "." + prefix + _mainName, mainFB); Type t = proxyTB.CreateType(); context.SaveAssembly(); return t; }
internal static object Compile(TextReader rdr, string sourceDirectory, string sourceName, string relativePath) { if (COMPILE_PATH.deref() == null) throw new Exception("*compile-path* not set"); object eofVal = new object(); object form; //string sourcePath = sourceDirectory == null ? sourceName : sourceDirectory + "\\" + sourceName; string sourcePath = relativePath; LineNumberingTextReader lntr = (rdr is LineNumberingTextReader) ? (LineNumberingTextReader)rdr : new LineNumberingTextReader(rdr); GenContext context = new GenContext(sourceName, ".dll", sourceDirectory, true); GenContext evalContext = new GenContext("EvalForCompile", false); Var.pushThreadBindings(RT.map( SOURCE_PATH, sourcePath, SOURCE, sourceName, METHOD, null, LOCAL_ENV, null, LOOP_LOCALS, null, NEXT_LOCAL_NUM, 0, RT.CURRENT_NS, RT.CURRENT_NS.deref(), //LINE_BEFORE, lntr.LineNumber, //LINE_AFTER, lntr.LineNumber, DOCUMENT_INFO, Expression.SymbolDocument(sourceName), // I hope this is enough CONSTANTS, PersistentVector.EMPTY, CONSTANT_IDS, new IdentityHashMap(), KEYWORDS, PersistentHashMap.EMPTY, VARS, PersistentHashMap.EMPTY, KEYWORD_CALLSITES, PersistentVector.EMPTY, // jvm doesn't do this, don't know why VAR_CALLSITES, PersistentVector.EMPTY, // jvm doesn't do this, don't know why PROTOCOL_CALLSITES, PersistentVector.EMPTY, // jvm doesn't do this, don't know why COMPILER_CONTEXT, context )); try { FnExpr objx = new FnExpr(null); objx.InternalName = sourcePath.Replace(Path.PathSeparator, '/').Substring(0, sourcePath.LastIndexOf('.')) + "__init"; TypeBuilder exprTB = context.AssemblyGen.DefinePublicType("__REPL__", typeof(object), true); //List<string> names = new List<string>(); List<Expr> exprs = new List<Expr>(); int i = 0; while ((form = LispReader.read(lntr, false, eofVal, false)) != eofVal) { //Java version: LINE_AFTER.set(lntr.LineNumber); Compile1(context, evalContext, exprTB, form, exprs, ref i); //Java version: LINE_BEFORE.set(lntr.LineNumber); } Type exprType = exprTB.CreateType(); // Need to put the loader init in its own type because we can't generate calls on the MethodBuilders // until after their types have been closed. TypeBuilder initTB = context.AssemblyGen.DefinePublicType("__Init__", typeof(object), true); Expression pushNSExpr = Expression.Call(null, Method_Compiler_PushNS); Expression popExpr = Expression.Call(null, Method_Var_popThreadBindings); BodyExpr bodyExpr = new BodyExpr(PersistentVector.create1(exprs)); FnMethod method = new FnMethod(objx, null, bodyExpr); objx.AddMethod(method); objx.Keywords = (IPersistentMap)KEYWORDS.deref(); objx.Vars = (IPersistentMap)VARS.deref(); objx.Constants = (PersistentVector)CONSTANTS.deref(); objx.KeywordCallsites = (IPersistentVector)KEYWORD_CALLSITES.deref(); objx.ProtocolCallsites = (IPersistentVector)PROTOCOL_CALLSITES.deref(); objx.VarCallsites = (IPersistentVector)VAR_CALLSITES.deref(); objx.Compile(typeof(AFunction), PersistentVector.EMPTY, false, context); Expression fnNew = objx.GenCode(RHC.Expression,objx,context); Expression fnInvoke = Expression.Call(fnNew, fnNew.Type.GetMethod("invoke", System.Type.EmptyTypes)); Expression tryCatch = Expression.TryCatchFinally(fnInvoke, popExpr); Expression body = Expression.Block(pushNSExpr, tryCatch); // create initializer call MethodBuilder mbInit = initTB.DefineMethod("Initialize", MethodAttributes.Public | MethodAttributes.Static); LambdaExpression initFn = Expression.Lambda(body); //initFn.CompileToMethod(mbInit, DebugInfoGenerator.CreatePdbGenerator()); initFn.CompileToMethod(mbInit, context.IsDebuggable); initTB.CreateType(); context.SaveAssembly(); } catch (LispReader.ReaderException e) { throw new CompilerException(sourceName, e.Line, e.InnerException); } finally { Var.popThreadBindings(); } return null; }