示例#1
0
        // ----------------------------------------------------------------------
        // 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));
        }
示例#2
0
        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);
            }
        }
示例#4
0
        // 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));
            }
        }
示例#5
0
        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()));
        }
示例#6
0
        // 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
        }
示例#7
0
        // ----------------------------------------------------------------------
        // 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();
            }
        }
示例#8
0
        // ----------------------------------------------------------------------
        // 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();
            }
        }
示例#9
0
        // ----------------------------------------------------------------------
        // 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));
        }
示例#10
0
        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));
            }
        }
示例#11
0
        // ----------------------------------------------------------------------
        // 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);
            }
        }