Exemplo n.º 1
0
        protected override Expression VisitLambda <T>(Expression <T> node)
        {
            Visit(node.Body);

            constructed = Js.Function(node.Name, new[] { Js.Return(constructed) }, node.Parameters.Select(p => p.Name).ToArray());

            return(node);
        }
Exemplo n.º 2
0
        protected override void OnBaseStateGenerated()
        {
            var lastStatement = CurrentState.Statements.LastOrDefault();

            if (lastStatement is JsContinueStatement || lastStatement is JsBreakStatement || lastStatement is JsReturnStatement)
            {
                return;
            }
            CurrentState.Add(Js.Return(Js.Primitive(false)));
        }
Exemplo n.º 3
0
 public static JsReturnStatement GenerateYieldReturnStatement(IMethod me)
 {
     //JsReturnStatement node2;
     //if (me != null && me.ReturnType != null && me.ReturnType.FullName.StartsWith("System.Collections.Generic.IEnumerator"))
     //    node2 = Js.Return(Js.Member("$yield").Member("GetEnumerator").Invoke());
     //else
     //    node2 = Js.Return(Js.Member("$yield"));
     //return node2;
     return(Js.Return());
 }
Exemplo n.º 4
0
        void YieldReturnInCurrentStep(JsExpression item)
        {
            var result    = Js.Value(true);
            var stepIndex = Steps.Count - 1;

            AddToCurrentStep(Js.This().Member("_current").Assign(item).Statement());
            AddToCurrentStep(_state().Assign(Js.Value(stepIndex + 1)).Statement());
            AddToCurrentStep(Js.Member("result").Assign(result).Statement());
            AddToCurrentStep(Js.Return(result));
        }
Exemplo n.º 5
0
 public override JsNode Visit(JsReturnStatement node)
 {
     escapeStatements.Add(new EscapeStatement {
         Type = Return
     });
     return(Js.Return(Js.Object(
                          Js.Item(EscapeTypeField, Js.Primitive(Return)),
                          Js.Item(EscapeValueField, node.Expression != null ? node.Expression : Js.Null()),
                          Js.Item(EscapeDepthField, Js.Primitive(loopDepth))
                          ).Compact()));
 }
Exemplo n.º 6
0
 public override JsNode Visit(JsBreakStatement node)
 {
     escapeStatements.Add(new EscapeStatement {
         Type = Break, Label = node.Label
     });
     return(Js.Return(Js.Object(
                          Js.Item(EscapeTypeField, Js.Primitive(Break)),
                          Js.Item(EscapeLabelField, node.Label != null ? Js.Primitive(node.Label) : Js.Null()),
                          Js.Item(EscapeDepthField, node.Label != null ? Js.Primitive(transformer.GetLabelDepth(node.Label)) : Js.Primitive(0))
                          ).Compact()));
 }
Exemplo n.º 7
0
        private JsNode ImportAttributeValue(ResolveResult res)
        {
            var node = AstNodeConverter.Visit(res);

            if (node.NodeType == JsNodeType.InvocationExpression)
            {
                var exp = (JsInvocationExpression)node;
                var me  = exp.Member as JsMemberExpression;
                if (me != null && me.Name == "Typeof")
                {
                    node = Js.Function().AddStatements(Js.Return(exp));
                }
            }
            return(node);
        }
Exemplo n.º 8
0
        public void SetResult(ExpressionSyntax result = null)
        {
            var setResult = Js.Reference(builder).Member("SetResult");

            if (result != null)
            {
                var statement = setResult.Invoke((JsExpression)result.Accept(Transformer)).Express();
                CurrentState.Add(statement);
            }
            else
            {
                CurrentState.Add(setResult.Invoke().Express());
            }
            CurrentState.Add(Js.Return());
        }
