Exemplo n.º 1
0
        public override void VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpressionSyntax node)
        {
            var jsBlock = new JsBlockStatement();

            var model = Context.Instance.Compilation.GetSemanticModel(node.SyntaxTree);
            var classType = (INamedTypeSymbol)ModelExtensions.GetDeclaredSymbol(model, node);
            if (processedTypes.Contains(classType))
                return;
            processedTypes.Add(classType);

            JsBlockStatement typeInitializer;
            JsBlockStatement staticInitializer;
            jsBlock.Aggregate(idioms.CreateTypeFunction(classType, out typeInitializer, out staticInitializer));
            
            // Create default constructor
            var constructorBlock = new JsBlockStatement();
            constructorBlock.Express(idioms.InvokeMethodAsThis(classType.BaseType.InstanceConstructors.Single(x => x.Parameters.Count() == 0)));
            var constructor = classType.InstanceConstructors.Single();

            typeInitializer.Add(idioms.StoreInPrototype(constructor.GetMemberName(), Js.Reference(SpecialNames.DefineConstructor).Invoke(
                Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                Js.Function().Body(constructorBlock))));
            
            foreach (var property in classType.GetMembers().OfType<IPropertySymbol>())
            {
                typeInitializer.Aggregate(CreateProperty(property));
            }

            Action action = () =>
            {
                body.Aggregate(jsBlock);
            };
            actions.Add(Tuple.Create(classType, action));
        }
		public JsSwitchSection(IEnumerable<JsExpression> values, JsStatement body) {
			if (values == null) throw new ArgumentNullException("values");
			if (body == null) throw new ArgumentNullException("body");
			Values = values.AsReadOnly();
			if (Values.Count == 0) throw new ArgumentException("Values cannot be empty", "values");
			Body = JsStatement.EnsureBlock(body);
		}
 internal JsBlockStatement Process(JsBlockStatement statement)
 {
     _allocateFinallyHandler = null;
     _makeSetCurrent = null;
     var result = Process(statement, false);
     var hoistResult = VariableHoistingVisitor.Process(result);
     return new JsBlockStatement(new[] { new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration(_stateVariableName, JsExpression.Number(0)) }.Concat(hoistResult.Item2.Select(v => new JsVariableDeclaration(v, null)))) }.Concat(hoistResult.Item1.Statements));
 }
Exemplo n.º 4
0
		public static JsBlockStatement RewriteNormalMethod(JsBlockStatement block, Func<JsExpression, bool> isExpressionComplexEnoughForATemporaryVariable, Func<string> allocateTempVariable, Func<string> allocateStateVariable, Func<string> allocateLoopLabel) {
			if (FindInterestingConstructsVisitor.Analyze(block, InterestingConstruct.Label)) {
				return new StateMachineRewriter(isExpressionComplexEnoughForATemporaryVariable, allocateTempVariable, allocateStateVariable, allocateLoopLabel).Process(block);
			}
			else {
				return block;
			}
		}
        internal IteratorStateMachine ProcessIteratorBlock(JsBlockStatement statement, Func<string> allocateFinallyHandler, Func<JsExpression, JsExpression> makeSetCurrent)
        {
            _allocateFinallyHandler = allocateFinallyHandler;
            _makeSetCurrent = makeSetCurrent;

            var result = Process(statement, true);

            var stateFinallyHandlers = _allStates.Where(s => !s.FinallyStack.IsEmpty).Select(s => Tuple.Create(s.StateValue, s.FinallyStack.Select(x => x.Item2).Reverse().ToList())).ToList();

            var hoistResult = VariableHoistingVisitor.Process(result);
            return new IteratorStateMachine(hoistResult.Item1,
                                            new[] { new JsVariableDeclaration(_stateVariableName, JsExpression.Number(0)) }.Concat(hoistResult.Item2.Select(v => new JsVariableDeclaration(v, null))),
                                            _finallyHandlers.Select(h => Tuple.Create(h.Item1, JsExpression.FunctionDefinition(new string[0], h.Item2))),
                                            stateFinallyHandlers.Count > 0 ? DisposeGenerator.GenerateDisposer(_stateVariableName, stateFinallyHandlers) : null);
        }
        private JsBlockStatement GenerateUsingBlock(LocalResolveResult resource, Expression aquisitionExpression, DomRegion tempVariableRegion, JsBlockStatement body)
        {
            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(_filename, aquisitionExpression.StartLocation, 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(_filename, aquisitionExpression.StartLocation,
                                          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.", _filename, aquisitionExpression.StartLocation);

            JsStatement releaseStmt;
            if (isDynamic) {
                releaseStmt = new JsExpressionStatement(compiledDisposeCall.Expression);
            }
            else {
                // if (d != null) ((IDisposable)d).Dispose()
                var compiledTest = _expressionCompiler.Compile(_filename, aquisitionExpression.StartLocation, 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.", _filename, aquisitionExpression.StartLocation);
                releaseStmt = new JsIfStatement(compiledTest.Expression, new JsExpressionStatement(compiledDisposeCall.Expression), null);
            }

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

            return new JsBlockStatement(stmts);
        }
Exemplo n.º 7
0
		private JsBlockStatement ProcessAsyncMethod(JsBlockStatement statement, string stateMachineMethodName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func<JsExpression, JsExpression> makeSetResult, Func<JsExpression, JsExpression> makeSetException, Func<JsExpression> getTask, Func<JsExpression, JsExpression, JsExpression> bindToContext) {
			_stateMachineMethodName = stateMachineMethodName;
			_doFinallyBlocksVariableName = doFinallyBlocksVariableName;
			_makeSetResult = taskCompletionSource != null ? makeSetResult : null;
			_needDoFinallyBlocksVariable = new HasAwaitInsideTryWithFinallyVisitor().Analyze(statement);

			var result = Process(statement, isIteratorBlock: false, isAsync: true);
			var hoistResult = VariableHoistingVisitor.Process(result);

			string catchVariable = _allocateTempVariable();

			JsStatement body;
			if (taskCompletionSource != null && (statement.Statements.Count == 0 || IsNextStatementReachable(statement.Statements[statement.Statements.Count - 1]))) {	// If we return the task, and if we risk falling out of the original method, we need to add a setResult call.
				body = JsStatement.Block(hoistResult.Item1.Statements.Concat(new JsStatement[] { makeSetResult(null) }));
			}
			else {
				body = hoistResult.Item1;
			}

			if (taskCompletionSource != null)
				body = JsStatement.Try(body, JsStatement.Catch(catchVariable, JsStatement.Block(makeSetException(JsExpression.Identifier(catchVariable)))), null);

			IEnumerable<JsVariableDeclaration> declarations = new[] { JsStatement.Declaration(_stateVariableName, JsExpression.Number(0)) };
			if (taskCompletionSource != null)
				declarations = declarations.Concat(new[] { taskCompletionSource });
			declarations = declarations.Concat(hoistResult.Item2.Select(v => JsStatement.Declaration(v, null)));

			if (_needDoFinallyBlocksVariable)
				body = JsStatement.Block(new[] { JsStatement.Var(_doFinallyBlocksVariableName, JsExpression.True) }.Concat(body is JsBlockStatement ? ((JsBlockStatement)body).Statements : (IEnumerable<JsStatement>)new[] { body }));

			var stateMachine = JsExpression.FunctionDefinition(new string[0], body);
			var boundStateMachine = UsesThisVisitor.Analyze(stateMachine.Body) ? bindToContext(stateMachine, JsExpression.This) : stateMachine;
			
			IEnumerable<JsStatement> stmts = new JsStatement[] { JsStatement.Var(declarations),
			                                                     JsStatement.Var(stateMachineMethodName, boundStateMachine),
			                                                     JsExpression.Invocation(JsExpression.Identifier(stateMachineMethodName))
			                                                   };
			if (taskCompletionSource != null)
				stmts = stmts.Concat(new[] { JsStatement.Return(getTask()) });

			return JsStatement.Block(stmts);
		}
Exemplo n.º 8
0
        private JsExpression CreateAttributes(ISymbol symbol)
        {
            var result = Js.Array();
            foreach (var attribute in symbol.GetAttributes().Where(x => x.AttributeClass.IsExported()))
            {
                if (!attribute.AttributeClass.IsExported())
                    continue;

                var attributeInstance = CreateObject(attribute.AttributeConstructor,
                    attribute.ConstructorArguments.Select(x => GetConstantValue(x.Type, x.Value)).ToArray());
                if (attribute.NamedArguments.Any())
                {
                    // Wrap initialization in an anonymous function
                    var initializerBlock = new JsBlockStatement();
                    var variable = Js.Variable("$obj$", attributeInstance);
                    initializerBlock.Local(variable);

                    // Process named arguments
                    foreach (var argument in attribute.NamedArguments)
                    {
                        initializerBlock.Express(variable.GetReference().Member("set_" + argument.Key).Invoke(Js.Literal(argument.Value)));
                    }

                    // Return obj
                    initializerBlock.Return(Js.Reference("$obj$"));

                    attributeInstance = Wrap(initializerBlock);
                }
                result.Elements.Add(attributeInstance);
            }
            return MakeArray(result, Context.Instance.Compilation.CreateArrayTypeSymbol(Context.Instance.Attribute));
        }
Exemplo n.º 9
0
        public JsBlockStatement CreateTypeFunction(INamedTypeSymbol classType, out JsBlockStatement typeInitializer, out JsBlockStatement staticInitializer)
        {
            var isBuiltIn = classType.IsBuiltIn();
            var extraBuiltInExports = classType.GetExtraBuiltInExports();
            var explicitBaseType = classType.GetAttributeValue<ITypeSymbol>(Context.Instance.JsAttributeType, "BaseType");
            var baseType = 
                explicitBaseType != null ? Type(explicitBaseType) :
                Equals(classType, Context.Instance.ObjectType) ? Js.Reference("Object") : 
                classType.BaseType == null ? Type(Context.Instance.ObjectType) : 
                Js.Reference(classType.BaseType.GetTypeName());
//                classType.BaseType.HasGenericParameters() ? Js.Reference(classType.BaseType.GetTypeName()) :
//                Type(classType.BaseType);

            var block = new JsBlockStatement();
            JsExpression outerClassType = Js.Reference(classType.GetTypeName());

            // Generate type initializer
            typeInitializer = new JsBlockStatement();
//            typeInitializer.Add(StoreInType(SpecialNames.GetAssembly, Js.Reference(classType.ContainingAssembly.GetAssemblyMethodName())));
//            typeInitializer.Add(StoreInPrototype(SpecialNames.TypeField, Js.Reference(SpecialNames.TypeInitializerTypeFunction)));
//            typeInitializer.Add(StoreInType(SpecialNames.BaseType, baseType));
            if (classType.IsExported() && !classType.IsBuiltIn())
            {
//                typeInitializer.Add(StoreInPrototype(SpecialNames.TypeName, Js.Reference(SpecialNames.TypeInitializerTypeFunction).Member(SpecialNames.TypeName)));
            }
            else
            {
                typeInitializer.Add(StoreInPrototype(SpecialNames.TypeName, Js.Primitive(classType.GetFullName())));
                typeInitializer.Add(StoreInType(SpecialNames.TypeName, GetFromPrototype(SpecialNames.TypeName)));
            }
            if (classType.IsBuiltIn())
                typeInitializer.Add(StoreClassGetType());
            typeInitializer.Add(StoreClassCreateType(classType));

            var containingType = classType.ContainingType;
            var typeInitializerFunction = Js.Function(new[] { Js.Parameter(SpecialNames.TypeInitializerTypeFunction), Js.Parameter(SpecialNames.TypeInitializerPrototype) }.Concat(classType.TypeParameters.Select(x => Js.Parameter(x.Name))).Concat(classType.GetAnonymousTypeParameters().Select(x => Js.Parameter(x.Item2))).ToArray()).Body(typeInitializer);

            if (!isBuiltIn)
            {
                var displayName = classType.GetFullName();
                var args = new[]
                {
                    Js.Reference(SpecialNames.Assembly),
                    containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                    Js.Primitive(displayName), 
                    Js.Primitive(classType.HasOrIsEnclosedInGenericParameters()),
                    Js.Array(
                        classType.TypeParameters.Select(x => 
                            (JsExpression)Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Name), 
                                Type(x.BaseType ?? Context.Instance.ObjectType, true)
                            )
                        )
                        .Concat(classType.GetAnonymousTypeParameters().Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Item2),
                                Type(x.Item1 ?? Context.Instance.ObjectType, true)
                            )
                        ))
                        .ToArray()
                    ),
                    baseType,
                    typeInitializerFunction
                };
                if (classType.ContainingType == null && !classType.IsAnonymousType)
                {
                    block.Assign(Js.Reference(classType.ContainingNamespace.GetFullName()).Member(classType.GetShortTypeName()), 
                        Js.Reference(SpecialNames.Define).Invoke(args));
                }
                else if (classType.ContainingType != null)
                {
                    outerClassType = Js.Reference(SpecialNames.TypeInitializerTypeFunction).Member(classType.GetShortTypeName());
                    block.Assign(outerClassType, Js.Reference(SpecialNames.Define).Invoke(args));
                }
                else
                {
                    block.Assign(Js.Reference(classType.GetTypeName()), Js.Reference(SpecialNames.Define).Invoke(args));
                }
            }

            if (classType.IsBuiltIn())
                block.Assign(outerClassType.Member(SpecialNames.TypeInitializer), Js.Reference(SpecialNames.DefineTypeFunction).Invoke(outerClassType, typeInitializerFunction));

            Func<JsExpression, JsExpression> primaryTypeInitializerCall = expression => expression
                .Member("call")
                .Invoke(
                    new[] 
                    { 
                        containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction), 
                        outerClassType, 
                        outerClassType.Member("prototype")
                    }
                    .Concat(
                        classType.TypeParameters.Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Name), 
                                Type(x.BaseType ?? Context.Instance.ObjectType, true)
                            )
                        )
                    )
                    .Concat(
                        classType.GetAnonymousTypeParameters().Select(x => 
                            Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                                Js.Reference(SpecialNames.Assembly),
                                Js.Primitive(x.Item2),
                                Type(x.Item1 ?? Context.Instance.ObjectType, true)
                            )
                        )
                    )
                    .ToArray()
                );

            if (extraBuiltInExports == null)
            {
                if (!classType.IsBuiltIn())
                    block.Express(outerClassType.Member(SpecialNames.CallTypeInitializer).Invoke());
                else
                    block.Express(primaryTypeInitializerCall(outerClassType.Member(SpecialNames.TypeInitializer)));
            }
            else
            {
                block.Express(primaryTypeInitializerCall(outerClassType.Member(SpecialNames.TypeInitializer)));
                foreach (var extra in extraBuiltInExports)
                {
                    block.Express(outerClassType.Member(SpecialNames.TypeInitializer).Member("call")
                        .Invoke(
                            new[] 
                            { 
                                (JsExpression)Js.Null(), 
                                Js.Reference(extra), 
                                Js.Reference(extra).Member("prototype")
                            }
                            .ToArray()));
                    
                }
            }
            if (classType.IsBuiltIn())
            {
                block.Express(Js.Reference(classType.ContainingAssembly.GetAssemblyTypesArray()).Member("push").Invoke(outerClassType));
            }

            staticInitializer = new JsBlockStatement();
