public override JsNode _VisitDelegate(ITypeDefinition ce)
        {
            var CurrentType = new JsClrType {
                Kind = JsClrTypeKind.Delegate
            };

            CurrentType.fullname = GetJsTypeName(ce);

            //Generate constructor
            var genericParams = new List <ITypeParameter>(ce.GetGenericArguments());
            var func          = new JsFunction();

            func.Parameters = genericParams.Select(t => t.Name).ToList();
            func.Parameters.Add("obj");
            func.Parameters.Add("func");
            func.Block = Js.Block();
            foreach (var ga in genericParams)
            {
                func.Block.Add(Js.This().Member(ga.Name).Assign(Js.Member(ga.Name)).Statement());
            }
            func.Block.Add(Js.Members("System.MulticastDelegate.ctor.call").Invoke(Js.This(), Js.Member("obj"), Js.Member("func")).Statement());
            CurrentType.GetDefinition(false)["ctor"] = func;
            return(OnAfterExportType(ce, CurrentType));
            //return func;

            //FullName',{ ShortName:function(T1,T2,T3,...,obj,func){this.T1=T1;....;this.construct(obj,func);},   })");
        }
Esempio n. 2
0
        public JsNode VisitUsingStatement(UsingStatement node)
        {
            var st3 = Visit(node.ResourceAcquisition);
            JsVariableDeclarationStatement stVar;

            if (st3 is JsExpression)
            {
                stVar = Js.Var("$r" + VariableResourceCounter++, (JsExpression)st3).Statement();
            }
            else
            {
                stVar = (JsVariableDeclarationStatement)st3;
            }
            var trySt = VisitStatement(node.EmbeddedStatement);
            var st2   = new JsTryStatement {
                TryBlock = trySt.ToBlock(), FinallyBlock = Js.Block()
            };

            //var resource = node.ResourceAcquisition;
            //var decl = resource as VariableDeclarationStatement;
            //if (decl == null || decl.Variables.Count == 0)
            //    throw new Exception("using statement is supported only with the var keyword in javascript. Example: using(var g = new MyDisposable()){}");
            foreach (var dr in stVar.Declaration.Declarators)
            {
                st2.FinallyBlock.Add(Js.Member(dr.Name).Member("Dispose").Invoke().Statement());
            }
            return(Js.Block().Add(stVar).Add(st2));            //TODO: get rid of block
        }
Esempio n. 3
0
 public JsBlockStatement GotoStateBlock(State newState)
 {
     return(Js.Block(
                ChangeState(newState),
                GotoTop()
                ));
 }
Esempio n. 4
0
        protected override Expression VisitBlock(BlockExpression node)
        {
            var list = new List <Js>();

            foreach (var e in node.Expressions)
            {
                Visit(e);
                list.Add(constructed);
            }

            constructed = Js.Block(list.ToArray());

            return(node);
        }
Esempio n. 5
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;
        }
Esempio n. 6
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());
            }
Esempio n. 7
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);
            }
        }