Exemplo n.º 9
0
        public void Process()
        {
            AfterFunction = BeforeFunction;
            SetParents(BeforeFunction.Block);
            foreach (var me in BeforeFunction.Block.Descendants <JsMemberExpression>().ToList())
            {
                if (me.PreviousMember == null && me.NodeType == JsNodeType.MemberExpression)
                {
                    me.PreviousMember = Js.This();
                }
            }

            BeginNewStep();
            ProcessStatement(BeforeFunction.Block);
            BeforeFunction.Block.Statements.Clear();

            var func = new JsFunction {
                Block = new JsBlock {
                    Statements = new List <JsStatement>()
                }
            };
            var i = 0;

            func.Block.Statements.Add(Js.Var("result").Statement());
            var stSwitch = Js.Switch(_state());
            var lastStep = Js.Block().Add(_state().Assign(Js.Value(Steps.Count)).Statement()).Add(new JsBreakStatement());

            Steps.Add(new YieldStep {
                Statements = { lastStep }
            });
            foreach (var step in Steps)
            {
                stSwitch.Case(Js.Value(i), step.Statements);
                i++;
            }
            func.Block.Statements.Add(stSwitch);
            func.Block.Statements.Add(Js.Member("result").Assign(Js.Value(false)).Statement());
            func.Block.Statements.Add(Js.Return(Js.Member("result")));

            BeforeFunction.Block.Statements.Add(Js.Return(Js.New(Js.Member("CustomEnumerable"), func)));
            return;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Wraps a setter invocation with a js function that returns the setter value back, if another assignment operation occurs
        /// var x = contact.Name = "Shooki";
        /// var x = contact.setName("Shooki"); //error
        /// var x = (function(arg){contact.setName(arg);return arg;}).call(this, "Shooki");
        /// </summary>
        /// <param name="res"></param>
        /// <param name="node2"></param>
        /// <returns></returns>
        internal JsNode WrapSetterToReturnValueIfNeeded(OperatorResolveResult res, JsNode node2)
        {
            var node3 = node2 as JsInvocationExpression;

            if (node3 == null)
            {
                return(node2);
            }

            if (RequiresWrapSetterToReturnValue(res))
            {
                var lastArg = node3.Arguments.Last();
                var prmName = "$p" + ParameterNameCounter++;
                node3.Arguments[node3.Arguments.Count - 1] = Js.Member(prmName);

                var func = Js.Function(prmName).Add(((JsExpression)node2).Statement());
                func.Add(Js.Return(Js.Member(prmName)));
                node2 = WrapFunctionAndInvoke(res, func, lastArg);
            }
            return(node2);
        }
Exemplo n.º 11
0
        private JsStatement TransformBody(JsStatement body)
        {
            var block = body is JsBlockStatement ? (JsBlockStatement)body : Js.Block(body);

            if (!escapeStatements.Any())
            {
                return(Js.Express(idioms.Wrap(block)));
            }
            else
            {
                if (!(block.Statements.Last() is JsReturnStatement))
                {
                    block.Return(Js.Object(Js.Item(EscapeTypeField, Js.Primitive(0))).Compact());
                }
                var wrapped    = idioms.Wrap(block);
                var outerBlock = new JsBlockStatement();
                var loopResult = outerBlock.Local("$loopResult", wrapped);
                if (escapeStatements.Any(x => x.Type == Return))
                {
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Return)),
                                  Js.Return(loopResult.GetReference().Member(EscapeValueField)));
                }
                if (escapeStatements.Any(x => x.Type == Continue))
                {
                    var         escapes = escapeStatements.Where(x => x.Type == Continue).Distinct();
                    JsStatement ifTrue;
                    if (!escapes.Any(x => x.Label != null))
                    {
                        ifTrue = Js.Continue();
                    }
                    else
                    {
                        ifTrue = Js.Switch(
                            loopResult.GetReference().Member(EscapeLabelField),
                            escapes
                            .Where(x => x.Label == null)
                            .Select(x => Js.Section(Js.Null()).Statement(Js.Continue()))
                            .Concat(escapes
                                    .Where(x => x.Label != null && transformer.GetLabelDepth(x.Label) == loopDepth)
                                    .Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Continue(x.Label))))
                            .Concat(new[] { Js.Section(Js.DefaultLabel()).Statements(Js.Return(loopResult.GetReference())) })
                            .ToArray());
                    }
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Continue)),
                                  ifTrue);
                }
                if (escapeStatements.Any(x => x.Type == Break))
                {
                    var         escapes = escapeStatements.Where(x => x.Type == Break).Distinct();
                    JsStatement ifTrue;
                    if (!escapes.Any(x => x.Label != null))
                    {
                        ifTrue = Js.Break();
                    }
                    else
                    {
                        ifTrue = Js.Switch(loopResult.GetReference().Member(EscapeLabelField),
                                           escapes.Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Break(x.Label))).ToArray());
                    }
                    outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Break)),
                                  ifTrue);
                }
                return(outerBlock);
            }
        }