//            staticInitializer.If(GetFromType(SpecialNames.IsStaticInitialized), Js.Return());
//            staticInitializer.Add(StoreInType(SpecialNames.IsStaticInitialized, Js.Primitive(true)));
            if (classType.BaseType != null)
            {
                staticInitializer.Express(Type(classType.BaseType).Member(SpecialNames.StaticInitializer).Invoke());
            }
            var staticInitializerFunction = Js.Function().Body(staticInitializer);
            typeInitializer.Add(StoreInType(SpecialNames.StaticInitializer, Js.Reference(SpecialNames.DefineStaticConstructor).Invoke(Js.Reference(SpecialNames.TypeInitializerTypeFunction), staticInitializerFunction)));

            if (classType.HasOrIsEnclosedInGenericParameters())
            {
                var makeGenericType = new JsBlockStatement();
                var name = containingType == null ? (JsExpression)Js.Null() : Js.Reference(SpecialNames.TypeInitializerTypeFunction);
//                makeGenericType.Return(
//                    Js.Reference(SpecialNames.MakeGenericTypeConstructor)
//                    .Member("call")
//                    .Invoke(name, SpecialTypeOnlyForEnclosingTypes(classType), Js.Reference("arguments"))
//                    .Invoke()
//                );
//                typeInitializer.Add(StoreInType("$", Js.Function().Body(makeGenericType)));
                typeInitializer.Add(StoreInType(SpecialNames.TypeArgs, 
                    Js.Array(classType.TypeArguments.Select(x => Type(x)).ToArray())));
                if (!classType.IsAnonymousType)
                {
                    JsExpression target;
                    if (containingType != null) 
                    {
                        target = Js.This().Member(classType.GetShortTypeName() + SpecialNames.MakeGenericType);
                    }
                    else
                    {
                        target = Js.Reference("window." + classType.GetTypeName() + SpecialNames.MakeGenericType);
                    }

                    typeInitializer.Assign(target, GetFromType("$"));                    
                }
                if (explicitBaseType == null && classType.BaseType != null)
                {
                    typeInitializer.Add(StoreInType(SpecialNames.BaseTypeArgs, 
                        Js.Array(classType.BaseType.TypeArguments.Select(x => x == classType ? Js.Reference(SpecialNames.TypeInitializerTypeFunction) : Type(x)).ToArray())));                
                }
            }

            return block;
        }
Exemplo n.º 10
0
        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);
            }
        }
