Example #1
0
        public JsNode VisitLambdaResolveResult(LambdaResolveResult res)
        {
            //var prmTypes = res.Parameters.Select(t => t.Type).ToArray();
            //var retType = res.GetInferredReturnType(prmTypes);
            //var conv = res.IsValid(prmTypes, retType, CSharpConversions.Get(Project.Compilation));
            //return Visit(conv);
            var func = new JsFunction {
                Parameters = res.Parameters.Select(t => JsIdentifier(t.Name)).ToList()
            };
            var    body = res.Body;
            JsNode body2;
            var    info = res.GetInfo();

            if (body.GetType() == typeof(ResolveResult) && body.Type.IsVoid())
            {
                var x       = res.GetType().GetProperty("BodyExpression", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(res, null);
                var astNode = (AstNode)x;
                body2 = Visit(astNode);
            }
            else
            {
                body2 = Visit(res.Body);
            }
            var currentMember = res.GetCurrentMember();
            var delType       = info.ConversionTargetType;

            if (body2 is JsExpression)
            {
                var         delMethod = delType.GetDelegateInvokeMethod();
                JsStatement st        = new JsReturnStatement {
                    Expression = (JsExpression)body2
                };
                if (delMethod != null && delMethod.ReturnType.IsVoid())
                {
                    st = new JsExpressionStatement {
                        Expression = (JsExpression)body2
                    }
                }
                ;

                func.Block = new JsBlock {
                    Statements = new List <JsStatement> {
                        st
                    }
                };
            }
            else if (body2 is JsBlock)
            {
                func.Block = (JsBlock)body2;
            }
            if (delType == null || currentMember == null)
            {
                Log.Warn(res.GetFirstNode(), "Cannot resolve delegate type / parent method");
                return(func);
            }
            else
            {
                return(CreateJsDelegateIfNeeded(func, currentMember, delType, true));
            }
        }
Example #2
0
 public virtual JsNode Visit(JsExpressionStatement node)
 {
     return(DefaultVisit(node, x =>
     {
         x.Expression = (JsExpression)x.Expression.Accept(this);
         return x;
     }));
 }
Example #3
0
 public object VisitExpressionStatement(JsExpressionStatement statement, bool addNewline)
 {
     VisitExpression(statement.Expression, statement.Expression is JsFunctionDefinitionExpression);
     _cb.Append(";");
     if (addNewline)
     {
         _cb.AppendLine();
     }
     return(null);
 }
 public object VisitExpressionStatement(JsExpressionStatement statement, bool addNewline)
 {
     VisitExpression(statement.Expression, ParenthesizeExpressionAsStatement(statement.Expression));
     _cb.Append(";");
     if (addNewline)
     {
         _cb.AppendLine();
     }
     return(null);
 }
Example #5
0
 public virtual void Visit(JsExpressionStatement node)
 {
     DefaultVisit(node);
     node.Expression.Accept(this);
 }
Example #6
0
        public JsNode VisitMethodGroupResolveResult(MethodGroupResolveResult res)
        {
            var     info = res.GetInfo();
            IMethod me;

            if (info != null && info.Conversion != null && info.Conversion.Method != null)
            {
                me = info.Conversion.Method;
            }
            else //happens when invoking a method with overloads, and a parameter is dynamic
            {
                var list = res.Methods.ToList();
                if (list.Count == 0)
                {
                    throw new Exception("Method group not resolved to any method");
                }
                else if (list.Count == 1)
                {
                    me = list[0];
                }
                else
                {
                    me = list[0];
                }
                //TODO: verify all methods has the same js name
            }
            var          isExtensionMethodStyle = me.IsExtensionMethod && !(res.TargetResult is TypeResolveResult) && info != null && info.Conversion != null && info.Conversion.DelegateCapturesFirstArgument;//TODO: IsExtensionMethodStyle(new CsInvocationExpression { entity = me, expression = node });
            JsExpression firstPrm = null;

            if (isExtensionMethodStyle)
            {
                firstPrm = (JsExpression)Visit(res.TargetResult);
            }
            var          node2 = SkJs.EntityToMember(me);
            JsExpression node3;
            JsExpression instanceContext = null;

            if (me.IsStatic || res.TargetResult == null) //getting ThisResolveResult even on static methods, getting TargetResult=null when MethodGroupResolveResult when using delegates
            {
                node3 = node2;
            }
            else
            {
                instanceContext = VisitExpression(res.TargetResult);
                node3           = instanceContext.Member(node2);
            }

            if (info != null && (instanceContext != null || firstPrm != null))
            {
                if (info.ConversionTargetType != null && !UseNativeFunctions(info.ConversionTargetType))//delegate type
                {
                    var parentMethod = info.Nodes.FirstOrDefault().GetCurrentMethod();
                    if (parentMethod == null || !Sk.ForceDelegatesAsNativeFunctions(parentMethod))
                    {
                        if (parentMethod == null)
                        {
                            Log.Warn(info.Nodes.FirstOrDefault(), "GetParentMethod() returned null");
                        }
                        var func = (JsExpression)node2;
                        if (instanceContext != null)
                        {
                            node3 = CreateJsDelegate(instanceContext, func);
                        }
                        else if (firstPrm != null)
                        {
                            node3 = CreateJsExtensionDelegate(firstPrm, func);
                        }
                    }
                }
            }

            // 其实以下的处理,也可以改代码,改成 Lambda 写法即可
            // 这样子引用的并不是同一个函数,可能会造成内存泄露
            if (res.TypeArguments.Count > 0 && info.Conversion.IsImplicit && me is SpecializedMethod)
            {
                var delegateFunc = node3 as JsInvocationExpression;

                var sme  = (SpecializedMethod)me;
                var pars = sme.TypeArguments.Select(type => SkJs.EntityTypeRefToMember(type, false)).ToList();
                pars.AddRange(sme.Parameters.Select(t => new JsCodeExpression
                {
                    Code = JsIdentifier(t.Name),
                }));
                var body = delegateFunc == null?node3.Invoke(pars.ToArray()) : delegateFunc.Arguments[1].Invoke(pars.ToArray());

                var func = new JsFunction()
                {
                    Parameters = sme.Parameters.Select(t => JsIdentifier(t.Name)).ToList(),
                };
                JsStatement st;
                if (sme.ReturnType.IsVoid())
                {
                    st = new JsExpressionStatement {
                        Expression = body
                    };
                }
                else
                {
                    st = new JsReturnStatement {
                        Expression = body
                    };
                }
                func.Block = new JsBlock {
                    Statements = new List <JsStatement> {
                        st
                    }
                };

                if (delegateFunc == null)
                {
                    node3 = func;
                }
                else
                {
                    delegateFunc.Arguments[1] = func;
                }
            }

            return(node3);
        }
Example #7
0
 public override void VisitExpressionStatement(JsExpressionStatement node)
 {
     node.Expression.Accept(this);
     output.AppendLine(";");
 }
        private JsBlockStatement GenerateUsingBlock(LocalResolveResult resource, Expression aquisitionExpression, DomRegion tempVariableRegion, JsBlockStatement body)
        {
            SetRegion(aquisitionExpression.GetRegion());
            var boolType = _compilation.FindType(KnownTypeCode.Boolean);
            var systemIDisposable = _compilation.FindType(KnownTypeCode.IDisposable);
            var disposeMethod = systemIDisposable.GetMethods().Single(m => m.Name == "Dispose");
            var conversions = CSharpConversions.Get(_compilation);

            var compiledAquisition = CompileExpression(aquisitionExpression, true);

            var stmts = new List<JsStatement>();
            stmts.AddRange(compiledAquisition.AdditionalStatements);
            stmts.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[resource.Variable].Name, compiledAquisition.Expression)));

            bool isDynamic = resource.Type.Kind == TypeKind.Dynamic;

            if (isDynamic) {
                var newResource = CreateTemporaryVariable(systemIDisposable, tempVariableRegion);
                var castExpr = _expressionCompiler.Compile(new ConversionResolveResult(systemIDisposable, resource, conversions.ExplicitConversion(resource, systemIDisposable)), true);
                stmts.AddRange(castExpr.AdditionalStatements);
                stmts.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[newResource].Name, castExpr.Expression)));
                resource = new LocalResolveResult(newResource);
            }

            var compiledDisposeCall = _expressionCompiler.Compile(
                                          new CSharpInvocationResolveResult(
                                              new ConversionResolveResult(systemIDisposable, resource, conversions.ImplicitConversion(resource, systemIDisposable)),
                                              disposeMethod,
                                              new ResolveResult[0]
                                          ), false);
            if (compiledDisposeCall.AdditionalStatements.Count > 0)
                _errorReporter.InternalError("Type test cannot return additional statements.");

            JsStatement releaseStmt;
            if (isDynamic) {
                releaseStmt = new JsExpressionStatement(compiledDisposeCall.Expression);
            }
            else {
                // if (d != null) ((IDisposable)d).Dispose()
                var compiledTest = _expressionCompiler.Compile(new OperatorResolveResult(boolType, ExpressionType.NotEqual, resource, new ConstantResolveResult(resource.Type, null)), true);
                if (compiledTest.AdditionalStatements.Count > 0)
                    _errorReporter.InternalError("Null test cannot return additional statements.");
                releaseStmt = new JsIfStatement(compiledTest.Expression, new JsExpressionStatement(compiledDisposeCall.Expression), null);
            }

            stmts.Add(new JsTryStatement(body, null, releaseStmt));

            return new JsBlockStatement(stmts);
        }
        public override void VisitForeachStatement(ForeachStatement foreachStatement)
        {
            var ferr = (ForEachResolveResult)_resolver.Resolve(foreachStatement);
            var iterator = (LocalResolveResult)_resolver.Resolve(foreachStatement.VariableNameToken);

            var systemArray = _compilation.FindType(KnownTypeCode.Array);
            var inExpression = ResolveWithConversion(foreachStatement.InExpression);
            if (Equals(inExpression.Type, systemArray) || inExpression.Type.DirectBaseTypes.Contains(systemArray)) {
                var arrayResult = CompileExpression(foreachStatement.InExpression, true);
                _result.AddRange(arrayResult.AdditionalStatements);
                var array = arrayResult.Expression;
                if (ExpressionCompiler.IsJsExpressionComplexEnoughToGetATemporaryVariable.Process(array)) {
                    var tmpArray = CreateTemporaryVariable(ferr.CollectionType, foreachStatement.GetRegion());
                    _result.Add(new JsVariableDeclarationStatement(_variables[tmpArray].Name, array));
                    array = JsExpression.Identifier(_variables[tmpArray].Name);
                }

                var length = systemArray.GetProperties().SingleOrDefault(p => p.Name == "Length");
                if (length == null) {
                    _errorReporter.InternalError("Property Array.Length not found.");
                    return;
                }
                var lengthSem = _metadataImporter.GetPropertySemantics(length);
                if (lengthSem.Type != PropertyScriptSemantics.ImplType.Field) {
                    _errorReporter.InternalError("Property Array.Length is not implemented as a field.");
                    return;
                }

                var index = CreateTemporaryVariable(_compilation.FindType(KnownTypeCode.Int32), foreachStatement.GetRegion());
                var jsIndex = JsExpression.Identifier(_variables[index].Name);
                var body = new[] { new JsVariableDeclarationStatement(_variables[iterator.Variable].Name, JsExpression.Index(array, jsIndex)) }
                          .Concat(CreateInnerCompiler().Compile(foreachStatement.EmbeddedStatement).Statements);

                _result.Add(new JsForStatement(new JsVariableDeclarationStatement(_variables[index].Name, JsExpression.Number(0)),
                                               JsExpression.Lesser(jsIndex, JsExpression.MemberAccess(array, lengthSem.FieldName)),
                                               JsExpression.PostfixPlusPlus(jsIndex),
                                               new JsBlockStatement(body)));
            }
            else {
                var getEnumeratorCall = _expressionCompiler.Compile(ferr.GetEnumeratorCall, true);
                _result.AddRange(getEnumeratorCall.AdditionalStatements);
                var enumerator = CreateTemporaryVariable(ferr.EnumeratorType, foreachStatement.GetRegion());
                _result.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[enumerator].Name, getEnumeratorCall.Expression)));

                var moveNextInvocation = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new LocalResolveResult(enumerator), ferr.MoveNextMethod, new ResolveResult[0]), true);
                if (moveNextInvocation.AdditionalStatements.Count > 0)
                    _errorReporter.InternalError("MoveNext() invocation is not allowed to require additional statements.");

                var getCurrent = _expressionCompiler.Compile(new MemberResolveResult(new LocalResolveResult(enumerator), ferr.CurrentProperty), true);
                var preBody = getCurrent.AdditionalStatements.Concat(new[] { new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[iterator.Variable].Name, getCurrent.Expression)) }).ToList();
                var body = CreateInnerCompiler().Compile(foreachStatement.EmbeddedStatement);

                body = new JsBlockStatement(preBody.Concat(body.Statements));

                JsStatement disposer;

                var systemIDisposable = _compilation.FindType(KnownTypeCode.IDisposable);
                var disposeMethod = systemIDisposable.GetMethods().Single(m => m.Name == "Dispose");
                var conversions = CSharpConversions.Get(_compilation);
                var disposableConversion = conversions.ImplicitConversion(enumerator.Type, systemIDisposable);
                if (disposableConversion.IsValid) {
                    // If the enumerator is implicitly convertible to IDisposable, we should dispose it.
                    var compileResult = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new ConversionResolveResult(systemIDisposable, new LocalResolveResult(enumerator), disposableConversion), disposeMethod, new ResolveResult[0]), false);
                    if (compileResult.AdditionalStatements.Count != 0)
                        _errorReporter.InternalError("Call to IDisposable.Dispose must not return additional statements.");
                    disposer = new JsExpressionStatement(compileResult.Expression);
                }
                else if (enumerator.Type.GetDefinition().IsSealed) {
                    // If the enumerator is sealed and not implicitly convertible to IDisposable, we need not dispose it.
                    disposer = null;
                }
                else {
                    // We don't know whether the enumerator is convertible to IDisposable, so we need to conditionally dispose it.
                    var test = _expressionCompiler.Compile(new TypeIsResolveResult(new LocalResolveResult(enumerator), systemIDisposable, _compilation.FindType(KnownTypeCode.Boolean)), true);
                    if (test.AdditionalStatements.Count > 0)
                        _errorReporter.InternalError("\"is\" test must not return additional statements.");
                    var innerStatements = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new ConversionResolveResult(systemIDisposable, new LocalResolveResult(enumerator), conversions.ExplicitConversion(enumerator.Type, systemIDisposable)), disposeMethod, new ResolveResult[0]), false);
                    disposer = new JsIfStatement(test.Expression, new JsBlockStatement(innerStatements.AdditionalStatements.Concat(new[] { new JsExpressionStatement(innerStatements.Expression) })), null);
                }
                JsStatement stmt = new JsWhileStatement(moveNextInvocation.Expression, body);
                if (disposer != null)
                    stmt = new JsTryStatement(stmt, null, disposer);
                _result.Add(stmt);
            }
        }
        public virtual JsStatement VisitExpressionStatement(JsExpressionStatement statement, TData data)
        {
            var after = VisitExpression(statement.Expression, data);

            return(ReferenceEquals(after, statement.Expression) ? statement : new JsExpressionStatement(after));
        }
Example #11
0
 public virtual void VisitExpressionStatement(JsExpressionStatement node)
 {
 }
Example #12
0
 public void Visit(JsExpressionStatement node)
 {
     BeforeVisit(node);
     DefaultVisit(node, VisitExpressionStatement);
     AfterVisit(node);
 }
Example #13
0
 /// <summary>
 /// Equalses the specified other.
 /// </summary>
 /// <param name="other">The other.</param>
 /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
 protected bool Equals(JsExpressionStatement other) => Equals(Expression, other.Expression);