Esempio n. 8
0
        public JsNode VisitForeachStatement(ForeachStatement node)
        {
            if (node.InExpression != null)
            {
                var expRes = node.InExpression.Resolve();
                var et     = expRes.Type.GetDefinitionOrArrayType();
                //var et = node.expression.entity_typeref.GetEntityType();
                if (et != null)
                {
                    var jta = Sk.GetJsTypeAttribute(et);
                    if (jta != null && jta.NativeEnumerator)
                    {
                        var node2 = new JsForInStatement
                        {
                            Initializer = Js.Var(node.VariableName),
                            Member      = VisitExpression(node.InExpression),
                            Statement   = VisitStatement(node.EmbeddedStatement)
                        };
                        return(node2);
                    }
                    else if (jta != null && jta.NativeArrayEnumerator)
                    {
                        VariableIteratorCounter++;
                        var iteratorName    = "$i" + VariableIteratorCounter;
                        var lengthCacheName = "$l" + VariableIteratorCounter;
                        var exp2            = VisitExpression(node.InExpression);
                        var target          = exp2;
                        var targetCacheName = "$t" + VariableIteratorCounter;
                        if (exp2.NodeType != JsNodeType.MemberExpression || ((JsMemberExpression)exp2).PreviousMember != null)                        //is not simple name
                        {
                            target = Js.Member(targetCacheName);
                        }
                        var itemAccess = target.IndexerAccess(Js.Member(iteratorName));
                        var node2      = new JsForStatement();

                        node2.Condition = Js.Member(iteratorName).LessThan(Js.Member(lengthCacheName));
                        node2.Iterators = new List <JsStatement> {
                            Js.Member(iteratorName).PlusPlus().Statement(), Js.Member(node.VariableName).Assign(itemAccess).Statement()
                        };
                        if (target != exp2)                        //use target caching
                        {
                            node2.Initializers = new List <JsStatement> {
                                Js.Var(iteratorName, Js.Value(0)).AndVar(targetCacheName, exp2.Clone()).AndVar(lengthCacheName, target.Clone().Member("length")).AndVar(node.VariableName, itemAccess.Clone()).Statement()
                            };
                        }
                        else
                        {
                            node2.Initializers = new List <JsStatement> {
                                Js.Var(iteratorName, Js.Value(0)).AndVar(lengthCacheName, exp2.Clone().Member("length")).AndVar(node.VariableName, itemAccess.Clone()).Statement()
                            };
                        }
                        node2.Statement = VisitStatement(node.EmbeddedStatement);
                        return(node2);
                    }
                }
            }

            var iteratorName2 = "$it" + VariableIteratorCounter;

            VariableIteratorCounter++;
            var     node3               = Js.Var(iteratorName2, VisitExpression(node.InExpression).Member("GetEnumerator").Invoke()).Statement();
            var     whileNode           = Js.While(Js.Member(iteratorName2).Member("MoveNext").Invoke());
            var     getCurrentStatement = Js.Var(node.VariableName, Js.Member(iteratorName2).Member("get_Current").Invoke()).Statement();
            var     jsStatement         = VisitStatement(node.EmbeddedStatement);
            JsBlock block;

            if (jsStatement is JsBlock)
            {
                block = (JsBlock)jsStatement;
            }
            else
            {
                block = Js.Block().Add(jsStatement);
            }
            block.Statements.Insert(0, getCurrentStatement);
            whileNode.Statement = block;

            var block2 = Js.Block().Add(node3).Add(whileNode);

            return(block2);
        }
Esempio n. 9
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);
        }
Esempio n. 10
0
        public override void VisitUsingStatement(UsingStatementSyntax node)
        {
            var afterTry        = GetNextState();
            var newTryStatement = Js.Try();

            // Keep track of exception, if any, so we can rethrow
            var exceptionIdentifier = HoistVariable(new LiftedVariableKey("$usingex"));

            // Identifier for caught exception
            var caughtExceptionIdentifier = UniqueName("$caughtex");

            // Hoist the variable into a field
            var disposables = new List <JsExpression>();

            if (node.Declaration != null)
            {
                foreach (var variable in node.Declaration.Variables)
                {
                    var symbol     = (ILocalSymbol)Transformer.Model.GetDeclaredSymbol(variable);
                    var identifier = HoistVariable(new LiftedVariableKey(variable.Identifier, symbol));
                    var name       = identifier.GetReference();
                    disposables.Add(name);
                    CurrentState.Add(name.Assign((JsExpression)variable.Initializer.Value.Accept(Transformer)).Express());
                }
            }
            if (node.Expression != null)
            {
                var identifier = Js.Reference(UniqueName("$using"));
                disposables.Add(identifier);
                CurrentState.Add(identifier.Assign((JsExpression)node.Expression.Accept(Transformer)).Express());
            }

            var tryState = NewSubstate();

            GotoState(tryState);

            var finallyState = GetNextState();

            CurrentState = finallyState;
            foreach (var disposable in disposables)
            {
                CurrentState.Add(disposable.Member("Dispose").Invoke().Express());
            }
            CurrentState.Add(Js.If(exceptionIdentifier.GetReference().NotEqualTo(Js.Null()), Js.Throw(exceptionIdentifier.GetReference())));
            GotoState(afterTry);
            newTryStatement.Catch      = Js.Catch(Js.Variable(caughtExceptionIdentifier));
            newTryStatement.Catch.Body = Js.Block(
                new[] { exceptionIdentifier.GetReference().Assign(Js.Reference(caughtExceptionIdentifier)).Express() }
                .Concat(GotoStateStatements(finallyState))
                .ToArray()
                );

            tryState.Wrap = switchStatement =>
            {
                newTryStatement.Body = Js.Block(switchStatement);
                return(newTryStatement);
            };

            StartSubstate(tryState);
            AcceptStatement(node.Statement);
            GotoState(finallyState);
            EndSubstate();

            CurrentState = afterTry;
        }