Exemplo n.º 11
0
        private JsBlockStatement CompileCatchClause(LocalResolveResult catchVariable, CatchClause catchClause, bool isCatchAll, bool isOnly)
        {
            SetRegion(catchClause.GetRegion());
            JsStatement variableDeclaration = null;
            if (!catchClause.VariableNameToken.IsNull) {
                JsExpression compiledAssignment;
                if (isCatchAll)	// If this is the only handler we need to construct the exception
                    compiledAssignment = isOnly ? _runtimeLibrary.MakeException(JsExpression.Identifier(_variables[catchVariable.Variable].Name)) : JsExpression.Identifier(_variables[catchVariable.Variable].Name);
                else
                    compiledAssignment = _runtimeLibrary.Downcast(JsExpression.Identifier(_variables[catchVariable.Variable].Name), _compilation.FindType(KnownTypeCode.Exception), _resolver.Resolve(catchClause.Type).Type);

                variableDeclaration = new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[((LocalResolveResult)_resolver.Resolve(catchClause.VariableNameToken)).Variable].Name, compiledAssignment));
            }

            var result = CreateInnerCompiler().Compile(catchClause.Body);
            if (variableDeclaration != null)
                result = new JsBlockStatement(new[] { variableDeclaration }.Concat(result.Statements));
            return result;
        }
Exemplo n.º 12
0
        private bool HandleSwitchStatement(JsSwitchStatement stmt, StackEntry location, ImmutableStack <StackEntry> stack, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, State currentState, State returnState, IList <JsStatement> currentBlock)
        {
            var          stateAfter = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);
            JsExpression expression = stmt.Expression;

            if (_isExpressionComplexEnoughForATemporaryVariable(expression))
            {
                string newName = _allocateTempVariable();
                currentBlock.Add(new JsVariableDeclarationStatement(newName, expression));
                expression = JsExpression.Identifier(newName);
            }

            var         clauses                 = new List <Tuple <JsExpression, JsBlockStatement> >();
            JsStatement defaultClause           = null;
            State?      currentFallthroughState = null;

            for (int i = 0; i < stmt.Sections.Count; i++)
            {
                var clause = stmt.Sections[i];

                var origBody = new List <JsStatement>();
                origBody.AddRange(clause.Body.Statements);

                State?nextFallthroughState;

                if (i < stmt.Sections.Count - 1 && (origBody.Count == 0 || IsNextStatementReachable(origBody[origBody.Count - 1])))
                {
                    // Fallthrough
                    var nextBody = stmt.Sections[i + 1].Body.Statements;
                    if (nextBody.Count > 0 && nextBody[0] is JsLabelledStatement)
                    {
                        nextFallthroughState = GetOrCreateStateForLabel(((JsLabelledStatement)nextBody[0]).Label, currentState.FinallyStack);
                    }
                    else
                    {
                        nextFallthroughState = CreateNewStateValue(currentState.FinallyStack);
                    }
                }
                else
                {
                    nextFallthroughState = null;
                }

                breakStack = breakStack.Push(Tuple.Create(GetLabelForState(currentState), stateAfter.Item1));

                IList <JsStatement> body;
                if (currentFallthroughState != null)
                {
                    body = new List <JsStatement>();
                    body.Add(new JsGotoStateStatement(currentFallthroughState.Value, currentState));
                    Enqueue(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(new JsBlockStatement(origBody), 0)), breakStack, continueStack, currentFallthroughState.Value, stateAfter.Item1);
                }
                else
                {
                    body = Handle(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(new JsBlockStatement(origBody), 0)), breakStack, continueStack, currentState, nextFallthroughState ?? stateAfter.Item1, false, false);
                }

                if (clause.Values.Any(v => v == null))
                {
                    defaultClause = new JsBlockStatement(body);
                }
                else
                {
                    JsExpression test = clause.Values.Select(v => JsExpression.Same(expression, v)).Aggregate((o, e) => o != null ? JsExpression.LogicalOr(o, e) : e);
                    clauses.Add(Tuple.Create(test, new JsBlockStatement(body)));
                }

                currentFallthroughState = nextFallthroughState;
            }
            clauses.Reverse();

            currentBlock.Add(clauses.Where(c => c.Item1 != null).Aggregate(defaultClause, (o, n) => new JsIfStatement(n.Item1, n.Item2, o)));
            currentBlock.Add(new JsGotoStateStatement(stateAfter.Item1, currentState));

            if (stateAfter.Item2)
            {
                Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter.Item1, returnState);
                return(false);
            }

            return(true);
        }
Exemplo n.º 13
0
 public BaseStateGenerator(Func <BaseStateGenerator, JsTransformer> transformer, CSharpSyntaxNode node, JsBlockStatement stateMachineBody, Idioms idioms, IMethodSymbol method, Action <BaseStateGenerator, JsTransformer> nodeAcceptor = null)
 {
     if (nodeAcceptor == null)
     {
         nodeAcceptor = (stateGenerator, jsTransformer) => node.Accept(stateGenerator);
     }
     this.transformer      = transformer(this);
     this.node             = node;
     this.stateMachineBody = stateMachineBody;
     this.method           = method;
     this.idioms           = idioms;
     this.nodeAcceptor     = nodeAcceptor;
 }
Exemplo n.º 14
0
 public PageJsBlockStatementFragment(JsBlockStatement statement)
 {
     Block = statement;
 }
Exemplo n.º 15
0
        private bool HandleTryStatement(JsTryStatement stmt, StackEntry location, ImmutableStack <StackEntry> stack, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, State currentState, State returnState, IList <JsStatement> currentBlock, bool isFirstStatement)
        {
            if (_isIteratorBlock && (FindInterestingConstructsVisitor.Analyze(stmt.GuardedStatement, InterestingConstruct.YieldReturn) || (stmt.Finally != null && stmt.Catch == null && !currentState.FinallyStack.IsEmpty)))
            {
                if (stmt.Catch != null)
                {
                    throw new InvalidOperationException("Cannot yield return from try with catch");
                }
                string           handlerName = _allocateFinallyHandler();
                JsBlockStatement handler;
                if (FindInterestingConstructsVisitor.Analyze(stmt.Finally, InterestingConstruct.Label))
                {
                    var inner = ProcessInner(stmt.Finally, breakStack, continueStack, currentState.FinallyStack, currentState.StateValue);
                    handler = new JsBlockStatement(new[]  { new JsSetNextStateStatement(inner.Item2) }.Concat(inner.Item1));
                    handler = new FinalizerRewriter(_stateVariableName, _labelStates).Process(handler);
                }
                else
                {
                    handler = stmt.Finally;
                }

                _finallyHandlers.Add(Tuple.Create(handlerName, handler));
                var stateAfter         = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);
                var innerState         = CreateNewStateValue(currentState.FinallyStack, handlerName);
                var stateBeforeFinally = CreateNewStateValue(innerState.FinallyStack);
                currentBlock.Add(new JsSetNextStateStatement(innerState.StateValue));
                currentBlock.AddRange(Handle(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(stmt.GuardedStatement, 0)), breakStack, continueStack, new State(currentState.LoopLabelName, currentState.StateValue, innerState.FinallyStack), stateBeforeFinally, false, false));

                Enqueue(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(new JsBlockStatement(new JsBlockStatement(new JsStatement[0], true)), 0)), breakStack, continueStack, stateBeforeFinally, stateAfter.Item1);
                if (!stack.IsEmpty || location.Index < location.Block.Statements.Count - 1)
                {
                    Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter.Item1, returnState);
                }
                return(false);
            }
            else if (_isIteratorBlock && stmt.Finally != null && !currentState.FinallyStack.IsEmpty)
            {
                // This is necessary to special-case in order to ensure that the inner finally block is executed before all outer ones.
                return(HandleTryStatement(new JsTryStatement(new JsTryStatement(stmt.GuardedStatement, stmt.Catch, null), null, stmt.Finally), location, stack, breakStack, continueStack, currentState, returnState, currentBlock, isFirstStatement));
            }
            else
            {
                var rewriter = new NestedStatementFixer(breakStack, continueStack, currentState, _exitState.Value, _makeSetResult);
                JsBlockStatement guarded;
                var guardedConstructs = FindInterestingConstructsVisitor.Analyze(stmt.GuardedStatement);
                if ((guardedConstructs & (InterestingConstruct.Label | InterestingConstruct.Await)) != InterestingConstruct.None)
                {
                    if (!isFirstStatement)
                    {
                        var sv = CreateNewStateValue(currentState.FinallyStack);
                        Enqueue(stack.Push(location), breakStack, continueStack, sv, returnState);
                        currentBlock.Add(new JsGotoStateStatement(sv, currentState));
                        return(false);
                    }

                    var inner = ProcessInner(stmt.GuardedStatement, breakStack, continueStack, currentState.FinallyStack, currentState.StateValue);
                    guarded = new JsBlockStatement(inner.Item1);
                    currentBlock.Add(new JsSetNextStateStatement(inner.Item2));
                }
                else
                {
                    guarded = rewriter.Process(stmt.GuardedStatement);
                }

                JsCatchClause @catch;
                if (stmt.Catch != null)
                {
                    if (FindInterestingConstructsVisitor.Analyze(stmt.Catch.Body, InterestingConstruct.Label))
                    {
                        var inner = ProcessInner(stmt.Catch.Body, breakStack, continueStack, currentState.FinallyStack, null);
                        @catch = new JsCatchClause(stmt.Catch.Identifier, new JsBlockStatement(new[] { new JsSetNextStateStatement(inner.Item2) }.Concat(inner.Item1)));
                    }
                    else
                    {
                        var body = rewriter.Process(stmt.Catch.Body);
                        @catch = ReferenceEquals(body, stmt.Catch.Body) ? stmt.Catch : new JsCatchClause(stmt.Catch.Identifier, body);
                    }
                }
                else
                {
                    @catch = null;
                }

                JsBlockStatement @finally;
                if (stmt.Finally != null)
                {
                    if (FindInterestingConstructsVisitor.Analyze(stmt.Finally, InterestingConstruct.Label))
                    {
                        var inner = ProcessInner(stmt.Finally, breakStack, continueStack, currentState.FinallyStack, null);
                        @finally = new JsBlockStatement(new[] { new JsSetNextStateStatement(inner.Item2) }.Concat(inner.Item1));
                    }
                    else
                    {
                        @finally = rewriter.Process(stmt.Finally);
                    }

                    if ((guardedConstructs & InterestingConstruct.Await) != InterestingConstruct.None)
                    {
                        // Wrap the finally block inside an 'if (doFinallyBlocks) {}'
                        @finally = new JsBlockStatement(new JsIfStatement(JsExpression.Identifier(_doFinallyBlocksVariableName), @finally, null));
                    }
                }
                else
                {
                    @finally = null;
                }

                if (currentBlock.Count > 0 && _childStates.ContainsKey(currentState.StateValue))
                {
                    var newBlock = new JsIfStatement(JsExpression.Same(JsExpression.Identifier(_stateVariableName), JsExpression.Number(currentState.StateValue)), new JsBlockStatement(currentBlock), null);
                    currentBlock.Clear();
                    currentBlock.Add(newBlock);
                }

                currentBlock.Add(new JsTryStatement(guarded, @catch, @finally));
                return(true);
            }
        }
