Пример #1
0
 private void BindMap <T>
     (ISeq <JST.Statement> statements,
     IMap <T, int> usageMap,
     IMap <T, JST.Expression> boundMap,
     Func <T, string> mkName,
     Func <T, JST.Expression> mkExpression)
 {
     foreach (var kv in usageMap)
     {
         if (!boundMap.ContainsKey(kv.Key))
         {
             if (kv.Value > 1)
             {
                 var e = mkExpression(kv.Key);
                 if (e != null)
                 {
                     if (env.DebugMode)
                     {
                         statements.Add(new JST.CommentStatement(mkName(kv.Key)));
                     }
                     var id = NameSupply.GenSym();
                     statements.Add(JST.Statement.Var(id, e));
                     boundMap.Add(kv.Key, id.ToE());
                 }
             }
             // else: inline expression as need it
         }
         // else: use outer binding
     }
 }
        public void BindUsage(ISeq <JST.Statement> statements, CST.Usage usage, TypePhase typePhase)
        {
            foreach (var kv in usage.Assemblies)
            {
                if (kv.Value > 1)
                {
                    if (!boundAssemblies.ContainsKey(kv.Key))
                    {
                        var e = env.JSTHelpers.DefaultResolveAssembly(this, kv.Key);
                        if (e != null)
                        {
                            if (env.DebugMode)
                            {
                                statements.Add(new JST.CommentStatement(kv.Key.ToString()));
                            }
                            var id = NameSupply.GenSym();
                            statements.Add(JST.Statement.Var(id, e));
                            boundAssemblies.Add(kv.Key, id.ToE());
                        }
                    }
                    // else: use outer binding
                }
                // else: inline expression as need it
            }

            foreach (var kv in usage.Types)
            {
                if (kv.Value > 1)
                {
                    var existing = default(ExpressionAndPhase);
                    var b        = boundTypes.TryGetValue(kv.Key, out existing);
                    if (!b || typePhase > existing.Phase)
                    {
                        var e = env.JSTHelpers.DefaultResolveType(this, kv.Key, typePhase);
                        if (e != null)
                        {
                            if (env.DebugMode)
                            {
                                statements.Add(new JST.CommentStatement(kv.Key.ToString()));
                            }
                            var id = NameSupply.GenSym();
                            statements.Add(JST.Statement.Var(id, e));
                            var updated = new ExpressionAndPhase(id.ToE(), typePhase);
                            if (b)
                            {
                                boundTypes[kv.Key] = updated;
                            }
                            else
                            {
                                boundTypes.Add(kv.Key, updated);
                            }
                        }
                    }
                    // else: use outer binding
                }
                // else: inline expression as need it
            }
        }
Пример #3
0
        // Collect types we need to compile
        private void CollectTypes()
        {
            foreach (var typeDef in assmEnv.Assembly.Types.Where(t => t.Invalid == null))
            {
                var tyconEnv = assmEnv.AddType(typeDef);
                if (typeDef.IsModule)
                {
                    // Look for any <Module>::.cctor()
                    // We know both <Module> and the .cctor have no type parameters
                    var methodDef =
                        typeDef.Members.OfType <CST.MethodDef>().Where
                            (m => m.Invalid == null && m.IsStatic && m.IsConstructor).FirstOrDefault();
                    if (methodDef != null)
                    {
                        moduleInitializer = methodDef.SelfMethodReference(tyconEnv);
                    }
                }

                if (typeDef.IsUsed)
                {
                    typeDefs.Add(typeDef);
                }
                else
                {
                    if (assemblyTrace == null || assemblyTrace.IncludeAssembly)
                    {
                        Env.Log(new UnusedDefinitionMessage(CST.MessageContextBuilders.Env(tyconEnv)));
                    }
                }
            }
        }
Пример #4
0
 private void CoalesceFrom(BasicBlock origHead, Set <BasicBlock> group, BasicBlock newBlock, Set <BasicBlock> visited)
 {
     if (!visited.Contains(this))
     {
         visited.Add(this);
         FixupTargets(origHead, newBlock);
         if (Equals(newBlock))
         {
             foreach (var s in origHead.Sources)
             {
                 if (!group.Contains(s))
                 {
                     newBlock.Sources.Add(s);
                 }
             }
         }
         else
         {
             for (var i = 0; i < Sources.Count; i++)
             {
                 if (group.Contains(Sources[i]))
                 {
                     Sources.RemoveAt(i--);
                 }
             }
         }
         if (newBlock.Targets.Contains(this))
         {
             Sources.Add(newBlock);
         }
         foreach (var t in Targets)
         {
             if (group.Contains(t))
             {
                 throw new InvalidOperationException
                           ("existing basic block has target strictly within group being removed");
             }
             t.CoalesceFrom(origHead, group, newBlock, visited);
         }
     }
 }
