Пример #1
0
        internal static IVariable[] GetCapturedLoopVariables(IEmitter emitter, AstNode context, IEnumerable <ParameterDeclaration> parameters, bool excludeReadOnly = false)
        {
            var loop = LambdaBlock.GetOuterLoop(context);

            if (loop == null)
            {
                return(null);
            }

            var loopVariablesAnalyzer = new LoopVariablesAnalyzer(emitter, excludeReadOnly);

            loopVariablesAnalyzer.Analyze(loop);

            var captureAnalyzer = new CaptureAnalyzer(emitter);

            captureAnalyzer.Analyze(context, parameters.Select(p => p.Name));
            return(captureAnalyzer.UsedVariables.Where(v => loopVariablesAnalyzer.Variables.Contains(v)).ToArray());
        }
Пример #2
0
        public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
        {
            if (captureOnly)
            {
                var analyzer = new CaptureAnalyzer(this.emitter);
                analyzer.Analyze(lambdaExpression.Body, lambdaExpression.Parameters.Select(p => p.Name));

                if (analyzer.UsedVariables.Count > 0)
                {
                    this.LambdaExpression.Add(lambdaExpression);
                }
            }
            else
            {
                this.LambdaExpression.Add(lambdaExpression);
            }

            base.VisitLambdaExpression(lambdaExpression);
        }
Пример #3
0
        public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
        {
            if (captureOnly)
            {
                var analyzer = new CaptureAnalyzer(this.emitter.Resolver.Resolver);
                analyzer.Analyze(anonymousMethodExpression.Body, anonymousMethodExpression.Parameters.Select(p => p.Name));

                if (analyzer.UsedVariables.Count > 0)
                {
                    this.LambdaExpression.Add(anonymousMethodExpression);
                }
            }
            else
            {
                this.LambdaExpression.Add(anonymousMethodExpression);
            }

            base.VisitAnonymousMethodExpression(anonymousMethodExpression);
        }
Пример #4
0
        public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
        {
            var analyzer = new CaptureAnalyzer(this.resolver);

            analyzer.Analyze(anonymousMethodExpression.Body, anonymousMethodExpression.Parameters.Select(p => p.Name));

            foreach (var usedVariable in analyzer.UsedVariables)
            {
                if (!_variables.Contains(usedVariable.Name) && !_usedVariables.Contains(usedVariable))
                {
                    _usedVariables.Add(usedVariable);
                }
            }

            if (analyzer.UsesThis)
            {
                this._usesThis = true;
            }

            //base.VisitAnonymousMethodExpression(anonymousMethodExpression);
        }
Пример #5
0
        public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
        {
            var analyzer = new CaptureAnalyzer(this.emitter);

            analyzer.Analyze(lambdaExpression.Body, lambdaExpression.Parameters.Select(p => p.Name));

            foreach (var usedVariable in analyzer.UsedVariables)
            {
                if (!_variables.Contains(usedVariable.Name) && !_usedVariables.Contains(usedVariable))
                {
                    _usedVariables.Add(usedVariable);
                }
            }

            if (analyzer.UsesThis)
            {
                this._usesThis = true;
            }

            //base.VisitLambdaExpression(lambdaExpression);
        }
Пример #6
0
        private string[] GetCapturedLoopVariables()
        {
            var loop = this.GetOuterLoop();

            if (loop == null)
            {
                return(null);
            }

            var loopVariablesAnalyzer = new LoopVariablesAnalyzer(this.Emitter);

            loopVariablesAnalyzer.Analyze(loop);

            var captureAnalyzer = new CaptureAnalyzer(this.Emitter);

            captureAnalyzer.Analyze(this.Context, this.Parameters.Select(p => p.Name));
            var capturedVariables = captureAnalyzer.UsedVariables.Where(v => loopVariablesAnalyzer.Variables.Contains(v)).ToArray();

            List <string> names = new List <string>();

            foreach (var capturedVariable in capturedVariables)
            {
                if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(capturedVariable))
                {
                    names.Add(this.Emitter.LocalsMap[capturedVariable]);
                }
                else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(capturedVariable.Name))
                {
                    names.Add(this.Emitter.LocalsNamesMap[capturedVariable.Name]);
                }
                else
                {
                    names.Add(capturedVariable.Name);
                }
            }

            return(names.ToArray());
        }