Exemplo n.º 16
0
 public virtual void VisitBlockStatement(JsBlockStatement node)
 {
 }
Exemplo n.º 17
0
 public void Visit(JsBlockStatement node)
 {
     BeforeVisit(node);
     DefaultVisit(node, VisitBlockStatement);
     AfterVisit(node);
 }
 public JsBlockStatement Process(JsBlockStatement statement)
 {
     return((JsBlockStatement)VisitStatement(statement, null));
 }
Exemplo n.º 19
0
		private Tuple<List<JsStatement>, int> ProcessInner(JsBlockStatement statement, ImmutableStack<Tuple<string, State>> breakStack, ImmutableStack<Tuple<string, State>> continueStack, ImmutableStack<Tuple<int, string>> finallyStack, int? parentState) {
			var oldLoopLabel = _currentLoopLabel;
			var oldRemainingBlocks = _remainingBlocks;
			try {
				_currentLoopLabel = _allocateLoopLabel();
				_remainingBlocks = new Queue<RemainingBlock>();
				_remainingBlocks.Enqueue(new RemainingBlock(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(statement, 0)), breakStack, continueStack, CreateNewStateValue(finallyStack), new State(_currentLoopLabel, -1, finallyStack)));
				if (_exitState == null)
					_exitState = new State(_currentLoopLabel, -1, ImmutableStack<Tuple<int, string>>.Empty);
	
				var sections = new List<Section>();

				int iterationCount = 0;
	
				while (_remainingBlocks.Count > 0) {
					var current = _remainingBlocks.Dequeue();
					var list = Handle(current.Stack, current.BreakStack, current.ContinueStack, current.StateValue, current.ReturnState, _isIteratorBlock || _isAsync, true);
					// Merge all top-level blocks that should be merged with their parents.
					list = list.SelectMany(stmt => (stmt is JsBlockStatement && ((JsBlockStatement)stmt).MergeWithParent) ? ((JsBlockStatement)stmt).Statements : (IList<JsStatement>)new[] { stmt }).ToList();
					sections.Add(new Section(current.StateValue, list));

					if (iterationCount++ > 100000)
						throw new Exception("Infinite loop when rewriting method to a state machine");
				}

				if (parentState != null && _isAsync) {
					List<int> childStates;
					if (!_childStates.TryGetValue(parentState.Value, out childStates))
						_childStates[parentState.Value] = childStates = new List<int>();
					childStates.AddRange(sections.Select(s => s.State.StateValue));
				}

				var body = new List<JsStatement> {
				               JsStatement.Label(_currentLoopLabel,
				                   JsStatement.For(JsStatement.Empty, null, null,
				                       JsStatement.Switch(JsExpression.Identifier(_stateVariableName),
				                           sections.Select(b => JsStatement.SwitchSection(
				                                                    GetAllContainedStateValues(b.State.StateValue).OrderBy(v => v).Select(v => JsExpression.Number(v)),
				                                                    JsStatement.Block(b.Statements)))
				                                   .Concat(new[] { JsStatement.SwitchSection(new JsExpression[] { null }, JsStatement.Break(_currentLoopLabel)) }))))
				           };
				return Tuple.Create(body, sections[0].State.StateValue);
			}
			finally {
				_currentLoopLabel = oldLoopLabel;
				_remainingBlocks = oldRemainingBlocks;
			}
		}
Exemplo n.º 20
0
 public JsTryStatement()
 {
     Body = new JsBlockStatement();
 }
Exemplo n.º 21
0
 public AsyncStateGenerator(Idioms idioms, JsBlockStatement stateMachineBody, CSharpSyntaxNode node, IMethodSymbol method, Action <BaseStateGenerator, JsTransformer> nodeAcceptor = null) :
     base(x => new AsyncExpressionDecomposer((AsyncStateGenerator)x, idioms), node, stateMachineBody, idioms, method, nodeAcceptor)
 {
 }
Exemplo n.º 22
0
 public IteratorStateMachine(JsBlockStatement mainBlock, IEnumerable <JsVariableDeclaration> variables, IEnumerable <Tuple <string, JsFunctionDefinitionExpression> > finallyHandlers, JsBlockStatement disposer)
 {
     MainBlock       = mainBlock;
     Variables       = variables.AsReadOnly();
     FinallyHandlers = finallyHandlers.AsReadOnly();
     Disposer        = disposer;
 }
Exemplo n.º 23
0
 public JsFunctionDefinitionExpression CompileMethod(IList<IParameter> parameters, IDictionary<IVariable, VariableData> variables, BlockStatement body, bool staticMethodWithThisAsFirstArgument)
 {
     SetRegion(body.GetRegion());
     try {
         _result = MethodCompiler.FixByRefParameters(parameters, variables);
         VisitChildren(body);
         JsBlockStatement jsbody;
         if (_result.Count == 1 && _result[0] is JsBlockStatement)
             jsbody = (JsBlockStatement)_result[0];
         else
             jsbody = new JsBlockStatement(_result);
         return JsExpression.FunctionDefinition((staticMethodWithThisAsFirstArgument ? new[] { _namer.ThisAlias } : new string[0]).Concat(parameters.Select(p => variables[p].Name)), jsbody);
     }
     catch (Exception ex) {
         _errorReporter.InternalError(ex);
         return JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);
     }
 }
Exemplo n.º 24
0
        public void MinimizingIdentifiersWorks()
        {
            var    stmt   = JsBlockStatement.MakeBlock(JavaScriptParser.Parser.ParseStatement(@"
{
	var variable1;
	(function() {
		var variable2;
		a;
		function d(p1, p2) {
			e;
			b;
			p1;
			variable1;
			var variable3;
		}
		for (var variable4 = 1;;) {
			for (var variable5 in d) {
			}
			for (f in x) {
			}
		}
	});
	try {
		ex;
	}
	catch (ex) {
		(function() {
			a;
			ex;
		});
	}
	j;
}"));
            var    result = Minifier.Process(stmt);
            string actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(
                            @"{
	var c;
	(function() {
		var g;
		a;
		function d(a, d) {
			e;
			b;
			a;
			c;
			var f;
		}
		for (var h = 1;;) {
			for (var i in d) {
			}
			for (f in x) {
			}
		}
	});
	try {
		ex;
	}
	catch (g) {
		(function() {
			a;
			g;
		});
	}
	j;
}
".Replace("\r\n", "\n")));
        }
Exemplo n.º 25
0
        public override void VisitTryCatchStatement(TryCatchStatement tryCatchStatement)
        {
            var tryBlock = CreateInnerCompiler().Compile(tryCatchStatement.TryBlock);
            JsCatchClause catchClause = null;
            if (tryCatchStatement.CatchClauses.Count > 0) {
                var oldVariableForRethrow = _currentVariableForRethrow;

                _currentVariableForRethrow = CreateTemporaryVariable(_compilation.FindType(KnownTypeCode.Object), tryCatchStatement.CatchClauses.First().GetRegion());
                string catchVariableName = _variables[_currentVariableForRethrow].Name;

                var catchClauses = tryCatchStatement.CatchClauses.ToList();
                var systemException = _compilation.FindType(KnownTypeCode.Exception);
                RemoveCatchClausesAfterExceptionType(catchClauses, systemException);

                bool lastIsCatchall = (catchClauses[catchClauses.Count - 1].Type.IsNull || _resolver.Resolve(catchClauses[catchClauses.Count - 1].Type).Type.Equals(systemException));
                JsStatement current = lastIsCatchall
                                    ? CompileCatchClause(new LocalResolveResult(_currentVariableForRethrow), catchClauses[catchClauses.Count - 1], true, catchClauses.Count == 1)
                                    : new JsBlockStatement(new JsThrowStatement(JsExpression.Identifier(catchVariableName)));

                for (int i = catchClauses.Count - (lastIsCatchall ? 2 : 1); i >= 0; i--) {
                    var test = _runtimeLibrary.TypeIs(JsExpression.Identifier(catchVariableName), _currentVariableForRethrow.Type, _resolver.Resolve(catchClauses[i].Type).Type);
                    current = new JsIfStatement(test, CompileCatchClause(new LocalResolveResult(_currentVariableForRethrow), catchClauses[i], false, catchClauses.Count == 1), current);
                }

                if (!lastIsCatchall || catchClauses.Count > 1) {
                    // We need to wrap the exception.
                    current = new JsBlockStatement(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(catchVariableName), _runtimeLibrary.MakeException(JsExpression.Identifier(catchVariableName)))), current);
                }

                catchClause = new JsCatchClause(catchVariableName, current);
                _currentVariableForRethrow = oldVariableForRethrow;
            }

            var finallyBlock = (!tryCatchStatement.FinallyBlock.IsNull ? CreateInnerCompiler().Compile(tryCatchStatement.FinallyBlock) : null);

            _result.Add(new JsTryStatement(tryBlock, catchClause, finallyBlock));
        }