Пример #5
0
 private static void PreOrderFrom(BasicBlock bb, ISeq <BasicBlock> res, Set <BasicBlock> visited)
 {
     if (!visited.Contains(bb))
     {
         visited.Add(bb);
         res.Add(bb);
         foreach (var t in bb.Targets)
         {
             PreOrderFrom(t, res, visited);
         }
     }
 }
Пример #6
0
 private static void AllEdgesFrom(BasicBlock bb, ISeq <BBEdge> edges, Set <BasicBlock> visited)
 {
     if (!visited.Contains(bb))
     {
         visited.Add(bb);
         foreach (var t in bb.Targets)
         {
             var edge = new BBEdge {
                 Source = bb, Target = t
             };
             edges.Add(edge);
             AllEdgesFrom(t, edges, visited);
         }
     }
 }
Пример #7
0
        private ExpressionStackEntry Eval(ISeq <Statement> statements, ExpressionStackEntry entry)
        {
            if (statements == null)
            {
                throw new ArgumentNullException("statements");
            }
            // Eval the expression and save it in a temporary. If result is a structure, make the implied
            // value semantics explicit by cloning the value.
            var id   = gensym();
            var cell = new VariableCell(id);

            compEnv.AddVariable(id, ArgLocal.Local, false, true, compEnv.SubstituteType(entry.Expression.Type(compEnv)));
            statements.Add(new ExpressionStatement(cell.Write(entry.Expression.CloneIfStruct(compEnv))));
            // We never re-write to temporaries, so this stack entry now has no effects, not even a 'read' effect.
            // Also, the result's Expression.IsValue will be true.
            return(new ExpressionStackEntry(cell.Read(), bottom));
        }
Пример #8
0
        private Effects PeekAndEval(ISeq <Statement> statements, int arity, bool isLinear, Effects bodyEffects)
        {
            if (arity > Depth)
            {
                return(Failed(default(Effects), "underflow in peek-and-eval"));
            }

            // We may need to evaluate some of the arguments
            var argEvalStatements = default(Seq <Statement>);
            var argAndBodyEffects = default(Effects);
            var deferredEffects   = default(Effects);

            if (isLinear)
            {
                argAndBodyEffects = bodyEffects;
                deferredEffects   = ArgEffects(arity);
            }
            else
            {
                argEvalStatements = new Seq <Statement>();
                argAndBodyEffects = ProtectStackFromNonLinearEvaluation(argEvalStatements, arity, bodyEffects, out deferredEffects);
            }

            // We may need to evaluate some entries in the stack below the arguments
            if (!ProtectStackFromEffects(statements, argAndBodyEffects, arity))
            {
                return(default(Effects));
            }

            if (argEvalStatements != null)
            {
                // Any effects of these stataments have already been accumulated above
                foreach (var s in argEvalStatements)
                {
                    if (statements == null)
                    {
                        return(Failed(default(Effects), "eval in peek-and-eval"));
                    }
                    statements.Add(s);
                }
            }

            return(deferredEffects);
        }
Пример #9
0
        private bool Dump(ISeq <Statement> statements, MachineState state, int skip, int i)
        {
            if (statements == null)
            {
                return(Failed(false, "eval in flush"));
            }

            var id   = state.PeekId(stack.Count - (1 + skip) - i, gensym);
            var cell = new VariableCell(id);
            var read = stack[i].Expression as ReadExpression;

            if (read == null || !read.Address.Equals(cell.AddressOf()))
            {
                // Ok if id already added as temporary
                compEnv.AddVariable(id, ArgLocal.Local, false, true, compEnv.SubstituteType(state.PeekType(stack.Count - (1 + skip) - i)));
                statements.Add(new ExpressionStatement(cell.Write(stack[i].Expression.CloneIfStruct(compEnv))));
            }
            // else: stack entry has not changed, so no need to save it
            return(true);
        }