Exemplo n.º 12
0
        public JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res)
        {
            if (res.Type.Kind == TypeKind.Delegate)
            {
                return(Visit(res.Arguments.Single()));
            }
            var me    = (IMethod)res.Member;
            var meAtt = Sk.GetJsMethodAttribute(me);
            var ce    = me.GetDeclaringTypeDefinition();
            var att   = ce == null ? null : ce.GetJsTypeAttribute();

            if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null))
            {
                var jtfn  = ce == null ? null : Sk.GetJsonTypeFieldName(ce);
                var node2 = VisitInvocationResolveResult(res);
                var json  = Importer.InitializersToJson(res.InitializerStatements, res.Type);
                if (jtfn != null)
                {
                    var x = json as JsJsonObjectExpression;
                    if (x != null)
                    {
                        x.Add(jtfn, SkJs.EntityTypeRefToMember(res.Type));
                    }
                }
                return(json);
            }
            else
            {
                var invokeExp = (JsInvocationExpression)VisitInvocationResolveResult(res);
                var newExp    = new JsNewObjectExpression {
                    Invocation = invokeExp
                };
                JsExpression finalExp;
                if (meAtt != null && meAtt.OmitNewOperator)
                {
                    finalExp = invokeExp;
                }
                else
                {
                    finalExp = newExp;
                }

                if (meAtt != null && meAtt.JsonInitializers)
                {
                    var json = Importer.InitializersToJson(res.InitializerStatements, res.Type);
                    invokeExp.Arguments.Add(json);
                }
                else if (res.InitializerStatements.IsNotNullOrEmpty())
                {
                    var func = Js.Function();

                    var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList();
                    //var init1 = res.InitializerStatements[0];

                    var target  = AstNodeConverter.FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult;
                    var varName = Importer.Initializers[target];
                    func.Add(Js.Var(varName, finalExp).Statement());

                    foreach (var init in inits2)
                    {
                        var exp = ((JsExpression)init);
                        func.Add(exp.Statement());
                    }
                    func.Add(Js.Return(Js.Member(varName)));
                    finalExp = Importer.WrapFunctionAndInvoke(res, func);
                }

                return(finalExp);
            }
        }
Exemplo n.º 13
0
 public JsNode VisitReturnStatement(ReturnStatement node)
 {
     return(Js.Return(VisitExpression(node.Expression)));
 }
Exemplo n.º 14
0
        protected JsBlock ExportMethodBody(IMethod me)
        {
            if (CompilerConfiguration.Current.EnableLogging)
            {
                Log.Debug("JsTypeImporter: Visit Method: " + me.ToString());
            }
            var nativeCode = Sk.GetNativeCode(me);

            if (nativeCode != null)
            {
                var block = Js.Block().Add(Js.CodeStatement(nativeCode)); //TODO: double semicolon?
                return(block);
            }
            var def = me.GetDefinition();

            if (def == null || def.IsNull)
            {
                if (me.IsAutomaticEventAccessor())
                {
                    if (me.IsEventAddAccessor())
                    {
                        var node = GenerateAutomaticEventAccessor((IEvent)me.GetOwner(), false);
                        return(node.Block);
                    }
                    else if (me.IsEventRemoveAccessor())
                    {
                        var node = GenerateAutomaticEventAccessor((IEvent)me.GetOwner(), true);
                        return(node.Block);
                    }
                }
                else if (me.IsAutomaticPropertyAccessor())
                {
                    var bf = Js.Member(AutoPropertyPrefix + SkJs.GetEntityJsName(me.AccessorOwner));
                    if (!me.IsStatic)
                    {
                        bf.PreviousMember = Js.This();
                    }
                    else if (!Sk.IsGlobalMethod(me))
                    {
                        bf.PreviousMember = SkJs.EntityToMember(me.DeclaringTypeDefinition);
                    }
                    if (me.IsGetter())
                    {
                        return(Js.Block().Add(Js.Return(bf)));
                    }
                    else
                    {
                        return(Js.Block().Add(bf.Assign(Js.Member("value")).Statement()));
                    }
                }
                return(null);
            }
            var block2 = (JsBlock)AstNodeConverter.Visit(def);

            block2.ContainsYield = false;
            if (def.Descendants.OfType <YieldReturnStatement>().FirstOrDefault() != null)
            {
                block2.ContainsYield = true;
                if (!AstNodeConverter.SupportClrYield)
                {
                    if (block2.Statements == null)
                    {
                        block2.Statements = new List <JsStatement>();
                    }
                    //block2.Statements.Insert(0, Js.Var("$yield", Js.NewJsonArray()).Statement());
                    //block2.Statements.Add(AstNodeConverter.GenerateYieldReturnStatement(me));
                }
            }
            return(block2);
        }