Exemplo n.º 26
0
        public void GatheringIsCorrect()
        {
            var stmt    = JsBlockStatement.MakeBlock(JavaScriptParser.Parser.ParseStatement(@"
{
	var a;
	(function() {
		var b;
		c;
		function d(p1, p2) {
			e;
			b;
			var f;
		}
		for (var g = 1;;) {
			for (var h in x) {
			}
			for (i in x) {
			}
		}
	});
	try {
	}
	catch (ex) {
		(function() {
			ex;
		});
	}
	j;
}"));
            var locals  = Minifier.LocalVariableGatherer.Analyze(stmt);
            var globals = Minifier.ImplicitGlobalsGatherer.Analyze(stmt, locals);
            var result  = new OutputRewriter(locals, globals).Process(stmt);

            string actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(
                            @"{
	locals(a);
	globals(c, d, e, i, j, x);
	var a;
	(function() {
		locals(b, g, h);
		globals(c, d, e, i, x);
		var b;
		c;
		function d(p1, p2) {
			locals(f, p1, p2);
			globals(e);
			e;
			b;
			var f;
		}
		for (var g = 1;;) {
			for (var h in x) {
			}
			for (i in x) {
			}
		}
	});
	try {
	}
	catch (ex) {
		(function() {
			locals();
			globals();
			ex;
		});
	}
	j;
}
".Replace("\r\n", "\n")));
        }
Exemplo n.º 27
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(JsBlockStatement other) => Statements.EquivalentTo(other.Statements);
 public JsStatement Process(JsBlockStatement stmt)
 {
     stmt = (JsBlockStatement)VisitStatement(stmt, null);
     return(JsStatement.Block(MakePrefix(new Minifier.Function()).Concat(stmt.Statements)));
 }
Exemplo n.º 29
0
        public JsBlockStatement InitializeInstanceFields(TypeDeclarationSyntax classDeclaration)
        {
            var result = new JsBlockStatement();

            // Add field initializers
            foreach (var field in classDeclaration.Members.OfType<FieldDeclarationSyntax>())
            {
                foreach (var variable in field.Declaration.Variables)
                {
                    var fieldSymbol = (IFieldSymbol)transformer.model.GetDeclaredSymbol(variable);
                    if (!fieldSymbol.IsExported())
                        continue;

                    var initializer = variable.Initializer != null ? 
                        (JsExpression)variable.Initializer.Accept(transformer) :
                        DefaultValue(fieldSymbol.Type);
                    if (!fieldSymbol.IsStatic)
                        result.Assign(Js.This().Member(fieldSymbol.GetMemberName()), initializer);
                }
            }
            // Add minimized auto-property initializers
            foreach (var property in classDeclaration.Members.OfType<PropertyDeclarationSyntax>())
            {
                var propertySymbol = transformer.model.GetDeclaredSymbol(property);
                if (propertySymbol.ExplicitInterfaceImplementations.Any())
                    continue;
                if (IsMinimizedAutoProperty(propertySymbol) && propertySymbol.IsExported())
                {
                    var initializer = property.Initializer == null ? DefaultValue(propertySymbol.Type) : (JsExpression)property.Initializer.Accept(transformer);
                    if (!propertySymbol.IsStatic)
                        result.Assign(Js.This().Member(propertySymbol.GetMemberName()), initializer);
                }
            }
            var model = Context.Instance.Compilation.GetSemanticModel(classDeclaration.SyntaxTree);
            foreach (var node in classDeclaration.Members.OfType<PropertyDeclarationSyntax>())
            {
                var getter = node.AccessorList.Accessors.SingleOrDefault(x => x.Keyword.IsKind(SyntaxKind.GetKeyword));
                var setter = node.AccessorList.Accessors.SingleOrDefault(x => x.Keyword.IsKind(SyntaxKind.SetKeyword));
                var property = (IPropertySymbol)ModelExtensions.GetDeclaredSymbol(model, node);
                if (!IsMinimizedAutoProperty(property) && getter != null && setter != null && getter.Body == null && setter.Body == null)
                {
                    if (!property.IsStatic)
                    {
                        var backingField = property.GetBackingFieldName();
                        var initializer = node.Initializer == null ? DefaultValue(property.Type) : (JsExpression)node.Initializer.Accept(transformer);
                        result.Assign(Js.This().Member(backingField), initializer);
                    }
                }
            }
            
            return result;
        }
        public virtual JsStatement VisitBlockStatement(JsBlockStatement statement, TData data)
        {
            var after = VisitStatements(statement.Statements, data);

            return(ReferenceEquals(after, statement.Statements) ? statement : new JsBlockStatement(after, statement.MergeWithParent));
        }
 public JsFunctionDefinitionExpression CompileMethod(IList<IParameter> parameters, IDictionary<IVariable, VariableData> variables, BlockStatement body)
 {
     _filename = body.GetRegion().FileName;
     try {
         _result = MethodCompiler.FixByRefParameters(parameters, variables);
         VisitChildren(body);
         JsBlockStatement jsbody;
         if (_result.Count == 1 && _result[0] is JsBlockStatement)
             jsbody = (JsBlockStatement)_result[0];
         else
             jsbody = new JsBlockStatement(_result);
         return JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), jsbody);
     }
     catch (Exception ex) {
         _errorReporter.InternalError(ex, _filename, _location);
         return JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);
     }
 }
Exemplo n.º 32
0
		public static JsBlockStatement RewriteAsyncMethod(JsBlockStatement block, Func<JsExpression, bool> isExpressionComplexEnoughForATemporaryVariable, Func<string> allocateTempVariable, Func<string> allocateStateVariable, Func<string> allocateLoopLabel, string stateMachineVariableName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func<JsExpression, JsExpression> makeSetResult, Func<JsExpression, JsExpression> makeSetException, Func<JsExpression> getTask, Func<JsExpression, JsExpression, JsExpression> bindToContext) {
			var obj = new StateMachineRewriter(isExpressionComplexEnoughForATemporaryVariable, allocateTempVariable, allocateStateVariable, allocateLoopLabel);
			return obj.ProcessAsyncMethod(block, stateMachineVariableName, doFinallyBlocksVariableName, taskCompletionSource, makeSetResult, makeSetException, getTask, bindToContext);
		}
