// ---------------------------------------------------------------------- // Initialize // ---------------------------------------------------------------------- // Build a function which will call the module initializer (if any) and effect the export of methods which // don't need an instance to bind into (if any) private void EmitInitializeFunction(Seq <JST.Statement> body) { var innerNameSupply = NameSupply.Fork(); var innerBody = new Seq <JST.Statement>(); // Export non-instance methods foreach (var typeDef in typeDefs) { var tyconEnv = assmEnv.AddType(typeDef); foreach (var methodDef in typeDef.Members.OfType <CST.MethodDef>().Where(m => m.Invalid == null)) { if (Env.InteropManager.IsExported(assmEnv.Assembly, typeDef, methodDef) && !Env.InteropManager.IsBindToInstance(assmEnv.Assembly, typeDef, methodDef)) { Env.InteropManager.AppendExport (innerNameSupply, rootId, assmEnv.Assembly, typeDef, methodDef, null, innerBody, (ns, asm, typ, meth, b, a) => Env.JSTHelpers.AppendCallExportedMethod(this, ns, asm, typ, meth, b, a)); } } } SetupTypes(innerBody); // Invoke any <Module>::.cctor if (moduleInitializer != null) { innerBody.Add (new JST.ExpressionStatement (MethodCallExpression(moduleInitializer, innerNameSupply, false, new Seq <JST.Expression>()))); } var func = new JST.FunctionExpression(null, new JST.Statements(innerBody)); // Simplify var simpCtxt = new JST.SimplifierContext(false, Env.DebugMode, NameSupply.Fork(), null); func = (JST.FunctionExpression)func.Simplify(simpCtxt, EvalTimes.Bottom); if (Env.DebugMode) { body.Add(new JST.CommentStatement("Assembly initializer")); } body.Add(JST.Statement.DotAssignment(assemblyId.ToE(), Constants.AssemblyInitialize, func)); }
private void EmitEntryPoint(Seq <JST.Statement> body) { var entryPoint = assmEnv.Assembly.EntryPoint; if (entryPoint != null) { var methEnv = entryPoint.EnterMethod(assmEnv); if (!methEnv.Method.IsStatic) { throw new InvalidOperationException("instance methods cannot be an entry point"); } if (methEnv.Method.IsConstructor) { throw new InvalidOperationException("constructors cannot be an entry point"); } if (methEnv.Type.Arity > 0) { throw new InvalidOperationException("methods of higher-kinded types cannot be an entry point"); } if (methEnv.Method.TypeArity > 0) { throw new InvalidOperationException("polymorphic methods cannot be an entry point"); } if (methEnv.Method.Arity > 0) { throw new InvalidOperationException("entry point method cannot accept arguments"); } var innerNameSupply = NameSupply.Fork(); var func = new JST.FunctionExpression (null, new JST.Statements(new JST.ExpressionStatement (MethodCallExpression(entryPoint, innerNameSupply, false, new Seq <JST.Expression>())))); if (Env.DebugMode) { body.Add(new JST.CommentStatement("Assembly entry point")); } body.Add(JST.Statement.DotAssignment(assemblyId.ToE(), Constants.AssemblyEntryPoint, func)); } }
// ---------------------------------------------------------------------- // Entry point from AssemblyCompiler // ---------------------------------------------------------------------- public void Emit(Seq<JST.Statement> body) { if (Env.BreakOnBreak && Env.AttributeHelper.TypeHasAttribute(TyconEnv.Assembly, TyconEnv.Type, Env.AttributeHelper.BreakAttributeRef, false, false)) System.Diagnostics.Debugger.Break(); CollectMembers(); var typeName = CST.CSTWriter.WithAppend (Env.Global, CST.WriterStyle.Uniform, TyconEnv.Type.EffectiveName(Env.Global).Append); var slotName = Env.GlobalMapping.ResolveTypeDefToSlot(TyconEnv.Assembly, TyconEnv.Type); if (TypeTrace != null && TypeTrace.IncludeType && TypeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Self-loader fragment var assmName = CST.CSTWriter.WithAppend (Env.Global, CST.WriterStyle.Uniform, TyconEnv.Assembly.Name.Append); var funcBody = new Seq<JST.Statement>(); BuildTypeStructure(funcBody); var func = new JST.FunctionExpression (new Seq<JST.Identifier> { RootId, AssemblyId, TypeDefinitionId }, new JST.Statements(funcBody)); var loaderBody = new Seq<JST.Statement>(); if (Env.DebugMode) loaderBody.Add(new JST.CommentStatement(TyconEnv.ToString())); loaderBody.Add (JST.Statement.DotCall (new JST.Identifier(Env.Root).ToE(), Constants.RootBindType, new JST.StringLiteral(assmName), new JST.StringLiteral(slotName), new JST.StringLiteral(typeName), func)); var program = new JST.Program(new JST.Statements(loaderBody)); var typePath = Path.Combine (Path.Combine(Env.OutputDirectory, JST.Lexemes.StringToFileName(assmName)), slotName); var fileName = Path.Combine(typePath, Constants.TypeFileName); program.ToFile(fileName, Env.PrettyPrint); Env.Log(new GeneratedJavaScriptFile("type '" + TyconEnv.TypeConstructorRef + "'", fileName)); CompileMethods(null, NameSupply); } else if (TypeTrace != null && !TypeTrace.IncludeType && TypeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Just passisng through CompileMethods(body, NameSupply); } else if (TypeTrace != null && !TypeTrace.IncludeType) { // Type defined elsewhere, include some/all methods only body.Add (JST.Statement.Var (TypeDefinitionId, JST.Expression.DotCall (AssemblyId.ToE(), new JST.Identifier(Constants.AssemblyTypeBuilderSlot(slotName)), Env.JSTHelpers.PhaseExpression(TypePhase.Slots)))); CompileMethods(body, NameSupply); } else { // Inline type definition and some/all methods if (Env.DebugMode) body.Add(new JST.CommentStatement(TyconEnv.ToString())); // We must construct the type explicity to phase 1 rather than using type compiler environment // since it thinks the type is already at phase 2. body.Add (JST.Statement.Var (TypeDefinitionId, JST.Expression.DotCall (AssemblyId.ToE(), new JST.Identifier(Constants.AssemblyTypeBuilderSlot(slotName)), Env.JSTHelpers.PhaseExpression(TypePhase.Id)))); BuildTypeStructure(body); CompileMethods(body, NameSupply); } }
// Take account of: // - BindToPrototype // - PassRootAsArgument // - PassInstanceAsArgument // - InlineParamsArray private void AppendFinalExport(JST.NameSupply nameSupply, JST.Identifier rootId, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef, JST.Expression script, JST.Expression instance, ISeq<JST.Statement> body, AppendCallExported appendCallExported) { if (script == null) throw new InvalidOperationException("expecting default script value"); var ctxt = CST.MessageContextBuilders.Member(env.Global, assemblyDef, typeDef, methodDef); var isInstance = !methodDef.IsStatic && !methodDef.IsConstructor; if (isInstance) { if (typeDef.Style is CST.ValueTypeStyle) { env.Log(new InvalidInteropMessage(ctxt, "cannot export instance methods from value types")); throw new DefinitionException(); } } var inlineParams = default(bool); attributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, attributeHelper.ExportAttributeRef, attributeHelper.TheInlineParamsArrayProperty, true, false, ref inlineParams); var lastArgIsParamsArray = methodDef.HasParamsArray(rootEnv) && inlineParams; var isPassRoot = default(bool); attributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, attributeHelper.ExportAttributeRef, attributeHelper.ThePassRootAsArgumentProperty, true, false, ref isPassRoot); var isProto = default(bool); attributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, attributeHelper.ExportAttributeRef, attributeHelper.TheBindToPrototypeProperty, true, false, ref isProto); var isPassInstance = default(bool); attributeHelper.GetValueFromMethod (assemblyDef, typeDef, methodDef, attributeHelper.ExportAttributeRef, attributeHelper.ThePassInstanceAsArgumentProperty, true, false, ref isPassInstance); var bindToInstance = isInstance && !isProto; if (bindToInstance != (instance != null)) throw new InvalidOperationException("expecting instance"); var captureThis = isInstance && !isPassInstance; var funcScript = script as JST.FunctionExpression; // Build the function to export var funcBody = new Seq<JST.Statement>(); var funcParameters = new Seq<JST.Identifier>(); var funcCallArgs = new Seq<JST.Expression>(); var funcArity = methodDef.Arity; if ((methodDef.IsConstructor && !methodDef.IsStatic) || captureThis) // unmanaged will not pass the instance funcArity--; if (lastArgIsParamsArray) // managed params args will be extracted from remainder of unmanaged arguments funcArity--; if (captureThis) funcCallArgs.Add(new JST.ThisExpression()); for (var i = 0; i < funcArity; i++) { var id = nameSupply.GenSym(); funcParameters.Add(id); funcCallArgs.Add(id.ToE()); } if (lastArgIsParamsArray) { var iId = nameSupply.GenSym(); var arrId = nameSupply.GenSym(); funcBody.Add(JST.Statement.Var(arrId, new JST.ArrayLiteral())); funcBody.Add (new JST.ForStatement (new JST.ForVarLoopClause (iId, new JST.NumericLiteral(funcArity), new JST.BinaryExpression (iId.ToE(), JST.BinaryOp.LessThan, JST.Expression.Dot(Constants.arguments.ToE(), Constants.length)), new JST.UnaryExpression(iId.ToE(), JST.UnaryOp.PostIncrement)), new JST.Statements (JST.Statement.DotCall (arrId.ToE(), Constants.push, new JST.IndexExpression(Constants.arguments.ToE(), iId.ToE()))))); funcCallArgs.Add(arrId.ToE()); } appendCallExported(nameSupply, assemblyDef, typeDef, methodDef, funcBody, funcCallArgs); var func = new JST.FunctionExpression(funcParameters, new JST.Statements(funcBody)); // Export the above function if (funcScript != null) { var scriptArgs = new Seq<JST.Expression>(); if (isPassRoot) scriptArgs.Add(rootId.ToE()); if (bindToInstance) scriptArgs.Add(instance); scriptArgs.Add(func); if (funcScript.Parameters.Count != scriptArgs.Count) { env.Log(new InvalidInteropMessage(ctxt, "invalid function arity")); throw new DefinitionException(); } body.Add(new JST.ExpressionStatement(new JST.CallExpression(script, scriptArgs))); } else { if (bindToInstance) script = JST.Expression.Dot(instance, JST.Expression.ExplodePath(script)); EnsurePathExists(body, script, !bindToInstance); body.Add(JST.Statement.Assignment(script, func)); } }
private void EmitManagedAndJavaScriptHelpers(Seq<JST.Statement> body, JST.Expression lhs) { var innerNameSupply = NameSupply.Fork(); var rep = Env.InteropManager.GetTypeRepresentation(TypeCompEnv.Assembly, TypeCompEnv.Type); var objId = innerNameSupply.GenSym(); var keyExp = JST.Expression.Dot(objId.ToE(), JST.Expression.ExplodePath(rep.KeyField)); var valId = innerNameSupply.GenSym(); var getKeyField = new JST.FunctionExpression (new Seq<JST.Identifier> { objId }, new JST.Statements(new JST.ReturnStatement(keyExp))); body.Add(JST.Statement.DotAssignment(lhs, Constants.TypeGetKeyField, getKeyField)); var setKeyField = new JST.FunctionExpression (new Seq<JST.Identifier> { objId, valId }, new JST.Statements(JST.Statement.Assignment(keyExp, valId.ToE()))); body.Add(JST.Statement.DotAssignment(lhs, Constants.TypeSetKeyField, setKeyField)); body.Add(JST.Statement.DotAssignment(lhs, Constants.TypeKeyToObject, new JST.ObjectLiteral())); }
// Build a function which will add (redirections to) exported instance methods into given unmanaged instance private void EmitBindInstanceExports(Seq<JST.Statement> body, JST.Expression lhs) { if (TypeCompEnv.Type.Extends == null || Parent.ExportedInstanceMethods.Count > 0) { var innerTypeCompEnv = TypeCompEnv.EnterFunction(); var parameters = new Seq<JST.Identifier>(); parameters.Add(innerTypeCompEnv.NameSupply.GenSym()); var innerBody = new Seq<JST.Statement>(); // Need to account for [NoInterop] #if false var usage = new Usage(); foreach (var methodDef in Parent.ExportedInstanceMethods) { var memEnv = TypeCompEnv.AddMember(methodDef); // We'll generally need these types to invoke import/exports foreach (var p in methodDef.ValueParameters) memEnv.SubstituteType(p.Type).AccumUsage(usage, true); if (methodDef.Result != null) memEnv.SubstituteType(methodDef.Result.Type).AccumUsage(usage, true); } innerTypeCompEnv.BindUsage(innerBody, usage, TypePhase.Constructed); #endif if (TypeCompEnv.Type.Extends != null && !(TypeCompEnv.Type.Extends.Style(TypeCompEnv) is CST.ObjectTypeStyle)) { // Bind exports from base innerBody.Add (JST.Statement.DotCall (innerTypeCompEnv.ResolveType(TypeCompEnv.Type.Extends, TypePhase.Slots), Constants.TypeBindInstanceExports, parameters[0].ToE())); } foreach (var methodDef in Parent.ExportedInstanceMethods) { Env.InteropManager.AppendExport (innerTypeCompEnv.NameSupply, RootId, TypeCompEnv.Assembly, TypeCompEnv.Type, methodDef, parameters[0].ToE(), innerBody, (ns, asm, typ, mem, b, a) => Env.JSTHelpers.AppendCallExportedMethod(innerTypeCompEnv, ns, asm, typ, mem, b, a)); } var func = new JST.FunctionExpression(parameters, new JST.Statements(innerBody)); // Simplify var simpCtxt = new JST.SimplifierContext(false, Env.DebugMode, NameSupply.Fork(), null); func = (JST.FunctionExpression)func.Simplify(simpCtxt, EvalTimes.Bottom); body.Add(JST.Statement.DotAssignment(lhs, Constants.TypeBindInstanceExports, func)); } // else: default is ok }
// ---------------------------------------------------------------------- // Entry point from compiler driver // ---------------------------------------------------------------------- public void Emit(Seq <JST.Statement> body) { if (Env.BreakOnBreak && Env.AttributeHelper.AssemblyHasAttribute(assmEnv.Assembly, Env.AttributeHelper.BreakAttributeRef, false, false)) { System.Diagnostics.Debugger.Break(); } var assmName = CST.CSTWriter.WithAppend(Env.Global, CST.WriterStyle.Uniform, assmEnv.Assembly.Name.Append); CollectTypes(); if (assemblyTrace == null || assemblyTrace.IncludeAssembly && assemblyTrace.Parent.Flavor == TraceFlavor.Remainder) { // Self-loader fragment, possibly containing entire assembly var assmBody = new Seq <JST.Statement>(); BuildAssembly(assmBody); CompileTypes(assmBody); EmitInitializeFunction(assmBody); var assmFunc = new JST.FunctionExpression(new Seq <JST.Identifier> { rootId, assemblyId }, new JST.Statements(assmBody)); var assmLoader = new Seq <JST.Statement>(); if (Env.DebugMode) { assmLoader.Add(new JST.CommentStatement(assmEnv.ToString())); } assmLoader.Add (JST.Statement.DotCall (new JST.Identifier(Env.Root).ToE(), Constants.RootBindAssembly, new JST.StringLiteral(assmName), assmFunc)); var assmProgram = new JST.Program(new JST.Statements(assmLoader)); var assmPath = Path.Combine(Env.OutputDirectory, JST.Lexemes.StringToFileName(assmName)); var finalName = default(string); switch (Env.CompilationMode) { case CompilationMode.Plain: case CompilationMode.Collecting: finalName = Constants.AllFileName; break; case CompilationMode.Traced: finalName = Constants.AssemblyFileName; break; default: throw new ArgumentOutOfRangeException(); } var assmFileName = Path.Combine(assmPath, finalName); assmProgram.ToFile(assmFileName, Env.PrettyPrint); Env.Log(new GeneratedJavaScriptFile("assembly '" + assmName + "'", assmFileName)); } else if (!assemblyTrace.IncludeAssembly && assemblyTrace.Parent.Flavor == TraceFlavor.Remainder) { // Just passing through CompileTypes(body); } else if (!assemblyTrace.IncludeAssembly) { // Assembly defined elsewhere, include some/all types only in trace body.Add (JST.Statement.Var (assemblyId, new JST.IndexExpression (JST.Expression.Dot(rootId.ToE(), Constants.RootAssemblyCache), new JST.StringLiteral(assmName)))); CompileTypes(body); } else { // Inline assembly definition and some/all types body.Add (JST.Statement.Var (assemblyId, JST.Expression.DotCall (rootId.ToE(), Constants.RootCreateAssembly, new JST.StringLiteral(assmName)))); BuildAssembly(body); CompileTypes(body); EmitInitializeFunction(body); } if (assmEnv.Assembly.EntryPoint != null && (assemblyTrace == null || assemblyTrace.IncludeAssembly)) { EmitStart(); EmitManifest(); } }
// ---------------------------------------------------------------------- // Entry point from compiler driver // ---------------------------------------------------------------------- public void Emit(Seq<JST.Statement> body) { if (Env.BreakOnBreak && Env.AttributeHelper.AssemblyHasAttribute(assmEnv.Assembly, Env.AttributeHelper.BreakAttributeRef, false, false)) System.Diagnostics.Debugger.Break(); var assmName = CST.CSTWriter.WithAppend(Env.Global, CST.WriterStyle.Uniform, assmEnv.Assembly.Name.Append); CollectTypes(); if (assemblyTrace == null || assemblyTrace.IncludeAssembly && assemblyTrace.Parent.Flavor == TraceFlavor.Remainder) { // Self-loader fragment, possibly containing entire assembly var assmBody = new Seq<JST.Statement>(); BuildAssembly(assmBody); CompileTypes(assmBody); EmitInitializeFunction(assmBody); var assmFunc = new JST.FunctionExpression(new Seq<JST.Identifier> { rootId, assemblyId }, new JST.Statements(assmBody)); var assmLoader = new Seq<JST.Statement>(); if (Env.DebugMode) assmLoader.Add(new JST.CommentStatement(assmEnv.ToString())); assmLoader.Add (JST.Statement.DotCall (new JST.Identifier(Env.Root).ToE(), Constants.RootBindAssembly, new JST.StringLiteral(assmName), assmFunc)); var assmProgram = new JST.Program(new JST.Statements(assmLoader)); var assmPath = Path.Combine(Env.OutputDirectory, JST.Lexemes.StringToFileName(assmName)); var finalName = default(string); switch (Env.CompilationMode) { case CompilationMode.Plain: case CompilationMode.Collecting: finalName = Constants.AllFileName; break; case CompilationMode.Traced: finalName = Constants.AssemblyFileName; break; default: throw new ArgumentOutOfRangeException(); } var assmFileName = Path.Combine(assmPath, finalName); assmProgram.ToFile(assmFileName, Env.PrettyPrint); Env.Log(new GeneratedJavaScriptFile("assembly '" + assmName + "'", assmFileName)); } else if (!assemblyTrace.IncludeAssembly && assemblyTrace.Parent.Flavor == TraceFlavor.Remainder) { // Just passing through CompileTypes(body); } else if (!assemblyTrace.IncludeAssembly) { // Assembly defined elsewhere, include some/all types only in trace body.Add (JST.Statement.Var (assemblyId, new JST.IndexExpression (JST.Expression.Dot(rootId.ToE(), Constants.RootAssemblyCache), new JST.StringLiteral(assmName)))); CompileTypes(body); } else { // Inline assembly definition and some/all types body.Add (JST.Statement.Var (assemblyId, JST.Expression.DotCall (rootId.ToE(), Constants.RootCreateAssembly, new JST.StringLiteral(assmName)))); BuildAssembly(body); CompileTypes(body); EmitInitializeFunction(body); } if (assmEnv.Assembly.EntryPoint != null && (assemblyTrace == null || assemblyTrace.IncludeAssembly)) { EmitStart(); EmitManifest(); } }
// ---------------------------------------------------------------------- // Initialize // ---------------------------------------------------------------------- // Build a function which will call the module initializer (if any) and effect the export of methods which // don't need an instance to bind into (if any) private void EmitInitializeFunction(Seq<JST.Statement> body) { var innerNameSupply = NameSupply.Fork(); var innerBody = new Seq<JST.Statement>(); // Export non-instance methods foreach (var typeDef in typeDefs) { var tyconEnv = assmEnv.AddType(typeDef); foreach (var methodDef in typeDef.Members.OfType<CST.MethodDef>().Where(m => m.Invalid == null)) { if (Env.InteropManager.IsExported(assmEnv.Assembly,typeDef, methodDef) && !Env.InteropManager.IsBindToInstance(assmEnv.Assembly, typeDef, methodDef)) { Env.InteropManager.AppendExport (innerNameSupply, rootId, assmEnv.Assembly, typeDef, methodDef, null, innerBody, (ns, asm, typ, meth, b, a) => Env.JSTHelpers.AppendCallExportedMethod(this, ns, asm, typ, meth, b, a)); } } } SetupTypes(innerBody); // Invoke any <Module>::.cctor if (moduleInitializer != null) innerBody.Add (new JST.ExpressionStatement (MethodCallExpression(moduleInitializer, innerNameSupply, false, new Seq<JST.Expression>()))); var func = new JST.FunctionExpression(null, new JST.Statements(innerBody)); // Simplify var simpCtxt = new JST.SimplifierContext(false, Env.DebugMode, NameSupply.Fork(), null); func = (JST.FunctionExpression)func.Simplify(simpCtxt, EvalTimes.Bottom); if (Env.DebugMode) body.Add(new JST.CommentStatement("Assembly initializer")); body.Add(JST.Statement.DotAssignment(assemblyId.ToE(), Constants.AssemblyInitialize, func)); }
private void EmitEntryPoint(Seq<JST.Statement> body) { var entryPoint = assmEnv.Assembly.EntryPoint; if (entryPoint != null) { var methEnv = entryPoint.EnterMethod(assmEnv); if (!methEnv.Method.IsStatic) throw new InvalidOperationException("instance methods cannot be an entry point"); if (methEnv.Method.IsConstructor) throw new InvalidOperationException("constructors cannot be an entry point"); if (methEnv.Type.Arity > 0) throw new InvalidOperationException("methods of higher-kinded types cannot be an entry point"); if (methEnv.Method.TypeArity > 0) throw new InvalidOperationException("polymorphic methods cannot be an entry point"); if (methEnv.Method.Arity > 0) throw new InvalidOperationException("entry point method cannot accept arguments"); var innerNameSupply = NameSupply.Fork(); var func = new JST.FunctionExpression (null, new JST.Statements(new JST.ExpressionStatement (MethodCallExpression(entryPoint, innerNameSupply, false, new Seq<JST.Expression>())))); if (Env.DebugMode) body.Add(new JST.CommentStatement("Assembly entry point")); body.Add(JST.Statement.DotAssignment(assemblyId.ToE(), Constants.AssemblyEntryPoint, func)); } }
// ---------------------------------------------------------------------- // Entry point from AssemblyCompiler // ---------------------------------------------------------------------- public void Emit(Seq <JST.Statement> body) { if (Env.BreakOnBreak && Env.AttributeHelper.TypeHasAttribute(TyconEnv.Assembly, TyconEnv.Type, Env.AttributeHelper.BreakAttributeRef, false, false)) { System.Diagnostics.Debugger.Break(); } CollectMembers(); var typeName = CST.CSTWriter.WithAppend (Env.Global, CST.WriterStyle.Uniform, TyconEnv.Type.EffectiveName(Env.Global).Append); var slotName = Env.GlobalMapping.ResolveTypeDefToSlot(TyconEnv.Assembly, TyconEnv.Type); if (TypeTrace != null && TypeTrace.IncludeType && TypeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Self-loader fragment var assmName = CST.CSTWriter.WithAppend (Env.Global, CST.WriterStyle.Uniform, TyconEnv.Assembly.Name.Append); var funcBody = new Seq <JST.Statement>(); BuildTypeStructure(funcBody); var func = new JST.FunctionExpression (new Seq <JST.Identifier> { RootId, AssemblyId, TypeDefinitionId }, new JST.Statements(funcBody)); var loaderBody = new Seq <JST.Statement>(); if (Env.DebugMode) { loaderBody.Add(new JST.CommentStatement(TyconEnv.ToString())); } loaderBody.Add (JST.Statement.DotCall (new JST.Identifier(Env.Root).ToE(), Constants.RootBindType, new JST.StringLiteral(assmName), new JST.StringLiteral(slotName), new JST.StringLiteral(typeName), func)); var program = new JST.Program(new JST.Statements(loaderBody)); var typePath = Path.Combine (Path.Combine(Env.OutputDirectory, JST.Lexemes.StringToFileName(assmName)), slotName); var fileName = Path.Combine(typePath, Constants.TypeFileName); program.ToFile(fileName, Env.PrettyPrint); Env.Log(new GeneratedJavaScriptFile("type '" + TyconEnv.TypeConstructorRef + "'", fileName)); CompileMethods(null, NameSupply); } else if (TypeTrace != null && !TypeTrace.IncludeType && TypeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Just passisng through CompileMethods(body, NameSupply); } else if (TypeTrace != null && !TypeTrace.IncludeType) { // Type defined elsewhere, include some/all methods only body.Add (JST.Statement.Var (TypeDefinitionId, JST.Expression.DotCall (AssemblyId.ToE(), new JST.Identifier(Constants.AssemblyTypeBuilderSlot(slotName)), Env.JSTHelpers.PhaseExpression(TypePhase.Slots)))); CompileMethods(body, NameSupply); } else { // Inline type definition and some/all methods if (Env.DebugMode) { body.Add(new JST.CommentStatement(TyconEnv.ToString())); } // We must construct the type explicity to phase 1 rather than using type compiler environment // since it thinks the type is already at phase 2. body.Add (JST.Statement.Var (TypeDefinitionId, JST.Expression.DotCall (AssemblyId.ToE(), new JST.Identifier(Constants.AssemblyTypeBuilderSlot(slotName)), Env.JSTHelpers.PhaseExpression(TypePhase.Id)))); BuildTypeStructure(body); CompileMethods(body, NameSupply); } }