Exemplo n.º 15
0
        void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JsInvocationExpression node2)
        {
            var target = res.TargetResult as ThisResolveResult;

            if (target != null && target.CausesNonVirtualInvocation) //base.
            {
                //var info = res.GetInfo();
                //var node = info.Nodes.FirstOrDefault();
                var ce = target.Type;// node.FindThisEntity();
                if (ce != null && Sk.IsExtJsType(ce.GetDefinitionOrArrayType()))
                {
                    node2.Member = Js.This().Member("callParent");
                    if (node2.Arguments.IsNotNullOrEmpty())
                    {
                        node2.Arguments = new List <JsExpression> {
                            Js.NewJsonArray(node2.Arguments.ToArray())
                        }
                    }
                    ;
                    //var me2 = (node2.Member as JsMemberExpression);
                    //me2.Name = "callParent";
                    return;
                }
                IMethod me2;
                var     me = res.Member;
                if (me is IProperty)
                {
                    me2 = ((IProperty)me).Getter;
                }
                else if (me is IMethod)
                {
                    me2 = (IMethod)res.Member;
                }
                else
                {
                    throw new Exception("Can't resolve method from member: " + res.Member);
                }
                var member = SkJs.EntityMethodToJsFunctionRef(me2);
                member       = member.Member("call");
                node2.Member = member;
                if (node2.Arguments == null)
                {
                    node2.Arguments = new List <JsExpression>();
                }
                node2.Arguments.Insert(0, Js.This());
            }
        }

        void ProcessByRefs1()
        {
            ByRefs       = new List <ByReferenceResolveResult>();
            ByRefIndexes = new List <int>();
            RefToRefs    = new List <int>();
            var c = 0;

            foreach (var bin in PrmBindings)
            {
                var binding = bin.Binding;
                var byRef   = binding.CallResult as ByReferenceResolveResult;
                if (byRef == null)
                {
                    c++;
                    continue;
                }
                var x = byRef.ElementResult as LocalResolveResult;
                if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference)
                {
                    if (binding.Parameter.IsRef || binding.Parameter.IsOut)
                    {
                        RefToRefs.Add(c);
                    }
                    c++;
                    continue;
                }
                ByRefs.Add(byRef);
                ByRefIndexes.Add(c);
                c++;
            }
        }

        void ProcessByRefs2()
        {
            var c = 0;

            for (var i = 0; i < Node2.Arguments.Count; i++)
            {
                if (Node2.Arguments[i] is JsMemberExpression)
                {
                    JsMemberExpression jsmex = Node2.Arguments[i] as JsMemberExpression;
                    if (RefToRefs.Contains(i))
                    {
                        Node2.Arguments[i] = jsmex.PreviousMember; //remove the .Value ref wrapper
                    }
                    else if (ByRefIndexes.Contains(i))
                    {
                        Node2.Arguments[i] = Js.Member(RefIndexToName(c));
                        c++;
                    }
                }
                else if (Node2.Arguments[i] is JsIndexerAccessExpression)
                {
                    if (ByRefIndexes.Contains(i))
                    {
                        Node2.Arguments[i] = Js.Member(RefIndexToName(c));
                        c++;
                    }
                }
            }
        }

        void ProcessByRefs3()
        {
            if (ByRefs.IsNotNullOrEmpty())
            {
                var func = Js.Function();

                //It must assigned to a temporary variable, because typed arrays do not acceppt json.
                //调整原来使用临时对象.Value的赋值方式,修改为Object.defineProperty定义get|set方法的实现
                //临时对象统一调用jsclr里的$Ref方法进行创建
                for (var i = 0; i < ByRefs.Count; i++)
                {
                    var byRef = ByRefs[i];
                    var expr  = VisitExpression(byRef);
                    if (expr is JsMemberExpression)
                    {
                        var memberExpr = expr as JsMemberExpression;
                        if (memberExpr.PreviousMember != null)
                        {
                            var refFuncInvoke = new JsInvocationExpression
                            {
                                Member = new JsMemberExpression {
                                    Name = "$Ref"
                                },
                                Arguments = new List <JsExpression> {
                                    memberExpr.PreviousMember, Js.String(memberExpr.Name)
                                }
                            };
                            func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                        }
                        else
                        {
                            //如果是局部变量的话使用旧实现方式
                            var refFuncInvoke = new JsInvocationExpression
                            {
                                Member = new JsMemberExpression {
                                    Name = "$Ref"
                                },
                                Arguments = new List <JsExpression> {
                                    Js.Member("null"), memberExpr
                                }
                            };
                            func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                        }
                    }
                    else if (expr is JsIndexerAccessExpression)
                    {
                        var indexerExpr   = expr as JsIndexerAccessExpression;
                        var indexArg      = indexerExpr.Arguments[0];
                        var refFuncInvoke = new JsInvocationExpression
                        {
                            Member = new JsMemberExpression {
                                Name = "$Ref"
                            },
                            Arguments = new List <JsExpression> {
                                indexerExpr.Member, indexArg
                            }
                        };
                        func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement());
                    }
                }

                func.Add(Js.Var("$res", Node2).Statement());

                for (var i = 0; i < ByRefs.Count; i++)
                {
                    var byRef      = ByRefs[i];
                    var memberExpr = VisitExpression(byRef) as JsMemberExpression;
                    if (memberExpr != null && memberExpr.PreviousMember == null)
                    {
                        func.Add(memberExpr.Assign(Js.Member(RefIndexToName(i)).Member("Value")).Statement());
                    }
                }

                func.Add(Js.Return(Js.Member("$res")));
                Node2 = Importer.WrapFunctionAndInvoke(Res, func);
            }
        }