Exemplo n.º 33
0
		public JsCatchClause(string identifier, JsStatement body) {
			if (identifier == null) throw new ArgumentNullException("identifier");
			if (body == null) throw new ArgumentNullException("body");
			Identifier = identifier;
			Body = JsStatement.EnsureBlock(body);
		}
        private bool HandleSwitchStatement(JsSwitchStatement stmt, StackEntry location, ImmutableStack<StackEntry> stack, ImmutableStack<Tuple<string, State>> breakStack, ImmutableStack<Tuple<string, State>> continueStack, State currentState, State returnState, IList<JsStatement> currentBlock)
        {
            var stateAfter = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);
            JsExpression expression = stmt.Expression;
            if (_isExpressionComplexEnoughForATemporaryVariable(expression)) {
                string newName = _allocateTempVariable();
                currentBlock.Add(new JsVariableDeclarationStatement(newName, expression));
                expression = JsExpression.Identifier(newName);
            }

            var clauses = new List<Tuple<JsExpression, JsBlockStatement>>();
            JsStatement defaultClause = null;
            State? currentFallthroughState = null;
            for (int i = 0; i < stmt.Sections.Count; i++) {
                var clause = stmt.Sections[i];

                var origBody = new List<JsStatement>();
                origBody.AddRange(clause.Body.Statements);

                State? nextFallthroughState;

                if (i < stmt.Sections.Count - 1 && (origBody.Count == 0 || IsNextStatementReachable(origBody[origBody.Count - 1]))) {
                    // Fallthrough
                    var nextBody = stmt.Sections[i + 1].Body.Statements;
                    if (nextBody.Count > 0 && nextBody[0] is JsLabelledStatement)
                        nextFallthroughState = GetOrCreateStateForLabel(((JsLabelledStatement)nextBody[0]).Label, currentState.FinallyStack);
                    else
                        nextFallthroughState = CreateNewStateValue(currentState.FinallyStack);
                }
                else {
                    nextFallthroughState = null;
                }

                breakStack = breakStack.Push(Tuple.Create(GetLabelForState(currentState), stateAfter.Item1));

                IList<JsStatement> body;
                if (currentFallthroughState != null) {
                    body = new List<JsStatement>();
                    body.Add(new JsGotoStateStatement(currentFallthroughState.Value, currentState));
                    Enqueue(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(new JsBlockStatement(origBody), 0)), breakStack, continueStack, currentFallthroughState.Value, stateAfter.Item1);
                }
                else {
                    body = Handle(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(new JsBlockStatement(origBody), 0)), breakStack, continueStack, currentState, nextFallthroughState ?? stateAfter.Item1);
                }

                if (clause.Values.Any(v => v == null)) {
                    defaultClause = new JsBlockStatement(body);
                }
                else {
                    JsExpression test = clause.Values.Select(v => JsExpression.Same(expression, v)).Aggregate((o, e) => o != null ? JsExpression.LogicalOr(o, e) : e);
                    clauses.Add(Tuple.Create(test, new JsBlockStatement(body)));
                }

                currentFallthroughState = nextFallthroughState;
            }
            clauses.Reverse();

            currentBlock.Add(clauses.Where(c => c.Item1 != null).Aggregate(defaultClause, (o, n) => new JsIfStatement(n.Item1, n.Item2, o)));
            currentBlock.Add(new JsGotoStateStatement(stateAfter.Item1, currentState));

            if (stateAfter.Item2) {
                Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter.Item1, returnState);
                return false;
            }

            return true;
        }
Exemplo n.º 35
0
		private JsBlockStatement Process(JsBlockStatement statement, bool isIteratorBlock, bool isAsync) {
			_stateVariableName = _allocateStateVariable();
			_nextStateIndex = 0;
			_isIteratorBlock = isIteratorBlock;
			_isAsync = isAsync;
			_processedStates = new HashSet<State>();
			_labelStates = new Dictionary<string, State>();
			_finallyHandlers = new List<Tuple<string, JsBlockStatement>>();
			_allStates = new List<State>();
			_remainingBlocks = new Queue<RemainingBlock>();
			_exitState = null;
			_childStates = new Dictionary<int, List<int>>();
			var body = ProcessInner(statement, ImmutableStack<Tuple<string, State>>.Empty, ImmutableStack<Tuple<string, State>>.Empty, ImmutableStack<Tuple<int, string>>.Empty, null).Item1;

			if (_isIteratorBlock)
				body.Add(JsStatement.Return(JsExpression.False));
			var resultBody = new FinalizerRewriter(_stateVariableName, _labelStates).Process(JsStatement.Block(body));
			return resultBody;
		}
 private JsBlockStatement Process(JsBlockStatement statement, bool isIteratorBlock)
 {
     _stateVariableName = _allocateStateVariable();
     _nextStateIndex = 0;
     _isIteratorBlock = isIteratorBlock;
     _processedStates = new HashSet<State>();
     _labelStates = new Dictionary<string, State>();
     _finallyHandlers = new List<Tuple<string, JsBlockStatement>>();
     _allStates = new List<State>();
     _remainingBlocks = new Queue<RemainingBlock>();
     _exitState = null;
     var body = ProcessInner(statement, ImmutableStack<Tuple<string, State>>.Empty, ImmutableStack<Tuple<string, State>>.Empty, ImmutableStack<Tuple<int, string>>.Empty);
     body.RemoveAt(0);	// Remove the initial assignment of the state. This will instead happen in the statement that declares the variables for this state machine.
     if (_isIteratorBlock)
         body.Add(new JsReturnStatement(JsExpression.False));
     var resultBody = new FinalizerRewriter(_stateVariableName, _labelStates).Process(new JsBlockStatement(body));
     return resultBody;
 }
Exemplo n.º 37
0
 public JsStatement Process(JsBlockStatement stmt)
 {
     stmt = (JsBlockStatement)VisitStatement(stmt, null);
     return(JsStatement.Block(MakePrefix(JsDeclarationScope.Root).Concat(stmt.Statements)));
 }
Exemplo n.º 38
0
 public AnonymousTypeTransformer(JsBlockStatement body, List <Tuple <INamedTypeSymbol, Action> > actions)
 {
     this.body    = body;
     this.actions = actions;
     this.idioms  = new Idioms(null);
 }
Exemplo n.º 39
0
		public static JsBlockStatement RewriteIteratorBlock(JsBlockStatement block, Func<JsExpression, bool> isExpressionComplexEnoughForATemporaryVariable, Func<string> allocateTempVariable, Func<string> allocateStateVariable, Func<string> allocateLoopLabel, Func<string> allocateFinallyHandler, Func<JsExpression, JsExpression> makeSetCurrent, Func<IteratorStateMachine, JsBlockStatement> makeIteratorBody) {
			var obj = new StateMachineRewriter(isExpressionComplexEnoughForATemporaryVariable, allocateTempVariable, allocateStateVariable, allocateLoopLabel);
			var sm = obj.ProcessIteratorBlock(block, allocateFinallyHandler, makeSetCurrent);
			return makeIteratorBody(sm);
		}
Exemplo n.º 40
0
		public StackEntry(JsBlockStatement block, int index, bool afterForInitializer = false) {
			Block = block;
			Index = index;
			AfterForInitializer = afterForInitializer;
		}
        private bool HandleTryStatement(JsTryStatement stmt, StackEntry location, ImmutableStack<StackEntry> stack, ImmutableStack<Tuple<string, State>> breakStack, ImmutableStack<Tuple<string, State>> continueStack, State currentState, State returnState, IList<JsStatement> currentBlock)
        {
            if (FindInterestingConstructsVisitor.Analyze(stmt.GuardedStatement, InterestingConstruct.YieldReturn) || (stmt.Finally != null && stmt.Catch == null && !currentState.FinallyStack.IsEmpty)) {
                if (stmt.Catch != null)
                    throw new InvalidOperationException("Cannot yield return from try with catch");
                string handlerName = _allocateFinallyHandler();
                _finallyHandlers.Add(Tuple.Create(handlerName, FindInterestingConstructsVisitor.Analyze(stmt.Finally, InterestingConstruct.Label) ? new FinalizerRewriter(_stateVariableName, _labelStates).Process(new JsBlockStatement(ProcessInner(stmt.Finally, breakStack, continueStack, currentState.FinallyStack))) : stmt.Finally));
                var stateAfter = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);
                var innerState = CreateNewStateValue(currentState.FinallyStack, handlerName);
                var stateBeforeFinally = CreateNewStateValue(innerState.FinallyStack);
                currentBlock.Add(new JsSetNextStateStatement(innerState.StateValue));
                currentBlock.AddRange(Handle(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(stmt.GuardedStatement, 0)), breakStack, continueStack, innerState, stateBeforeFinally));

                Enqueue(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(new JsBlockStatement(new JsBlockStatement(new JsStatement[0], true)), 0)), breakStack, continueStack, stateBeforeFinally, stateAfter.Item1);
                if (!stack.IsEmpty || location.Index < location.Block.Statements.Count - 1) {
                    Enqueue(PushFollowing(stack, location), breakStack, continueStack, stateAfter.Item1, returnState);
                }
                return false;
            }
            else if (stmt.Finally != null && !currentState.FinallyStack.IsEmpty) {
                // This is necessary to special-case in order to ensure that the inner finally block is executed before all outer ones.
                return HandleTryStatement(new JsTryStatement(new JsTryStatement(stmt.GuardedStatement, stmt.Catch, null), null, stmt.Finally), location, stack, breakStack, continueStack, currentState, returnState, currentBlock);
            }
            else {
                var rewriter = new NestedJumpStatementRewriter(breakStack, continueStack, currentState, _exitState.Value);
                var guarded = FindInterestingConstructsVisitor.Analyze(stmt.GuardedStatement, InterestingConstruct.Label)
                              ? new JsBlockStatement(ProcessInner(stmt.GuardedStatement, breakStack, continueStack, currentState.FinallyStack))
                              : rewriter.Process(stmt.GuardedStatement);

                JsCatchClause @catch;
                if (stmt.Catch != null) {
                    if (FindInterestingConstructsVisitor.Analyze(stmt.Catch.Body, InterestingConstruct.Label)) {
                        @catch = new JsCatchClause(stmt.Catch.Identifier, new JsBlockStatement(ProcessInner(stmt.Catch.Body, breakStack, continueStack, currentState.FinallyStack)));
                    }
                    else {
                        var body = rewriter.Process(stmt.Catch.Body);
                        @catch = ReferenceEquals(body, stmt.Catch.Body) ? stmt.Catch : new JsCatchClause(stmt.Catch.Identifier, body);
                    }
                }
                else
                    @catch = null;

                JsBlockStatement @finally;
                if (stmt.Finally != null) {
                    if (FindInterestingConstructsVisitor.Analyze(stmt.Finally, InterestingConstruct.Label))
                        @finally = new JsBlockStatement(ProcessInner(stmt.Finally, breakStack, continueStack, currentState.FinallyStack));
                    else
                        @finally = rewriter.Process(stmt.Finally);
                }
                else
                    @finally = null;

                currentBlock.Add(new JsTryStatement(guarded, @catch, @finally));
                return true;
            }
        }