Пример #10
0
 public override void AccumLeaveTrys(IMSet <BasicBlock> visited, ISeq <LeaveTryBasicBlock> acc, int depth)
 {
     if (!visited.Contains(this))
     {
         visited.Add(this);
         if (depth == 0)
         {
             // Only include leave's from the try we started from, not inner trys
             acc.Add(this);
         }
         else
         {
             depth -= HandlerPopCount;
             if (depth >= 0)
             {
                 Target.AccumLeaveTrys(visited, acc, depth);
             }
         }
     }
 }
Пример #11
0
 private void ConsumeCommentStatement(ISeq<Statement> statements)
 {
     if (pendingComments != null)
     {
         statements.Add(new CommentStatement(pendingCommentsLoc, pendingComments.ToString()));
         pendingComments = null;
         pendingCommentsLoc = null;
     }
 }
Пример #12
0
        public void BindUsage(ISeq<JST.Statement> statements, CST.Usage usage, TypePhase typePhase)
        {
            foreach (var kv in usage.Assemblies)
            {
                if (kv.Value > 1)
                {
                    if (!boundAssemblies.ContainsKey(kv.Key))
                    {
                        var e = env.JSTHelpers.DefaultResolveAssembly(this, kv.Key);
                        if (e != null)
                        {
                            if (env.DebugMode)
                                statements.Add(new JST.CommentStatement(kv.Key.ToString()));
                            var id = NameSupply.GenSym();
                            statements.Add(JST.Statement.Var(id, e));
                            boundAssemblies.Add(kv.Key, id.ToE());
                        }
                    }
                    // else: use outer binding
                }
                // else: inline expression as need it
            }

            foreach (var kv in usage.Types)
            {
                if (kv.Value > 1)
                {
                    var existing = default(ExpressionAndPhase);
                    var b = boundTypes.TryGetValue(kv.Key, out existing);
                    if (!b || typePhase > existing.Phase)
                    {
                        var e = env.JSTHelpers.DefaultResolveType(this, kv.Key, typePhase);
                        if (e != null)
                        {
                            if (env.DebugMode)
                                statements.Add(new JST.CommentStatement(kv.Key.ToString()));
                            var id = NameSupply.GenSym();
                            statements.Add(JST.Statement.Var(id, e));
                            var updated = new ExpressionAndPhase(id.ToE(), typePhase);
                            if (b)
                                boundTypes[kv.Key] = updated;
                            else
                                boundTypes.Add(kv.Key, updated);
                        }
                    }
                    // else: use outer binding
                }
                // else: inline expression as need it
            }
        }
Пример #13
0
 private static void AllEdgesFrom(BasicBlock bb, ISeq<BBEdge> edges, Set<BasicBlock> visited)
 {
     if (!visited.Contains(bb))
     {
         visited.Add(bb);
         foreach (var t in bb.Targets)
         {
             var edge = new BBEdge { Source = bb, Target = t };
             edges.Add(edge);
             AllEdgesFrom(t, edges, visited);
         }
     }
 }
Пример #14
0
        protected void Lex(ISeq <string> args, TextReader reader)
        {
            var sb = new StringBuilder();

            while (true)
            {
                var c = reader.Read();
                if (c < 0)
                {
                    return;
                }
                if (c == '"')
                {
                    while (true)
                    {
                        var d = reader.Read();
                        if (d < 0)
                        {
                            // Ignore non-terminated string...
                            args.Add(sb.ToString());
                            return;
                        }
                        else if (d == '"')
                        {
                            var e = reader.Read();
                            if (e < 0)
                            {
                                args.Add(sb.ToString());
                                return;
                            }
                            else if (e == '"')
                            {
                                sb.Append((char)e);
                            }
                            else
                            {
                                args.Add(sb.ToString());
                                sb = new StringBuilder();
                                break;
                            }
                        }
                        else
                        {
                            sb.Append((char)d);
                        }
                    }
                }
                else if (!IsWS(c))
                {
                    sb.Append((char)c);
                    while (true)
                    {
                        var d = reader.Read();
                        if (d < 0)
                        {
                            args.Add(sb.ToString());
                            return;
                        }
                        else if (IsWS(d))
                        {
                            args.Add(sb.ToString());
                            sb = new StringBuilder();
                            break;
                        }
                        else
                        {
                            sb.Append((char)d);
                        }
                    }
                }
                // else: discard
            }
        }