Esempio n. 11
0
        public override void VisitTryStatement(TryStatementSyntax node)
        {
            var afterTry        = GetNextState();
            var newTryStatement = Js.Try();

            var tryState = NewSubstate();

            GotoState(tryState);

            // Keep track of exception, if any, so we can rethrow
            var exceptionIdentifier = HoistVariable(new LiftedVariableKey("$ex"));
            var exceptionVariable   = UniqueName("$caughtex");

            State finallyState = node.Finally == null ? null : GetNextState();

            // Declare a block to store all the catch statements the try statement's only catch clause. (No
            // type-specific catch clauses in Javascript
            var catchBlock = Js.Block();

            // Make sure that the exception is stored in a variable accessible to the entire state machine.
            catchBlock.Express(exceptionIdentifier.GetReference().Assign(Js.Reference(exceptionVariable)));

            foreach (var catchClause in node.Catches)
            {
                // Get the symbol that represents the exception declaration (identifier and type)
                var symbol        = Transformer.Model.GetDeclaredSymbol(catchClause.Declaration);
                var exceptionType = symbol == null ? null : symbol.Type;
                if (exceptionType == null && catchClause.Declaration != null && catchClause.Declaration.Type != null)
                {
                    exceptionType = (ITypeSymbol)Transformer.Model.GetSymbolInfo(catchClause.Declaration.Type).Symbol;
                }

                // True if it is actually declaring the variable (as opposed to a catch clause that specifies
                // merely an exception type
                var hasDeclaration = catchClause.Declaration.Identifier.Kind() != SyntaxKind.None;

                // A variable to store the new unique identifier to store the exception
                IJsDeclaration newIdentifier;

                // Hoist the variable into a field
                if (hasDeclaration)
                {
                    newIdentifier = HoistVariable(new LiftedVariableKey(catchClause.Declaration.Identifier, symbol));
                }
                else
                {
                    newIdentifier = HoistVariable(new LiftedVariableKey(SyntaxFactory.Identifier("ex")));
                }

                // Collect all the catch statements into the catchState by making that state current
                var catchState = GetNextState();
                CurrentState = catchState;
                AcceptStatement(catchClause.Block);

                // Add onto the catch state some commands to go to the next state.
                if (finallyState != null)
                {
                    GotoState(finallyState);
                }
                else
                {
                    GotoState(afterTry);
                }

                // Create the statements that will live in the actual catch handler, which directs the logic
                // to the actual catch state and also stores the exception in the correct identifier.
                var thisCatchStatements = Js.Block();
                thisCatchStatements.Express(newIdentifier.SetReference().Assign(exceptionIdentifier.GetReference()));

                // Apply filter if present
                if (catchClause.Filter != null)
                {
                    var filter = (JsExpression)catchClause.Filter.FilterExpression.Accept(Transformer);
                    thisCatchStatements.Add(Js.If(filter, Js.Block(GotoStateStatements(catchState))));
                }
                else
                {
                    thisCatchStatements.AddRange(GotoStateStatements(catchState));
                }

                // Only do the above if the current exception is of the type expected by the catch handler.
                var condition = Idioms.Is(exceptionIdentifier.GetReference(), exceptionType);
                catchBlock.Add(Js.If(condition, thisCatchStatements));
            }
            if (node.Finally != null)
            {
                // Collect the statements of the finally block into the finally state
                CurrentState = finallyState;
                AcceptStatement(node.Finally.Block);

                // If the exception object is not null, then rethrow it.  In other words, if this is a finally
                // clause that has responded to an exception, we need to propagate the exception rather than
                // continue after the try statement.  Otherwise, go to the code after the try block.
                CurrentState.Add(Js.If(exceptionIdentifier.GetReference().NotEqualTo(Js.Null()),
                                       Js.Throw(exceptionIdentifier.GetReference()),
                                       Js.Block(GotoStateStatements(afterTry))));

                // Finally, at the very end of the catch clause (and we can only get here if the logic didn't break
                // out as it would with the logic in the catch handlers) go to the finally state.
                catchBlock.AddRange(GotoStateStatements(finallyState).ToArray());
            }
            catchBlock.Add(Js.Throw(exceptionIdentifier.GetReference()));

            newTryStatement.Catch      = Js.Catch(Js.Variable(exceptionVariable));
            newTryStatement.Catch.Body = catchBlock;
            tryState.Wrap = switchStatement =>
            {
                newTryStatement.Body = Js.Block(switchStatement);
                return(newTryStatement);
            };

            StartSubstate(tryState);
            AcceptStatement(node.Block);
            if (node.Finally != null)
            {
                GotoState(finallyState);
            }
            else
            {
                GotoState(afterTry);
            }
            EndSubstate();

            CurrentState = afterTry;
        }