Exemplo n.º 42
0
 public NamespaceTransformer(JsBlockStatement body)
 {
     this.body = body;
 }
        private IList<JsStatement> ProcessInner(JsBlockStatement statement, ImmutableStack<Tuple<string, State>> breakStack, ImmutableStack<Tuple<string, State>> continueStack, ImmutableStack<Tuple<int, string>> finallyStack)
        {
            var oldLoopLabel = _currentLoopLabel;
            var oldRemainingBlocks = _remainingBlocks;
            try {
                _currentLoopLabel = _allocateLoopLabel();
                _remainingBlocks = new Queue<RemainingBlock>();
                _remainingBlocks.Enqueue(new RemainingBlock(ImmutableStack<StackEntry>.Empty.Push(new StackEntry(statement, 0)), breakStack, continueStack, CreateNewStateValue(finallyStack), new State(_currentLoopLabel, -1, finallyStack)));
                if (_exitState == null)
                    _exitState = new State(_currentLoopLabel, -1, ImmutableStack<Tuple<int, string>>.Empty);

                var sections = new List<Section>();

                while (_remainingBlocks.Count > 0) {
                    var current = _remainingBlocks.Dequeue();
                    var list = Handle(current.Stack, current.BreakStack, current.ContinueStack, current.StateValue, current.ReturnState);
                    // Merge all top-level blocks that should be merged with their parents.
                    list = list.SelectMany(stmt => (stmt is JsBlockStatement && ((JsBlockStatement)stmt).MergeWithParent) ? ((JsBlockStatement)stmt).Statements : (IList<JsStatement>)new[] { stmt }).ToList();
                    if (_isIteratorBlock && !(list.Count > 0 && (list[0] is JsSetNextStateStatement || list[0] is JsGotoStateStatement)))
                        list.Insert(0, new JsSetNextStateStatement(current.StateValue.FinallyStack.IsEmpty ? -1 : current.StateValue.FinallyStack.Peek().Item1));
                    sections.Add(new Section(current.StateValue, list));
                }

                var body = new List<JsStatement> {
                               new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(_stateVariableName), JsExpression.Number(sections[0].State.StateValue))),				                                 	new JsLabelledStatement(_currentLoopLabel,
                                   new JsForStatement(new JsEmptyStatement(), null, null,
                                       new JsSwitchStatement(JsExpression.Identifier(_stateVariableName),
                                           sections.Select(b => new JsSwitchSection(
                                                                    new[] { JsExpression.Number(b.State.StateValue) },
                                                                    new JsBlockStatement(b.Statements)))
                                                   .Concat(new[] { new JsSwitchSection(new JsExpression[] { null }, new JsBreakStatement(_currentLoopLabel)) }))))
                           };
                return body;
            }
            finally {
                _currentLoopLabel = oldLoopLabel;
                _remainingBlocks = oldRemainingBlocks;
            }
        }
Exemplo n.º 44
0
//        public const string current = "$current";

        public YieldStateGenerator(Func <BaseStateGenerator, JsTransformer> transformer, CSharpSyntaxNode node, JsBlockStatement stateMachineBody, Idioms idioms, IMethodSymbol method) : base(transformer, node, stateMachineBody, idioms, method)
        {
        }
Exemplo n.º 45
0
        public static JsBlockStatement RewriteAsyncMethod(JsBlockStatement block, Func <JsExpression, bool> isExpressionComplexEnoughForATemporaryVariable, Func <string> allocateTempVariable, Func <string> allocateStateVariable, Func <string> allocateLoopLabel, string stateMachineVariableName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func <JsExpression, JsExpression> makeSetResult, Func <JsExpression, JsExpression> makeSetException, Func <JsExpression> getTask, Func <JsExpression, JsExpression, JsExpression> bindToContext)
        {
            var obj = new StateMachineRewriter(isExpressionComplexEnoughForATemporaryVariable, allocateTempVariable, allocateStateVariable, allocateLoopLabel);

            return(obj.ProcessAsyncMethod(block, stateMachineVariableName, doFinallyBlocksVariableName, taskCompletionSource, makeSetResult, makeSetException, getTask, bindToContext));
        }
Exemplo n.º 46
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PageBlockFragment"/> class.
 /// </summary>
 /// <param name="originalText">The original text.</param>
 /// <param name="name">The name.</param>
 /// <param name="argument">The argument.</param>
 /// <param name="body">The body.</param>
 /// <param name="elseStatements">The else statements.</param>
 public PageBlockFragment(string originalText, string name, string argument,
                          JsBlockStatement body, IEnumerable <PageElseBlock> elseStatements = null)
     : this(originalText.AsMemory(), name, argument.AsMemory(), new PageFragment[] { new PageJsBlockStatementFragment(body) }, elseStatements)
 {
 }
Exemplo n.º 47
0
 public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
 {
     var body = CreateInnerCompiler().Compile(doWhileStatement.EmbeddedStatement);
     var compiledCondition = CompileExpression(doWhileStatement.Condition, true);
     if (compiledCondition.AdditionalStatements.Count > 0)
         body = new JsBlockStatement(body.Statements.Concat(compiledCondition.AdditionalStatements));
     _result.Add(new JsDoWhileStatement(compiledCondition.Expression, body));
 }
Exemplo n.º 48
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PageElseBlock"/> class.
 /// </summary>
 /// <param name="argument">The argument.</param>
 /// <param name="block">The block.</param>
 public PageElseBlock(string argument, JsBlockStatement block)
     : this(argument.AsMemory(), new PageFragment[] { new PageJsBlockStatementFragment(block) })
 {
 }
Exemplo n.º 49
0
        public override void VisitForStatement(ForStatement forStatement)
        {
            // Initializer. In case we need more than one statement, put all other statements just before this loop.
            JsStatement initializer;
            if (forStatement.Initializers.Count == 1 && forStatement.Initializers.First() is VariableDeclarationStatement) {
                forStatement.Initializers.First().AcceptVisitor(this);
                initializer = _result[_result.Count - 1];
                _result.RemoveAt(_result.Count - 1);
            }
            else {
                JsExpression initExpr = null;
                foreach (var init in forStatement.Initializers) {
                    var compiledInit = CompileExpression(((ExpressionStatement)init).Expression, false);
                    if (compiledInit.AdditionalStatements.Count == 0) {
                        initExpr = (initExpr != null ? JsExpression.Comma(initExpr, compiledInit.Expression) : compiledInit.Expression);
                    }
                    else {
                        if (initExpr != null)
                            _result.Add(new JsExpressionStatement(initExpr));
                        _result.AddRange(compiledInit.AdditionalStatements);
                        initExpr = compiledInit.Expression;
                    }
                }
                initializer = (initExpr != null ? (JsStatement)new JsExpressionStatement(initExpr) : (JsStatement)new JsEmptyStatement());
            }

            // Condition
            JsExpression condition;
            List<JsStatement> preBody = null;
            if (!forStatement.Condition.IsNull) {
                var compiledCondition = CompileExpression(forStatement.Condition, true);
                if (compiledCondition.AdditionalStatements.Count == 0) {
                    condition = compiledCondition.Expression;
                }
                else {
                    // The condition requires additional statements. Transform "for (int i = 0; i < (SomeProperty = 1); i++) { ... }" to "for (var i = 0;; i++) { this.set_SomeProperty(1); if (!(i < 1)) { break; } ... }
                    preBody = new List<JsStatement>();
                    preBody.AddRange(compiledCondition.AdditionalStatements);
                    preBody.Add(new JsIfStatement(JsExpression.LogicalNot(compiledCondition.Expression), new JsBreakStatement(), null));
                    condition = null;
                }
            }
            else {
                condition = null;
            }

            // Iterators
            JsExpression iterator = null;
            List<JsStatement> postBody = null;
            if (forStatement.Iterators.Count > 0) {
                var compiledIterators = forStatement.Iterators.Select(i => CompileExpression(((ExpressionStatement)i).Expression, false)).ToList();
                if (compiledIterators.All(i => i.AdditionalStatements.Count == 0)) {
                    // No additional statements are required, add them as a single comma-separated expression to the JS iterator.
                    iterator = compiledIterators.Aggregate(iterator, (current, i) => (current != null ? JsExpression.Comma(current, i.Expression) : i.Expression));
                }
                else {
                    // At least one of the compiled iterators need additional statements. We could add the last expressions that don't need extra statements to the iterators section of the for loop, but for simplicity we'll just add everything to the end of the loop.
                    postBody = new List<JsStatement>();
                    foreach (var i in compiledIterators) {
                        postBody.AddRange(i.AdditionalStatements);
                        postBody.Add(new JsExpressionStatement(i.Expression));
                    }
                }
            }

            // Body
            var body = CreateInnerCompiler().Compile(forStatement.EmbeddedStatement);

            if (preBody != null || postBody != null) {
                body = new JsBlockStatement(((IEnumerable<JsStatement>)preBody ?? new JsStatement[0]).Concat(body.Statements).Concat((IEnumerable<JsStatement>)postBody ?? new JsStatement[0]));
            }

            _result.Add(new JsForStatement(initializer, condition, iterator, body));
        }