Пример #7
0
        protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context)
        {
            var analyzer = new CaptureAnalyzer(this.Emitter.Resolver.Resolver);

            analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name));

            var oldLevel = this.Emitter.Level;

            if (analyzer.UsedVariables.Count == 0)
            {
                this.Emitter.Level = 1;
            }

            AsyncBlock asyncBlock = null;

            this.PushLocals();

            if (this.IsAsync)
            {
                if (context is LambdaExpression)
                {
                    asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context);
                }
                else
                {
                    asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context);
                }

                asyncBlock.InitAsyncBlock();
            }

            var prevMap      = this.BuildLocalsMap();
            var prevNamesMap = this.BuildLocalsNamesMap();

            this.AddLocals(parameters, body);

            bool block = body is BlockStatement;

            this.Write("");

            var savedPos       = this.Emitter.Output.Length;
            var savedThisCount = this.Emitter.ThisRefCounter;

            this.WriteFunction();
            this.EmitMethodParameters(parameters, null, context);
            this.WriteSpace();

            int pos = 0;

            if (!block && !this.IsAsync)
            {
                this.BeginBlock();
                pos = this.Emitter.Output.Length;
            }

            bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync;

            if (isSimpleLambda)
            {
                this.ConvertParamsToReferences(parameters);
                var rr = this.Emitter.Resolver.ResolveNode(this.Context, this.Emitter) as LambdaResolveResult;

                if (rr == null || rr.ReturnType.Kind != TypeKind.Void)
                {
                    this.WriteReturn(true);
                }
            }

            if (this.IsAsync)
            {
                asyncBlock.Emit(true);
            }
            else
            {
                body.AcceptVisitor(this.Emitter);
            }

            if (isSimpleLambda)
            {
                this.WriteSemiColon();
            }

            if (!block && !this.IsAsync)
            {
                this.WriteNewLine();
                this.EndBlock();
            }

            if (!block && !this.IsAsync)
            {
                this.EmitTempVars(pos);
            }

            if (analyzer.UsedVariables.Count == 0)
            {
                var name = "f" + (this.Emitter.NamedFunctions.Count + 1);
                var code = this.Emitter.Output.ToString().Substring(savedPos);
                var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code);

                if (pair.Key != null && pair.Value != null)
                {
                    name = pair.Key;
                }
                else
                {
                    this.Emitter.NamedFunctions.Add(name, code);
                }

                this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos);
                this.Emitter.Output.Insert(savedPos, "$_." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name);
                this.Emitter.Level = oldLevel;
            }

            if (this.Emitter.ThisRefCounter > savedThisCount)
            {
                this.Emitter.Output.Insert(savedPos, Bridge.Translator.Emitter.ROOT + "." + Bridge.Translator.Emitter.DELEGATE_BIND + "(this, ");
                this.WriteCloseParentheses();
            }

            this.PopLocals();
            this.ClearLocalsMap(prevMap);
            this.ClearLocalsNamesMap(prevNamesMap);
        }