Пример #15
0
        // Take acccount of:
        //   - PassRootAsArgument
        //   - PassInstanceAsArgument
        //   - InlineParamsArray
        private JST.Expression AppendFinalImport(JST.NameSupply nameSupply, JST.Identifier rootId, CST.AssemblyDef assemblyDef, CST.TypeDef typeDef, CST.MethodDef methodDef, JST.Expression script, ISeq<JST.Statement> body, IImSeq<JST.Expression> arguments)
        {
            var isInstanceMethod = !(methodDef.IsStatic || methodDef.IsConstructor);
            var scriptExpectsRoot = default(bool);
            attributeHelper.GetValueFromMethod
                (assemblyDef,
                 typeDef,
                 methodDef,
                 attributeHelper.ImportAttributeRef,
                 attributeHelper.ThePassRootAsArgumentProperty,
                 true,
                 false,
                 ref scriptExpectsRoot);
            var passInstAsArg = default(bool);
            attributeHelper.GetValueFromMethod
                (assemblyDef,
                 typeDef,
                 methodDef,
                 attributeHelper.ImportAttributeRef,
                 attributeHelper.ThePassInstanceAsArgumentProperty,
                 true,
                 false,
                 ref passInstAsArg);
            var instanceIsThis = isInstanceMethod && !passInstAsArg;
            var inlineParams = default(bool);
            attributeHelper.GetValueFromMethod
                (assemblyDef,
                 typeDef,
                 methodDef,
                 attributeHelper.ImportAttributeRef,
                 attributeHelper.TheInlineParamsArrayProperty,
                 true,
                 false,
                 ref inlineParams);
            var lastArgIsParamsArray = methodDef.HasParamsArray(rootEnv) && inlineParams;

            var funcScript = script as JST.FunctionExpression;

            var nextArg = 0;
            var instArg = default(JST.Expression);
            if (instanceIsThis)
            {
                // Instance argument will be the first arg to 'call' or 'apply', or the target of a '.' call.
                instArg = arguments[nextArg++];
                if (lastArgIsParamsArray && !instArg.IsDuplicatable)
                {
                    // Make sure instance argument is evaluated before the remaining arguments
                    var instId = nameSupply.GenSym();
                    body.Add(JST.Statement.Var(instId, instArg));
                    instArg = instId.ToE();
                }
            }
            else
            {
                if (lastArgIsParamsArray)
                    instArg = new JST.NullExpression();
            }

            var knownArgs = 0;
            var call = default(JST.Expression);

            if (lastArgIsParamsArray)
            {
                // We mush build script args at runtime
                var argsId = nameSupply.GenSym();
                body.Add(JST.Statement.Var(argsId, new JST.ArrayLiteral()));
                if (scriptExpectsRoot)
                {
                    body.Add(JST.Statement.DotCall(argsId.ToE(), Constants.push, rootId.ToE()));
                    knownArgs++;
                }
                while (nextArg < arguments.Count - 1)
                {
                    body.Add(JST.Statement.DotCall(argsId.ToE(), Constants.push, arguments[nextArg++]));
                    knownArgs++;
                }
                var arrArg = arguments[nextArg];
                if (!arrArg.IsDuplicatable)
                {
                    var arrId = nameSupply.GenSym();
                    body.Add(JST.Statement.Var(arrId, arrArg));
                    arrArg = arrId.ToE();
                }
                var iId = nameSupply.GenSym();
                body.Add
                    (new JST.IfStatement
                         (JST.Expression.IsNotNull(arrArg),
                          new JST.Statements
                              (new JST.ForStatement
                                   (new JST.ForVarLoopClause
                                        (iId,
                                         new JST.NumericLiteral(0),
                                         new JST.BinaryExpression
                                             (iId.ToE(),
                                              JST.BinaryOp.LessThan,
                                              JST.Expression.Dot(arrArg, Constants.length)),
                                         new JST.UnaryExpression(iId.ToE(), JST.UnaryOp.PostIncrement)),
                                    new JST.Statements
                                        (JST.Statement.DotCall
                                             (argsId.ToE(), Constants.push, new JST.IndexExpression(arrArg, iId.ToE())))))));

                if (funcScript != null)
                {
                    // var args = ...; var x = script; x.apply(this/null, args)
                    var scriptId = nameSupply.GenSym();
                    body.Add(JST.Statement.Var(scriptId, funcScript));
                    call = JST.Expression.DotCall(scriptId.ToE(), Constants.apply, instArg, argsId.ToE());
                }
                else
                {
                    if (instanceIsThis)
                    {
                        // var args = ...; (this.script).apply(this, args);
                        call = JST.Expression.DotCall
                            (JST.Expression.Dot(instArg, JST.Expression.ExplodePath(script)),
                             Constants.apply,
                             instArg,
                             argsId.ToE());
                    }
                    else
                    {
                        // var args = ...; script.apply(null, args)
                        call = JST.Expression.DotCall(script, Constants.apply, instArg, argsId.ToE());
                    }
                }
            }
            else
            {
                var callArgs = new Seq<JST.Expression>();
                if (instanceIsThis && funcScript != null)
                    callArgs.Add(instArg);
                if (scriptExpectsRoot)
                {
                    callArgs.Add(rootId.ToE());
                    knownArgs++;
                }
                while (nextArg < arguments.Count)
                {
                    callArgs.Add(arguments[nextArg++]);
                    knownArgs++;
                }
                if (instanceIsThis)
                {
                    if (funcScript != null)
                    {
                        // var x = script; x.call(this, arg1, ..., argn)
                        var scriptId = nameSupply.GenSym();
                        body.Add(JST.Statement.Var(scriptId, funcScript));
                        call = JST.Expression.DotCall(scriptId.ToE(), Constants.call, callArgs);
                    }
                    else
                        // this.script(arg1, ..., angn)
                        call = new JST.CallExpression
                            (JST.Expression.Dot(instArg, JST.Expression.ExplodePath(script)), callArgs);
                }
                else
                    // script(arg1, ..., argn)
                    call = new JST.CallExpression(script, callArgs);
            }

            if (funcScript != null)
            {
                if (funcScript.Parameters.Count < knownArgs)
                {
                    var ctxt = CST.MessageContextBuilders.Member(env.Global, assemblyDef, typeDef, methodDef);
                    env.Log(new InvalidInteropMessage(ctxt, "script accepts too few arguments"));
                    throw new DefinitionException();
                }
            }

            return call;
        }