Exemplo n.º 50
0
        public JsExpressionStatement StoreClassCreateType(INamedTypeSymbol type)
        {
            var explicitName = type.GetAttributeValue<string>(Context.Instance.JsAttributeType, "Name");
            var fullTypeName = type.GetFullName();
            var baseType = type.BaseType != null ? Type(type.BaseType, true) : Js.Null();
            var body = new JsBlockStatement();
            body.Assign(Js.This().Member(SpecialNames.TypeField), 
                CreateObject(Context.Instance.TypeConstructor, Js.Primitive(type.Name), CreateAttributes(type)));

            TypeFlags typeFlags = 0;
            if (type.ContainingType == null)
            {
                switch (type.DeclaredAccessibility)
                {
                    case Accessibility.Public:
                        typeFlags |= TypeFlags.Public;
                        break;
                    case Accessibility.Internal:
                        typeFlags |= TypeFlags.Internal;
                        break;
                    default:
                        throw new Exception();
                }                
            }
            else
            {
                switch (type.DeclaredAccessibility)
                {
                    case Accessibility.Public:
                        typeFlags |= TypeFlags.Public;
                        break;
                    case Accessibility.Internal:
                        typeFlags |= TypeFlags.Internal;
                        break;
                    case Accessibility.Private:
                        typeFlags |= TypeFlags.Private;
                        break;
                    case Accessibility.Protected:
                        typeFlags |= TypeFlags.Protected;
                        break;
                    case Accessibility.ProtectedOrInternal:
                        typeFlags |= TypeFlags.Private | TypeFlags.Internal;
                        break;
                    default:
                        throw new Exception();
                }
            }
            if (type.TypeKind == TypeKind.Interface)
            {
                typeFlags |= TypeFlags.Interface;
            }
            else if (type.TypeKind == TypeKind.Class)
            {
                typeFlags |= TypeFlags.Class;
            }
            else if (type.TypeKind == TypeKind.Enum)
            {
                typeFlags |= TypeFlags.Enum;
            }
            if (type.IsAbstract)
            {
                typeFlags |= TypeFlags.Abstract;
            }
            else if (type.IsSealed)
            {
                typeFlags |= TypeFlags.Sealed;
            }
            if (type.IsValueType)
            {
                typeFlags |= TypeFlags.ValueType;
            }
            if (type.IsPrimitive())
            {
                typeFlags |= TypeFlags.Primitive;
            }
            if (type.IsGenericType || type.IsAnonymousTypeWithTypeParameters())
            {
                typeFlags |= TypeFlags.GenericType;
            }
            if (type.TypeParameters.Any())
            {
                typeFlags |= TypeFlags.GenericTypeDefenition;
            }
            if (type.TypeKind == TypeKind.TypeParameter)
            {
                typeFlags |= TypeFlags.GenericParameter;
            }

            var arguments = new List<JsExpression>
            {
                Js.Primitive(explicitName ?? fullTypeName),          // Param1: fullTypeName
                Js.Primitive((int)typeFlags),
                Type(type, true), 
                baseType,
                CreateInterfaceReferences(type),
                MakeArray(Js.Array(type.TypeParameters.Select(x => Js.Reference(x.Name)).Concat(type.GetAnonymousTypeParameters().Select(x => Js.Reference(x.Item2))).ToArray()), Context.Instance.TypeArray)
            };

            if (!Context.Instance.Compilation.Assembly.IsReflectionMinimized())
            {
                arguments.AddRange(new[]
                {
                    CreateFieldInfos(type),
                    CreateMethodInfos(type, false),
                    CreateMethodInfos(type, true),
                    CreatePropertyInfos(type),
                    CreateEventInfos(type)
                });
            }

            body.Express(Invoke(Js.This().Member(SpecialNames.TypeField), Context.Instance.TypeInit, arguments.ToArray()));
            body.Return(Js.This().Member(SpecialNames.TypeField));
            var result = StoreInType(SpecialNames.CreateType, Js.Function().Body(body).Compact());
            return result;
        }
Exemplo n.º 51
0
        public override void VisitWhileStatement(WhileStatement whileStatement)
        {
            // Condition
            JsExpression condition;
            List<JsStatement> preBody = null;
            var compiledCondition = CompileExpression(whileStatement.Condition, true);
            if (compiledCondition.AdditionalStatements.Count == 0) {
                condition = compiledCondition.Expression;
            }
            else {
                // The condition requires additional statements. Transform "while ((SomeProperty = 1) < 0) { ... }" to "while (true) { this.set_SomeProperty(1); if (!(i < 1)) { break; } ... }
                preBody = new List<JsStatement>();
                preBody.AddRange(compiledCondition.AdditionalStatements);
                preBody.Add(new JsIfStatement(JsExpression.LogicalNot(compiledCondition.Expression), new JsBreakStatement(), null));
                condition = JsExpression.True;
            }

            var body = CreateInnerCompiler().Compile(whileStatement.EmbeddedStatement);
            if (preBody != null)
                body = new JsBlockStatement(preBody.Concat(body.Statements));

            _result.Add(new JsWhileStatement(condition, body));
        }
Exemplo n.º 52
0
        private JsExpression CreateMethodInfo(IMethodSymbol method, bool constructor = false)
        {
            JsExpression methodAttributes;
            switch (method.DeclaredAccessibility)
            {
                case Accessibility.Public:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesPublic);
                    break;
                case Accessibility.Internal:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesAssembly);
                    break;
                case Accessibility.Private:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesPrivate);
                    break;
                case Accessibility.Protected:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesFamily);
                    break;
                case Accessibility.ProtectedOrInternal:
                    methodAttributes = GetEnumValue(Context.Instance.MethodAttributesFamORAssem);
                    break;
                default:
                    throw new Exception();
            }
            if (method.IsStatic)
            {
                methodAttributes = EnumBitwise(SyntaxKind.BitwiseOrExpression, Context.Instance.MethodAttributes, 
                    methodAttributes, GetEnumValue(Context.Instance.MethodAttributesStatic));
            }

            var returnType = method.ReturnType;

            JsExpression info = constructor ?
                CreateObject(Context.Instance.ConstructorInfoConstructor,
                    Js.Primitive(method.GetMemberName()),
                    GetMethodFunction(method, true),
                    CreateParameterInfos(method.Parameters.ToArray()),
                    methodAttributes,
                    CreateAttributes(method)) :
                CreateObject(Context.Instance.MethodInfoConstructor,
                    Js.Primitive(method.MetadataName),
                    GetMethodFunction(method, true),
                    CreateParameterInfos(method.Parameters.ToArray()),
                    Type(returnType),
                    methodAttributes,
                    CreateAttributes(method));

            if (method.TypeParameters.Any())
            {
                var block = new JsBlockStatement();
                foreach (var typeParameter in method.TypeParameters)
                {
                    block.Local(
                        typeParameter.Name, 
                        Js.Reference(SpecialNames.DefineTypeParameter).Invoke(
                            Js.Reference(SpecialNames.Assembly),
                            Js.Primitive(typeParameter.Name), 
                            Type(typeParameter.BaseType ?? Context.Instance.ObjectType, true)));
                }
                block.Return(info);
                info = Wrap(block);
            }

            return info;
        }
		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 aquisitionResolveResult = _resolver.Resolve(aquisitionExpression);
			var compiledAquisition = _expressionCompiler.Compile(aquisitionResolveResult, true);

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

			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(JsStatement.Var(_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 = 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 = resource.Type.IsReferenceType == false && !resource.Type.IsKnownType(KnownTypeCode.NullableOfT) ? (JsStatement)compiledDisposeCall.Expression : JsStatement.If(compiledTest.Expression, compiledDisposeCall.Expression, null);
			}

			stmts.Add(JsStatement.Try(body, null, releaseStmt));

			return JsStatement.Block(stmts);
		}
 public bool Analyze(JsBlockStatement block)
 {
     _result = false;
     VisitStatement(block, null);
     return(_result);
 }