Exemplo n.º 16
0
            public override JsNode VisitAwaitExpression(AwaitExpressionSyntax node)
            {
                var operand = (JsExpression)node.Expression.Accept(this);

/*
 *              var expressionInfo = stateGenerator.Transformer.model.GetAwaitExpressionInfo(node);
 *              if (expressionInfo.GetResultMethod == null)
 *              {
 *                  var classText = node.FirstAncestorOrSelf<ClassDeclarationSyntax>().NormalizeWhitespace().ToString();
 *                  var diagnostics = model.GetDiagnostics().Select(x => x.ToString()).ToArray();
 *              }
 *
 *              var returnsVoid = expressionInfo.GetResultMethod.ReturnsVoid;
 */
                var expressionInfo    = stateGenerator.Transformer.model.GetTypeInfo(node).ConvertedType;
                var returnsVoid       = expressionInfo.SpecialType == SpecialType.System_Void;
                var operandType       = model.GetTypeInfo(node.Expression).ConvertedType;
                var awaiterMethodName = ((INamedTypeSymbol)operandType).GetMethodByName("GetAwaiter").GetMemberName();

                // Store the awaiter in a field
                var awaiterIdentifier = stateGenerator.HoistVariable(new LiftedVariableKey("$awaiter"));
                var awaiter           = awaiterIdentifier.GetReference();

                stateGenerator.CurrentState.Add(awaiter.Assign(operand.Member(awaiterMethodName).Invoke()).Express());

                var nextState = stateGenerator.InsertState();

                JsExpression result = null;

                if (!returnsVoid)
                {
                    // If the await returns a value, store it in a field
                    var resultIdentifier = stateGenerator.HoistVariable(new LiftedVariableKey("$result"));
                    result = resultIdentifier.GetReference();

                    // Make sure the field gets set from the awaiter at the beginning of the next state.
                    nextState.Add(result.Assign(awaiter.Member("GetResult").Invoke()).Express());
                }
                else
                {
                    // We still need to call GetResult even if void in order to propagate exceptions
                    nextState.Add(awaiter.Member("GetResult").Invoke().Express());
                }

                // Set the state to the next state
                stateGenerator.CurrentState.Add(stateGenerator.ChangeState(nextState));

                stateGenerator.CurrentState.Add(Js.If(
                                                    awaiter.Member("get_IsCompleted").Invoke(),

                                                    // If the awaiter is already completed, go to the next state
                                                    stateGenerator.GotoTop(),

                                                    // Otherwise await for completion
                                                    Js.Block(
                                                        // Start the async process
                                                        Js.Reference(builder)
                                                        .Member("TrueAwaitOnCompleted")
                                                        .Invoke(awaiterIdentifier.GetReference(), Js.Reference(stateMachine))
                                                        .Express(),
                                                        Js.Return()
                                                        )
                                                    ));

                stateGenerator.CurrentState = nextState;

                return(result ?? Js.Null());
            }
Exemplo n.º 17
0
        private JsBlockStatement CreateProperty(IPropertySymbol property)
        {
            var block        = new JsBlockStatement();
            var propertyName = property.GetMemberName();

            var backingField   = property.GetBackingFieldName();
            var valueParameter = Js.Parameter("value");

            block.Add(idioms.StoreInPrototype(backingField, Js.Null()));
            if (property.GetMethod != null)
            {
                block.Add(idioms.StoreInPrototype(property.GetMethod.GetMemberName(), Js.Function().Body(Js.Return(Js.This().Member(backingField)))));
            }
            if (property.SetMethod != null)
            {
                block.Add(idioms.StoreInPrototype(property.SetMethod.GetMemberName() + propertyName, Js.Function(valueParameter).Body(
                                                      Js.Assign(Js.This().Member(backingField), valueParameter.GetReference()))));
            }

            return(block);
        }