Пример #16
0
        private void EnsurePathExists(ISeq<JST.Statement> statements, JST.Expression script, bool isStatic)
        {
            var path = JST.Expression.ExplodePath(script);
            for (var i = isStatic ? 0 : 1; i < path.Count - 1; i++)
            {
                var prefixPath = new Seq<JST.PropertyName>();
                for (var j = 0; j <= i; j++)
                    prefixPath.Add(path[j]);
                var prefix = JST.Expression.Path(prefixPath);
                if (i == 0)
                {
                    var exId = new JST.Identifier("e");
#if !JSCRIPT_IS_CORRECT
                    statements.Add(JST.Statement.Var(exId));
#endif
                    statements.Add
                        (new JST.TryStatement
                             (new JST.Statements(new JST.ExpressionStatement(prefix)),
                              new JST.CatchClause
                                  (exId, new JST.Statements(JST.Statement.Assignment(prefix, new JST.ObjectLiteral())))));
                }
                else if (!path[i].Value.Equals(Constants.prototype.Value, StringComparison.Ordinal))
                    statements.Add
                        (new JST.IfStatement
                             (JST.Expression.IsNull(prefix),
                              new JST.Statements(JST.Statement.Assignment(prefix, new JST.ObjectLiteral()))));
            }
        }
Пример #17
0
        // ----------------------------------------------------------------------
        // Entry point from TypeCompiler
        // ----------------------------------------------------------------------

        public void Emit(ISeq<JST.Statement> body, JST.Expression target)
        {
            if (env.BreakOnBreak &&
                env.AttributeHelper.MethodHasAttribute(methEnv.Assembly, methEnv.Type, methEnv.Method, env.AttributeHelper.BreakAttributeRef, false, false))
                System.Diagnostics.Debugger.Break();

            var methodName = CST.CSTWriter.WithAppend(env.Global, CST.WriterStyle.Debug, methEnv.MethodRef.Append);
            var methodSlot = env.GlobalMapping.ResolveMethodDefToSlot(methEnv.Assembly, methEnv.Type, methEnv.Method);
            var method = Method(methodName);

            switch (mode)
            {
                case MethodCompilationMode.SelfContained:
                {
                    if (target != null)
                        throw new InvalidOperationException("not expecting target in self-contained mode");
                    var assmName = CST.CSTWriter.WithAppend
                        (env.Global, CST.WriterStyle.Uniform, methEnv.Assembly.Name.Append);
                    var typeSlot = env.GlobalMapping.ResolveTypeDefToSlot(methEnv.Assembly, methEnv.Type);

                    var func = new JST.FunctionExpression
                        (new Seq<JST.Identifier> { rootId, assemblyId, typeDefinitionId },
                         new JST.Statements(new JST.ReturnStatement(method)));
                    var methodLoader = new Seq<JST.Statement>();
                    if (env.DebugMode)
                        methodLoader.Add(new JST.CommentStatement(methodName));
                    methodLoader.Add
                        (JST.Statement.DotCall
                             (new JST.Identifier(env.Root).ToE(),
                              Constants.RootBindMethod,
                              new JST.StringLiteral(assmName),
                              new JST.StringLiteral(typeSlot),
                              new JST.BooleanLiteral(env.InteropManager.IsStatic(methEnv.Assembly, methEnv.Type, methEnv.Method)),
                              new JST.StringLiteral(methodSlot),
                              func));
                    var methodProgram = new JST.Program(new JST.Statements(methodLoader));
                    var methodFileName = Path.Combine
                        (env.OutputDirectory,
                         Path.Combine
                             (JST.Lexemes.StringToFileName(assmName),
                              Path.Combine(typeSlot, Path.Combine(methodSlot, Constants.MethodFileName))));
                    methodProgram.ToFile(methodFileName, env.PrettyPrint);
                    env.Log(new GeneratedJavaScriptFile("method '" + methEnv.MethodRef + "'", methodFileName));
                    break;
                }
            case MethodCompilationMode.DirectBind:
                {
                    if (target == null)
                        throw new InvalidOperationException("expecting target in self-contained mode");
                    if (env.DebugMode)
                        body.Add(new JST.CommentStatement(methodName));
                    body.Add
                        (JST.Statement.Assignment(JST.Expression.Dot(target, new JST.Identifier(methodSlot)), method));
                    break;
                }
            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Пример #18
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));
            }
        }
