void ExportNamespace(JsUnit unit, string ns) { var Writer = new StringWriter(); if (ns.IsNotNullOrEmpty()) { var tokens = ns.Split('.'); for (var i = 0; i < tokens.Length; i++) { var ns2 = tokens.Take(i + 1).StringJoin("."); JsStatement st; if (i == 0) { st = Js.Var(ns2, Js.Json()).Statement(); } else { st = Js.Member(ns2).Assign(Js.Json()).Statement(); } var st2 = Js.If(Js.Typeof(Js.Member(ns2)).Equal(Js.String("undefined"))).Then(st); unit.Statements.Add(st2); st2.AddAnnotation(new NamespaceVerificationAnnotation { Namespace = ns2 }); //.Ex(true).NamespaceVerification = ns2; } } }
public override void VisitIfStatement(IfStatementSyntax node) { var afterIfState = GetNextState(); var ifTrueState = GetNextState(); var ifFalseState = node.Else != null?GetNextState() : null; var newIfStatement = Js.If( (JsExpression)node.Condition.Accept(Transformer), GotoStateBlock(ifTrueState)); if (node.Else != null) { newIfStatement.IfFalse = GotoStateBlock(ifFalseState); } CurrentState.Add(newIfStatement); GotoState(afterIfState); CurrentState = ifTrueState; AcceptStatement(node.Statement); GotoState(afterIfState); if (ifFalseState != null) { CurrentState = ifFalseState; AcceptStatement(node.Else.Statement); GotoState(afterIfState); } CurrentState = afterIfState; }
public void TestMethod1() { var x = Js.Variable("x"); var y = Js.Variable("y"); var t = Js.Assign( Js.Variable("fn"), Js.Function(new [] { Js.If( Js.Equality(x, y), Js.MultiplyAssign(x, y)) }, "x", "y") ); }
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()); }
public MemberConverter_Clr() { VerifyJsTypesArrayStatement = Js.If(Js.Typeof(Js.Member("JsTypes")).Equal(Js.String("undefined"))).Then(Js.Var("JsTypes", Js.NewJsonArray()).Statement()); VerifyJsTypesArrayStatement.AddAnnotation(new VerifyJsTypesArrayStatementAnnotation()); }
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; }
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; }