Пример #8
0
        protected virtual void EmitLambda(IEnumerable <ParameterDeclaration> parameters, AstNode body, AstNode context)
        {
            var rr         = this.Emitter.Resolver.ResolveNode(context, this.Emitter);
            var oldLifting = this.Emitter.ForbidLifting;

            this.Emitter.ForbidLifting = false;
            var analyzer = new CaptureAnalyzer(this.Emitter);

            analyzer.Analyze(this.Body, this.Parameters.Select(p => p.Name));

            var oldLevel = this.Emitter.Level;

            if (analyzer.UsedVariables.Count == 0)
            {
                this.Emitter.ResetLevel();
                Indent();
            }

            AsyncBlock asyncBlock = null;

            this.PushLocals();

            if (this.IsAsync)
            {
                if (context is LambdaExpression)
                {
                    asyncBlock = new AsyncBlock(this.Emitter, (LambdaExpression)context);
                }
                else
                {
                    asyncBlock = new AsyncBlock(this.Emitter, (AnonymousMethodExpression)context);
                }

                asyncBlock.InitAsyncBlock();
            }

            var prevMap      = this.BuildLocalsMap();
            var prevNamesMap = this.BuildLocalsNamesMap();

            this.AddLocals(parameters, body);

            bool block = body is BlockStatement;

            this.Write("");

            var savedPos          = this.Emitter.Output.Length;
            var savedThisCount    = this.Emitter.ThisRefCounter;
            var capturedVariables = this.GetCapturedLoopVariables();

            if (capturedVariables != null && capturedVariables.Length > 0)
            {
                this.Write("(function (" + string.Join(", ", capturedVariables) + ") ");
                this.BeginBlock();
                this.Write("return ");
            }

            this.WriteFunction();
            this.EmitMethodParameters(parameters, null, context);
            this.WriteSpace();

            int pos = 0;

            if (!block && !this.IsAsync)
            {
                this.BeginBlock();
                pos = this.Emitter.Output.Length;
            }

            bool isSimpleLambda = body.Parent is LambdaExpression && !block && !this.IsAsync;

            if (isSimpleLambda)
            {
                this.ConvertParamsToReferences(parameters);
                var lrr = rr as LambdaResolveResult;

                if (lrr == null || lrr.ReturnType.Kind != TypeKind.Void)
                {
                    this.WriteReturn(true);
                }
            }

            if (this.IsAsync)
            {
                asyncBlock.Emit(true);
            }
            else
            {
                body.AcceptVisitor(this.Emitter);
            }

            if (isSimpleLambda)
            {
                this.WriteSemiColon();
            }

            if (!block && !this.IsAsync)
            {
                this.WriteNewLine();
                this.EndBlock();
            }

            if (!block && !this.IsAsync)
            {
                this.EmitTempVars(pos);
            }

            if (analyzer.UsedVariables.Count == 0)
            {
                if (!this.Emitter.ForbidLifting)
                {
                    var name = "f" + (this.Emitter.NamedFunctions.Count + 1);
                    var code = this.Emitter.Output.ToString().Substring(savedPos);
                    var pair = this.Emitter.NamedFunctions.FirstOrDefault(p => p.Value == code);

                    if (pair.Key != null && pair.Value != null)
                    {
                        name = pair.Key;
                    }
                    else
                    {
                        this.Emitter.NamedFunctions.Add(name, code);
                    }

                    this.Emitter.Output.Remove(savedPos, this.Emitter.Output.Length - savedPos);
                    this.Emitter.Output.Insert(savedPos, JS.Vars.D_ + "." + BridgeTypes.ToJsName(this.Emitter.TypeInfo.Type, this.Emitter, true) + "." + name);
                }

                this.Emitter.ResetLevel(oldLevel);
            }

            this.Emitter.ForbidLifting = oldLifting;


            var methodDeclaration = this.Body.GetParent <MethodDeclaration>();

            if (this.Emitter.ThisRefCounter > savedThisCount || this.IsAsync && methodDeclaration != null && !methodDeclaration.HasModifier(Modifiers.Static))
            {
                this.Emitter.Output.Insert(savedPos, JS.Funcs.BRIDGE_BIND + "(this, ");
                this.WriteCloseParentheses();
            }

            if (capturedVariables != null && capturedVariables.Length > 0)
            {
                this.WriteSemiColon(true);
                this.EndBlock();
                this.Write(")(" + string.Join(", ", capturedVariables) + ")");
            }

            this.PopLocals();
            this.ClearLocalsMap(prevMap);
            this.ClearLocalsNamesMap(prevNamesMap);
        }