Пример #19
0
        // ----------------------------------------------------------------------
        // Object helper methods in type structure
        // ----------------------------------------------------------------------

        private void AccumInstanceFields(CST.TypeEnvironment thisTypeEnv, ISeq<CST.FieldRef> fields)
        {
            if (thisTypeEnv.Type.Extends != null)
                AccumInstanceFields(thisTypeEnv.Type.Extends.Enter(thisTypeEnv), fields);

            foreach (var fieldDef in
                thisTypeEnv.Type.Members.OfType<CST.FieldDef>().Where
                    (f => f.Invalid == null && f.IsUsed && !f.IsStatic))
                fields.Add(new CST.FieldRef(thisTypeEnv.TypeRef, fieldDef.FieldSignature));
        }
Пример #20
0
 private static void PreOrderFrom(BasicBlock bb, ISeq<BasicBlock> res, Set<BasicBlock> visited)
 {
     if (!visited.Contains(bb))
     {
         visited.Add(bb);
         res.Add(bb);
         foreach (var t in bb.Targets)
             PreOrderFrom(t, res, visited);
     }
 }
Пример #21
0
        // ----------------------------------------------------------------------
        // Effective control flow (accounting for exceptions)
        // ----------------------------------------------------------------------

        // Given block is within a try. What instructions within it may originate an exception?
        private void AddExceptionalExits(ISeq<Instruction> exits, Instructions block)
        {
            foreach (var instruction in block.Body)
            {
                if (instruction.Flavor == InstructionFlavor.Try)
                {
                    var tryi = (TryInstruction)instruction;
                    var addedBody = false;
                    foreach (var handler in tryi.Handlers)
                    {
                        if (handler.Flavor == HandlerFlavor.Filter)
                            throw new InvalidOperationException("filter block");
                        // An exception handler may always throw an exception of its own
                        AddExceptionalExits(exits, handler.Body);
                        if (handler.Flavor == HandlerFlavor.Catch)
                        {
                            // Its possible for the catch handler not to match the throw exception,
                            // thus exception will escape from try body
                            if (!addedBody)
                            {
                                AddExceptionalExits(exits, tryi.Body);
                                addedBody = true;
                            }
                        }
                        // else: Fault and Finally blocks always capture the exception, and continue with
                        // their own control flow. Thus no exception will escape the try body directly.
                    }
                }
                else
                    exits.Add(instruction);
            }
        }