Beispiel #1
0
        internal JsBlockStatement Process(JsBlockStatement statement)
        {
            _allocateFinallyHandler = null;
            _makeSetCurrent         = null;
            var result      = Process(statement, false, 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)));
        }
Beispiel #2
0
 public void NewArgumentListContainsNoSpaces()
 {
     AssertCorrect(JsExpression.New(JsExpression.Identifier("x"), null), "new x");
     AssertCorrect(JsExpression.New(JsExpression.Identifier("x")), "new x()");
     AssertCorrect(JsExpression.New(JsExpression.Identifier("x"), JsExpression.Number(1), JsExpression.Number(2), JsExpression.Number(3)), "new x(1,2,3)");
 }
Beispiel #3
0
 public void ObjectLiteralsContainNoEmbeddedSpaces()
 {
     AssertCorrect(JsExpression.ObjectLiteral(), "{}");
     AssertCorrect(JsExpression.ObjectLiteral(new JsObjectLiteralProperty("x", JsExpression.Number(1))), "{x:1}");
     AssertCorrect(JsExpression.ObjectLiteral(new JsObjectLiteralProperty("x", JsExpression.Number(1)),
                                              new JsObjectLiteralProperty("y", JsExpression.Number(2)),
                                              new JsObjectLiteralProperty("z", JsExpression.Number(3))),
                   "{x:1,y:2,z:3}");
 }
Beispiel #4
0
 public void IfStatementIsCorrectlyOutput()
 {
     AssertCorrect(new JsIfStatement(JsExpression.True, new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0))), null),
                   "if(true){i=0;}");
     AssertCorrect(new JsIfStatement(JsExpression.True, new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0))), new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(1)))),
                   "if(true){i=0;}else{i=1;}");
 }
Beispiel #5
0
 public void WhileStatementIsCorrectlyOutput()
 {
     AssertCorrect(new JsWhileStatement(JsExpression.True, new JsBlockStatement(new JsVariableDeclarationStatement(new JsVariableDeclaration("x", JsExpression.Number(0))))),
                   "while(true){var x=0;}");
 }
        private static JsExpression ConstructConstructorInfo(IMethod constructor, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType)
        {
            var properties = GetCommonMemberInfoProperties(constructor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType);

            var sem = metadataImporter.GetConstructorSemantics(constructor);

            if (sem.Type == ConstructorScriptSemantics.ImplType.NotUsableFromScript)
            {
                errorReporter.Message(Messages._7200, constructor.FullName);
                return(JsExpression.Null);
            }
            properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Constructor)));
            properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(constructor.Parameters.Select(p => instantiateType(p.Type)))));
            if (sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod)
            {
                properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name)));
            }
            if (sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod)
            {
                properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True));
            }
            if ((sem.Type == ConstructorScriptSemantics.ImplType.UnnamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.NamedConstructor || sem.Type == ConstructorScriptSemantics.ImplType.StaticMethod) && sem.ExpandParams)
            {
                properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True));
            }
            if (sem.Type == ConstructorScriptSemantics.ImplType.Json || sem.Type == ConstructorScriptSemantics.ImplType.InlineCode)
            {
                var usedNames  = new HashSet <string>();
                var parameters = new List <IVariable>();
                var variables  = new Dictionary <IVariable, VariableData>();
                IList <ResolveResult> constructorParameters = null;
                IList <ResolveResult> initializerStatements = null;
                if (sem.Type == ConstructorScriptSemantics.ImplType.Json && constructor.DeclaringType.Kind == TypeKind.Anonymous)
                {
                    initializerStatements = new List <ResolveResult>();
                    foreach (var p in constructor.DeclaringType.GetProperties())
                    {
                        string paramName = MakeCamelCase(p.Name);
                        string name      = namer.GetVariableName(paramName, usedNames);
                        usedNames.Add(name);
                        var variable = new SimpleVariable(p.ReturnType, paramName, DomRegion.Empty);
                        parameters.Add(variable);
                        variables.Add(variable, new VariableData(name, null, false));
                        initializerStatements.Add(new OperatorResolveResult(p.ReturnType, ExpressionType.Assign, new MemberResolveResult(new InitializedObjectResolveResult(constructor.DeclaringType), p), new LocalResolveResult(variable)));
                    }
                }
                else
                {
                    constructorParameters = new List <ResolveResult>();
                    foreach (var p in constructor.Parameters)
                    {
                        string name = namer.GetVariableName(p.Name, usedNames);
                        usedNames.Add(name);
                        var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty);
                        parameters.Add(variable);
                        variables.Add(variable, new VariableData(name, null, false));
                        constructorParameters.Add(new LocalResolveResult(variable));
                    }
                }
                var compileResult = CompileConstructorInvocation(constructor, initializerStatements, constructor.DeclaringTypeDefinition, constructor, constructorParameters, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, variables, usedNames);
                var definition    = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), new JsBlockStatement(compileResult.AdditionalStatements.Concat(new[] { new JsReturnStatement(compileResult.Expression) })));
                properties.Add(new JsObjectLiteralProperty("def", definition));
            }
            return(JsExpression.ObjectLiteral(properties));
        }
Beispiel #7
0
 public void VariableDeclarationStatementsAreCorrectlyOutput()
 {
     AssertCorrect(new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration("i", null) }), "var i;");
     AssertCorrect(new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration("i", null), new JsVariableDeclaration("j", null) }), "var i,j;");
     AssertCorrect(new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration("i", JsExpression.Number(0)) }), "var i=0;");
     AssertCorrect(new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration("i", JsExpression.Number(0)), new JsVariableDeclaration("j", JsExpression.Number(1)) }), "var i=0,j=1;");
     AssertCorrect(new JsVariableDeclarationStatement(new[] { new JsVariableDeclaration("i", JsExpression.Number(0)), new JsVariableDeclaration("j", null) }), "var i=0,j;");
 }
        private void AddClassMembers(JsClass c, JsExpression typeRef, ICompilation compilation, List <JsStatement> stmts)
        {
            ICollection <JsMethod> instanceMethods;

            if (_metadataImporter.IsTestFixture(c.CSharpTypeDefinition))
            {
                var tests = new List <Tuple <string, string, bool, int?, JsFunctionDefinitionExpression> >();
                var instanceMethodList = new List <JsMethod>();
                foreach (var m in c.InstanceMethods)
                {
                    var td = (m.CSharpMember is IMethod ? _metadataImporter.GetTestData((IMethod)m.CSharpMember) : null);
                    if (td != null)
                    {
                        tests.Add(Tuple.Create(td.Description, td.Category, td.IsAsync, td.ExpectedAssertionCount, m.Definition));
                    }
                    else
                    {
                        instanceMethodList.Add(m);
                    }
                }
                var testInvocations = new List <JsExpression>();
                foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category))
                {
                    if (category.Category != null)
                    {
                        testInvocations.Add(JsExpression.Invocation(JsExpression.Identifier("module"), JsExpression.String(category.Category)));
                    }
                    testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This) })));
                }

                instanceMethodList.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], new JsBlockStatement(testInvocations.Select(t => new JsExpressionStatement(t))))));

                instanceMethods = instanceMethodList;
            }
            else
            {
                instanceMethods = c.InstanceMethods;
            }

            if (instanceMethods.Count > 0)
            {
                stmts.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, Prototype), JsExpression.ObjectLiteral(instanceMethods.Select(m => new JsObjectLiteralProperty(m.Name, m.Definition != null ? RewriteMethod(m) : JsExpression.Null))))));
            }

            if (c.NamedConstructors.Count > 0)
            {
                stmts.AddRange(c.NamedConstructors.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, m.Name), m.Definition))));
                stmts.Add(new JsExpressionStatement(c.NamedConstructors.Reverse().Aggregate((JsExpression)JsExpression.MemberAccess(typeRef, Prototype), (right, ctor) => JsExpression.Assign(JsExpression.MemberAccess(JsExpression.MemberAccess(typeRef, ctor.Name), Prototype), right))));                   // This generates a statement like {C}.ctor1.prototype = {C}.ctor2.prototype = {C}.prototoype
            }

            var defaultConstructor = c.CSharpTypeDefinition.GetConstructors().SingleOrDefault(x => x.Parameters.Count == 0 && x.IsPublic);

            if (defaultConstructor != null)
            {
                JsExpression createInstance = CreateDefaultConstructorInvocation(defaultConstructor, typeRef);
                if (createInstance != null)
                {
                    stmts.Add(new JsExpressionStatement(
                                  JsExpression.Assign(
                                      JsExpression.MemberAccess(typeRef, "createInstance"),
                                      JsExpression.FunctionDefinition(new string[0],
                                                                      new JsReturnStatement(createInstance)))));
                }
            }

            stmts.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, m.Name), RewriteMethod(m)))));

            if (c.TypeArgumentNames.Count > 0)
            {
                if (c.ClassType == JsClass.ClassTypeEnum.Interface)
                {
                    stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterGenericInterfaceInstance),
                                                                                typeRef,
                                                                                new JsTypeReferenceExpression(compilation.MainAssembly, c.Name),
                                                                                JsExpression.ArrayLiteral(c.TypeArgumentNames.Select(JsExpression.Identifier)),
                                                                                JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(c.ImplementedInterfaces))))));
                }
                else
                {
                    stmts.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterGenericClassInstance),
                                                                                typeRef,
                                                                                new JsTypeReferenceExpression(compilation.MainAssembly, c.Name),
                                                                                JsExpression.ArrayLiteral(c.TypeArgumentNames.Select(JsExpression.Identifier)),
                                                                                JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(c.BaseClass)),
                                                                                JsExpression.FunctionDefinition(new string[0], new JsReturnStatement(JsExpression.ArrayLiteral(c.ImplementedInterfaces))))));
                }
            }
        }
        public IList <JsStatement> Rewrite(IEnumerable <JsType> types, ICompilation compilation)
        {
            var netSystemType = compilation.FindType(KnownTypeCode.Type).GetDefinition();
            var systemType    = new JsTypeReferenceExpression(netSystemType.ParentAssembly, _metadataImporter.GetTypeSemantics(netSystemType).Name);

            var result = new List <JsStatement>();

            var    orderedTypes = OrderByNamespace(types, t => t.Name).ToList();
            string currentNs    = "";

            foreach (var t in orderedTypes)
            {
                try {
                    var globalMethodsPrefix = _metadataImporter.GetGlobalMethodsPrefix(t.CSharpTypeDefinition);

                    string ns = GetNamespace(t.Name);
                    if (ns != currentNs && globalMethodsPrefix == null)
                    {
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(systemType, RegisterNamespace), JsExpression.String(ns))));
                        currentNs = ns;
                    }
                    result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, t.Name);
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (globalMethodsPrefix != null)
                        {
                            if (globalMethodsPrefix == "")
                            {
                                result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.MemberAccess(JsExpression.Identifier("window"), m.Name), m.Definition))));
                            }
                            else
                            {
                                result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(globalMethodsPrefix + "." + m.Name), m.Definition))));
                            }
                        }
                        else if (_metadataImporter.IsResources(t.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);

                            if (c.TypeArgumentNames.Count == 0)
                            {
                                result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, unnamedCtor)));
                                AddClassMembers(c, typeRef, compilation, result);
                            }
                            else
                            {
                                var stmts = new List <JsStatement> {
                                    new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), compilation, stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(c.TypeArgumentNames, new JsBlockStatement(stmts)))));
                                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, c.ClassType == JsClass.ClassTypeEnum.Interface ? RegisterGenericInterface : RegisterGenericClass), JsExpression.String(c.Name), JsExpression.Number(c.TypeArgumentNames.Count))));
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var  e     = (JsEnum)t;
                        bool flags = GetAttributePositionalArgs(t.CSharpTypeDefinition, FlagsAttribute, "System") != null;
                        result.Add(new JsExpressionStatement(JsExpression.Assign(typeRef, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement))));
                        result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.MemberAccess(typeRef, Prototype), JsExpression.ObjectLiteral(e.Values.Select(v => new JsObjectLiteralProperty(v.Name, (_metadataImporter.IsNamedValues(t.CSharpTypeDefinition) ? JsExpression.String(v.Name) : JsExpression.Number(v.Value))))))));
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterEnum), JsExpression.String(t.Name), JsExpression.Boolean(flags))));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            var typesToRegister = orderedTypes.OfType <JsClass>()
                                  .Where(c => c.TypeArgumentNames.Count == 0 &&
                                         _metadataImporter.GetGlobalMethodsPrefix(c.CSharpTypeDefinition) == null &&
                                         !_metadataImporter.IsResources(c.CSharpTypeDefinition))
                                  .ToList();

            result.AddRange(TopologicalSortTypesByInheritance(typesToRegister)
                            .Select(c => {
                try {
                    var typeRef = new JsTypeReferenceExpression(compilation.MainAssembly, c.Name);
                    if (c.ClassType == JsClass.ClassTypeEnum.Interface)
                    {
                        return(JsExpression.Invocation(JsExpression.MemberAccess(typeRef, RegisterInterface), JsExpression.String(c.Name), JsExpression.ArrayLiteral(c.ImplementedInterfaces)));
                    }
                    else
                    {
                        return(CreateRegisterClassCall(JsExpression.String(c.Name), c.BaseClass, c.ImplementedInterfaces, typeRef));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = c.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName);
                    return(JsExpression.Number(0));
                }
            })
                            .Select(expr => new JsExpressionStatement(expr)));
            result.AddRange(orderedTypes.OfType <JsClass>().Where(c => c.TypeArgumentNames.Count == 0 && !_metadataImporter.IsResources(c.CSharpTypeDefinition)).SelectMany(t => t.StaticInitStatements));

            return(result);
        }
Beispiel #10
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)
        {
            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, 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 (_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));
            }
            else
            {
                var rewriter = new NestedJumpStatementRewriter(breakStack, continueStack, currentState, _exitState.Value);
                JsBlockStatement guarded;
                var guardedConstructs = FindInterestingConstructsVisitor.Analyze(stmt.GuardedStatement);
                if ((guardedConstructs & (InterestingConstruct.Label | InterestingConstruct.Await)) != InterestingConstruct.None)
                {
                    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);
            }
        }
Beispiel #11
0
        public JsExpression Default(IType type, IRuntimeContext context)
        {
            if (type.IsReferenceType == true || type.Kind == TypeKind.Dynamic || type.IsKnownType(KnownTypeCode.NullableOfT))
            {
                return(JsExpression.Null);
            }
            else if (type.Kind == TypeKind.Enum)
            {
                return(MetadataUtils.IsNamedValues(type.GetDefinition(), _attributeStore) ? JsExpression.Null : JsExpression.Number(0));
            }
            else if (type is ITypeDefinition)
            {
                switch (((ITypeDefinition)type).KnownTypeCode)
                {
                case KnownTypeCode.Boolean:
                    return(JsExpression.False);

                case KnownTypeCode.NullableOfT:
                    return(JsExpression.Null);

                case KnownTypeCode.DateTime:
                    return(JsExpression.New(CreateTypeReferenceExpression(KnownTypeReference.DateTime), JsExpression.Number(0)));

                case KnownTypeCode.Byte:
                case KnownTypeCode.SByte:
                case KnownTypeCode.Char:
                case KnownTypeCode.Int16:
                case KnownTypeCode.UInt16:
                case KnownTypeCode.Int32:
                case KnownTypeCode.UInt32:
                case KnownTypeCode.Int64:
                case KnownTypeCode.UInt64:
                case KnownTypeCode.Decimal:
                case KnownTypeCode.Single:
                case KnownTypeCode.Double:
                    return(JsExpression.Number(0));
                }
            }
            return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "getDefaultValue"), GetScriptType(type, TypeContext.GetScriptType, context)));
        }
Beispiel #12
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);
                    // 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> {
                    new JsLabelledStatement(_currentLoopLabel,
                                            new JsForStatement(new JsEmptyStatement(), null, null,
                                                               new JsSwitchStatement(JsExpression.Identifier(_stateVariableName),
                                                                                     sections.Select(b => new JsSwitchSection(
                                                                                                         GetAllContainedStateValues(b.State.StateValue).OrderBy(v => v).Select(v => JsExpression.Number(v)),
                                                                                                         new JsBlockStatement(b.Statements)))
                                                                                     .Concat(new[] { new JsSwitchSection(new JsExpression[] { null }, new JsBreakStatement(_currentLoopLabel)) }))))
                };
                return(Tuple.Create(body, sections[0].State.StateValue));
            }
            finally {
                _currentLoopLabel = oldLoopLabel;
                _remainingBlocks  = oldRemainingBlocks;
            }
        }
Beispiel #13
0
        private JsBlockStatement ProcessAsyncMethod(JsBlockStatement statement, string stateMachineMethodName, string doFinallyBlocksVariableName, JsVariableDeclaration taskCompletionSource, Func <JsExpression, JsExpression> makeSetResult, Func <JsExpression, JsExpression> makeSetException, Func <JsExpression> getTask)
        {
            _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();

            JsBlockStatement tryBody;

            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.
            {
                tryBody = new JsBlockStatement(hoistResult.Item1.Statements.Concat(new[] { new JsExpressionStatement(makeSetResult(null)) }));
            }
            else
            {
                tryBody = hoistResult.Item1;
            }

            JsStatement body = new JsTryStatement(tryBody, new JsCatchClause(catchVariable,
                                                                             taskCompletionSource != null
                                                                                             ? new JsBlockStatement(new JsExpressionStatement(makeSetException(JsExpression.Identifier(catchVariable))))
                                                                                             : JsBlockStatement.EmptyStatement), null);

            IEnumerable <JsVariableDeclaration> declarations = new[] { new JsVariableDeclaration(_stateVariableName, JsExpression.Number(0)) };

            if (taskCompletionSource != null)
            {
                declarations = declarations.Concat(new[] { taskCompletionSource });
            }
            declarations = declarations.Concat(hoistResult.Item2.Select(v => new JsVariableDeclaration(v, null)));

            if (_needDoFinallyBlocksVariable)
            {
                body = new JsBlockStatement(new JsVariableDeclarationStatement(_doFinallyBlocksVariableName, JsExpression.True), body);
            }

            IEnumerable <JsStatement> stmts = new JsStatement[] { new JsVariableDeclarationStatement(declarations),
                                                                  new JsVariableDeclarationStatement(stateMachineMethodName, JsExpression.FunctionDefinition(new string[0], body)),
                                                                  new JsExpressionStatement(JsExpression.Invocation(JsExpression.Identifier(stateMachineMethodName))) };

            if (taskCompletionSource != null)
            {
                stmts = stmts.Concat(new[] { new JsReturnStatement(getTask()) });
            }

            return(new JsBlockStatement(stmts));
        }
Beispiel #14
0
        private IteratorStateMachine ProcessIteratorBlock(JsBlockStatement statement, Func <string> allocateFinallyHandler, Func <JsExpression, JsExpression> makeSetCurrent)
        {
            _allocateFinallyHandler = allocateFinallyHandler;
            _makeSetCurrent         = makeSetCurrent;

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

            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));
        }
Beispiel #15
0
        private static JsStatement GenerateBody(string stateVariableName, List <Node> nodes)
        {
            if (nodes.Count == 0)
            {
                return(JsBlockStatement.EmptyStatement);
            }

            return(new JsSwitchStatement(JsExpression.Identifier(stateVariableName),
                                         nodes.Select(n => new JsSwitchSection(n.StateValues.Select(v => JsExpression.Number(v)),
                                                                               new JsTryStatement(
                                                                                   GenerateBody(stateVariableName, n.Children),
                                                                                   null,
                                                                                   new JsExpressionStatement(JsExpression.Invocation(JsExpression.MemberAccess(JsExpression.Identifier(n.HandlerName), "call"), JsExpression.This)))))));
        }
 public void CommaExpressionIsParenthesizedInsideObjectLiteral()
 {
     AssertCorrect(JsExpression.ObjectLiteral(new JsObjectLiteralProperty("x", JsExpression.Comma(JsExpression.Number(1), JsExpression.Number(2))),
                                              new JsObjectLiteralProperty("y", JsExpression.Number(3))),
                   "{ x: (1, 2), y: 3 }");
 }
Beispiel #17
0
        public static JsBlockStatement GenerateDisposer(string stateVariableName, List <Tuple <int, List <string> > > stateFinallyHandlers)
        {
            if (stateFinallyHandlers.Count == 0)
            {
                return(null);
            }

            return(new JsBlockStatement(
                       new JsTryStatement(
                           GenerateBody(stateVariableName, GenerateHandlerTree(stateFinallyHandlers)),
                           null,
                           new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(stateVariableName), JsExpression.Number(-1)))
                           )
                       ));
        }
 public void NumberIsParenthesizedWhenUsedAsMemberAccessTarget()
 {
     AssertCorrect(JsExpression.Member(JsExpression.Number(1), "X"), "(1).X");
 }
        public static JsExpression ConstructMemberInfo(IMember m, ICompilation compilation, IMetadataImporter metadataImporter, INamer namer, IRuntimeLibrary runtimeLibrary, IErrorReporter errorReporter, Func <IType, JsExpression> instantiateType, bool includeDeclaringType)
        {
            if (m is IMethod && ((IMethod)m).IsConstructor)
            {
                return(ConstructConstructorInfo((IMethod)m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType));
            }

            var properties = GetCommonMemberInfoProperties(m, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType);

            if (m.IsStatic)
            {
                properties.Add(new JsObjectLiteralProperty("isStatic", JsExpression.True));
            }

            if (m is IMethod)
            {
                var method = (IMethod)m;
                var sem    = metadataImporter.GetMethodSemantics(method);
                if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "method");
                    return(JsExpression.Null);
                }
                if ((sem.Type == MethodScriptSemantics.ImplType.NormalMethod || sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument) && sem.ExpandParams)
                {
                    properties.Add(new JsObjectLiteralProperty("exp", JsExpression.True));
                }

                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)));
                if (sem.Type == MethodScriptSemantics.ImplType.InlineCode)
                {
                    var usedNames  = new HashSet <string>();
                    var parameters = new List <IVariable>();
                    var variables  = new Dictionary <IVariable, VariableData>();
                    var arguments  = new List <ResolveResult>();
                    foreach (var p in method.Parameters)
                    {
                        string name = namer.GetVariableName(p.Name, usedNames);
                        usedNames.Add(name);
                        var variable = new SimpleVariable(p.Type, p.Name, DomRegion.Empty);
                        parameters.Add(variable);
                        variables.Add(variable, new VariableData(name, null, false));
                        arguments.Add(new LocalResolveResult(variable));
                    }
                    var tokens = InlineCodeMethodCompiler.Tokenize(method, sem.LiteralCode, _ => {});

                    var compileResult = Compile(new CSharpInvocationResolveResult(new ThisResolveResult(method.DeclaringType), method, arguments), method.DeclaringTypeDefinition, method, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, true, variables, usedNames);
                    var definition    = JsExpression.FunctionDefinition(parameters.Select(p => variables[p].Name), new JsBlockStatement(compileResult.AdditionalStatements.Concat(new[] { new JsReturnStatement(compileResult.Expression) })));

                    if (tokens.Any(t => t.Type == InlineCodeToken.TokenType.TypeParameter && t.OwnerType == EntityType.Method))
                    {
                        definition = JsExpression.FunctionDefinition(method.TypeParameters.Select(namer.GetTypeParameterName), new JsReturnStatement(definition));
                        properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count)));
                    }
                    properties.Add(new JsObjectLiteralProperty("def", definition));
                }
                else
                {
                    if (IsJsGeneric(method, metadataImporter))
                    {
                        properties.Add(new JsObjectLiteralProperty("tpcount", JsExpression.Number(method.TypeParameters.Count)));
                    }
                    if (sem.Type == MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument)
                    {
                        properties.Add(new JsObjectLiteralProperty("sm", JsExpression.True));
                    }
                    properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name)));
                }
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(method.ReturnType)));
                properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(method.Parameters.Select(p => instantiateType(p.Type)))));
            }
            else if (m is IField)
            {
                var field = (IField)m;
                var sem   = metadataImporter.GetFieldSemantics(field);
                if (sem.Type != FieldScriptSemantics.ImplType.Field)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "field");
                    return(JsExpression.Null);
                }
                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Field)));
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(field.ReturnType)));
                properties.Add(new JsObjectLiteralProperty("sname", JsExpression.String(sem.Name)));
            }
            else if (m is IProperty)
            {
                var prop = (IProperty)m;
                var sem  = metadataImporter.GetPropertySemantics(prop);
                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property)));
                properties.Add(new JsObjectLiteralProperty("returnType", instantiateType(prop.ReturnType)));
                if (prop.Parameters.Count > 0)
                {
                    properties.Add(new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(prop.Parameters.Select(p => instantiateType(p.Type)))));
                }

                switch (sem.Type)
                {
                case PropertyScriptSemantics.ImplType.GetAndSetMethods:
                    if (sem.GetMethod != null && sem.GetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.GetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.GetMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                    {
                        errorReporter.Message(Messages._7202, m.FullName, "property", "getter");
                        return(JsExpression.Null);
                    }
                    if (sem.SetMethod != null && sem.SetMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.SetMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.SetMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                    {
                        errorReporter.Message(Messages._7202, m.FullName, "property", "setter");
                        return(JsExpression.Null);
                    }
                    if (sem.GetMethod != null)
                    {
                        properties.Add(new JsObjectLiteralProperty("getter", ConstructMemberInfo(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)));
                    }
                    if (sem.SetMethod != null)
                    {
                        properties.Add(new JsObjectLiteralProperty("setter", ConstructMemberInfo(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)));
                    }
                    break;

                case PropertyScriptSemantics.ImplType.Field:
                    if (prop.CanGet)
                    {
                        properties.Add(new JsObjectLiteralProperty("getter", ConstructFieldPropertyAccessor(prop.Getter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: true, includeDeclaringType: includeDeclaringType)));
                    }
                    if (prop.CanSet)
                    {
                        properties.Add(new JsObjectLiteralProperty("setter", ConstructFieldPropertyAccessor(prop.Setter, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, sem.FieldName, instantiateType, isGetter: false, includeDeclaringType: includeDeclaringType)));
                    }
                    properties.Add(new JsObjectLiteralProperty("fname", JsExpression.String(sem.FieldName)));
                    break;

                default:
                    errorReporter.Message(Messages._7201, m.FullName, "property");
                    return(JsExpression.Null);
                }
            }
            else if (m is IEvent)
            {
                var evt = (IEvent)m;
                var sem = metadataImporter.GetEventSemantics(evt);
                if (sem.Type != EventScriptSemantics.ImplType.AddAndRemoveMethods)
                {
                    errorReporter.Message(Messages._7201, m.FullName, "event");
                    return(JsExpression.Null);
                }
                if (sem.AddMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.AddMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.AddMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7202, m.FullName, "event", "add accessor");
                    return(JsExpression.Null);
                }
                if (sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.NormalMethod && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.StaticMethodWithThisAsFirstArgument && sem.RemoveMethod.Type != MethodScriptSemantics.ImplType.InlineCode)
                {
                    errorReporter.Message(Messages._7202, m.FullName, "event", "remove accessor");
                    return(JsExpression.Null);
                }

                properties.Add(new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Event)));
                properties.Add(new JsObjectLiteralProperty("adder", ConstructMemberInfo(evt.AddAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)));
                properties.Add(new JsObjectLiteralProperty("remover", ConstructMemberInfo(evt.RemoveAccessor, compilation, metadataImporter, namer, runtimeLibrary, errorReporter, instantiateType, includeDeclaringType)));
            }
            else
            {
                throw new ArgumentException("Invalid member " + m);
            }

            return(JsExpression.ObjectLiteral(properties));
        }
Beispiel #20
0
        public IList <JsStatement> Process(IEnumerable <JsType> types, IMethod entryPoint)
        {
            var result = new List <JsStatement>();

            var orderedTypes = OrderByNamespace(types, t => _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name).ToList();

            foreach (var t in orderedTypes)
            {
                try {
                    string name     = _metadataImporter.GetTypeSemantics(t.CSharpTypeDefinition).Name;
                    bool   isGlobal = string.IsNullOrEmpty(name);
                    bool   isMixin  = MetadataUtils.IsMixin(t.CSharpTypeDefinition);

                    result.Add(new JsComment("//////////////////////////////////////////////////////////////////////////////" + Environment.NewLine + " " + t.CSharpTypeDefinition.FullName));

                    var typeRef = JsExpression.Identifier(_namer.GetTypeVariableName(name));
                    if (t is JsClass)
                    {
                        var c = (JsClass)t;
                        if (isGlobal)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Binary(ExpressionNodeType.Assign, JsExpression.Member(GetRoot(t.CSharpTypeDefinition, exportNonPublic: true), m.Name), m.Definition))));
                        }
                        else if (isMixin)
                        {
                            result.AddRange(c.StaticMethods.Select(m => new JsExpressionStatement(JsExpression.Assign(MakeNestedMemberAccess(name + "." + m.Name), m.Definition))));
                        }
                        else if (MetadataUtils.IsResources(c.CSharpTypeDefinition))
                        {
                            result.Add(GenerateResourcesClass(c));
                        }
                        else
                        {
                            var unnamedCtor = c.UnnamedConstructor ?? JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement);

                            if (MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter))
                            {
                                var typeParameterNames = c.CSharpTypeDefinition.TypeParameters.Select(tp => _namer.GetTypeParameterName(tp)).ToList();
                                var stmts = new List <JsStatement> {
                                    new JsVariableDeclarationStatement(InstantiatedGenericTypeVariableName, unnamedCtor)
                                };
                                AddClassMembers(c, JsExpression.Identifier(InstantiatedGenericTypeVariableName), stmts);
                                stmts.AddRange(c.StaticInitStatements);
                                stmts.Add(new JsReturnStatement(JsExpression.Identifier(InstantiatedGenericTypeVariableName)));
                                var replacer = new GenericSimplifier(c.CSharpTypeDefinition, typeParameterNames, JsExpression.Identifier(InstantiatedGenericTypeVariableName));
                                for (int i = 0; i < stmts.Count; i++)
                                {
                                    stmts[i] = replacer.Process(stmts[i]);
                                }
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(typeParameterNames, new JsBlockStatement(stmts))));
                                var args = new List <JsExpression> {
                                    GetRoot(t.CSharpTypeDefinition), JsExpression.String(name), typeRef, JsExpression.Number(c.CSharpTypeDefinition.TypeParameterCount)
                                };
                                var metadata = GetMetadataDescriptor(t.CSharpTypeDefinition, false);
                                if (metadata != null)
                                {
                                    args.Add(metadata);
                                }
                                result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(_systemScript, c.CSharpTypeDefinition.Kind == TypeKind.Interface ? RegisterGenericInterface : RegisterGenericClass), args)));
                            }
                            else
                            {
                                result.Add(new JsVariableDeclarationStatement(typeRef.Name, unnamedCtor));
                                AddClassMembers(c, typeRef, result);
                            }
                        }
                    }
                    else if (t is JsEnum)
                    {
                        var e = (JsEnum)t;
                        result.Add(new JsVariableDeclarationStatement(typeRef.Name, JsExpression.FunctionDefinition(new string[0], JsBlockStatement.EmptyStatement)));
                        var values = new List <JsObjectLiteralProperty>();
                        foreach (var v in e.CSharpTypeDefinition.Fields)
                        {
                            if (v.ConstantValue != null)
                            {
                                var sem = _metadataImporter.GetFieldSemantics(v);
                                if (sem.Type == FieldScriptSemantics.ImplType.Field)
                                {
                                    values.Add(new JsObjectLiteralProperty(sem.Name, JsExpression.Number(Convert.ToDouble(v.ConstantValue))));
                                }
                                else if (sem.Type == FieldScriptSemantics.ImplType.Constant && sem.Name != null)
                                {
                                    values.Add(new JsObjectLiteralProperty(sem.Name, sem.Value is string?JsExpression.String((string)sem.Value) : JsExpression.Number(Convert.ToDouble(sem.Value))));
                                }
                            }
                            else
                            {
                                _errorReporter.Region = v.Region;
                                _errorReporter.InternalError("Enum field " + v.FullName + " is not constant.");
                            }
                        }
                        result.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Member(typeRef, Prototype), JsExpression.ObjectLiteral(values))));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = t.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + t.CSharpTypeDefinition.FullName);
                }
            }

            var typesToRegister = orderedTypes
                                  .Where(c => !(c is JsClass && MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter)) &&
                                         !string.IsNullOrEmpty(_metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name) &&
                                         (!MetadataUtils.IsResources(c.CSharpTypeDefinition) || c.CSharpTypeDefinition.IsExternallyVisible()) &&                        // Resources classes are only exported if they are public.
                                         !MetadataUtils.IsMixin(c.CSharpTypeDefinition))
                                  .ToList();

            result.AddRange(TopologicalSortTypesByInheritance(typesToRegister)
                            .Select(c => {
                try {
                    string name = _metadataImporter.GetTypeSemantics(c.CSharpTypeDefinition).Name;
                    if (c.CSharpTypeDefinition.Kind == TypeKind.Enum)
                    {
                        return(CreateRegisterEnumCall(c.CSharpTypeDefinition, name, JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                    }
                    if (MetadataUtils.IsResources(c.CSharpTypeDefinition))
                    {
                        return(JsExpression.Invocation(JsExpression.Member(_systemScript, RegisterType), GetRoot(c.CSharpTypeDefinition), JsExpression.String(name), JsExpression.Identifier(_namer.GetTypeVariableName(name))));
                    }
                    if (c.CSharpTypeDefinition.Kind == TypeKind.Interface)
                    {
                        return(CreateRegisterInterfaceCall(c.CSharpTypeDefinition,
                                                           name,
                                                           JsExpression.Identifier(_namer.GetTypeVariableName(name)),
                                                           GetImplementedInterfaces(c.CSharpTypeDefinition.GetDefinition()).ToList()));
                    }
                    else
                    {
                        return(CreateRegisterClassCall(c.CSharpTypeDefinition,
                                                       name,
                                                       JsExpression.Identifier(_namer.GetTypeVariableName(name)),
                                                       GetBaseClass(c.CSharpTypeDefinition),
                                                       GetImplementedInterfaces(c.CSharpTypeDefinition).ToList()));
                    }
                }
                catch (Exception ex) {
                    _errorReporter.Region = c.CSharpTypeDefinition.Region;
                    _errorReporter.InternalError(ex, "Error formatting type " + c.CSharpTypeDefinition.FullName);
                    return(JsExpression.Number(0));
                }
            })
                            .Select(expr => new JsExpressionStatement(expr)));
            result.AddRange(GetStaticInitializationOrder(orderedTypes.OfType <JsClass>(), 1)
                            .Where(c => !MetadataUtils.IsJsGeneric(c.CSharpTypeDefinition, _metadataImporter) && !MetadataUtils.IsResources(c.CSharpTypeDefinition))
                            .SelectMany(c => c.StaticInitStatements));

            if (entryPoint != null)
            {
                if (entryPoint.Parameters.Count > 0)
                {
                    _errorReporter.Region = entryPoint.Region;
                    _errorReporter.Message(Messages._7800, entryPoint.FullName);
                }
                else
                {
                    var sem = _metadataImporter.GetMethodSemantics(entryPoint);
                    if (sem.Type != MethodScriptSemantics.ImplType.NormalMethod)
                    {
                        _errorReporter.Region = entryPoint.Region;
                        _errorReporter.Message(Messages._7801, entryPoint.FullName);
                    }
                    else
                    {
                        result.Add(new JsExpressionStatement(JsExpression.Invocation(JsExpression.Member(new JsTypeReferenceExpression(entryPoint.DeclaringTypeDefinition), sem.Name))));
                    }
                }
            }

            return(result);
        }
Beispiel #21
0
        public void ForStatementsAreCorrectlyOutput()
        {
            AssertCorrect(new JsForStatement(new JsVariableDeclarationStatement(new JsVariableDeclaration("i", JsExpression.Number(0))),
                                             JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                             JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")),
                                             JsBlockStatement.EmptyStatement),
                          "for(var i=0;i<10;i++){}");

            AssertCorrect(new JsForStatement(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0))),
                                             JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                             JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")),
                                             JsBlockStatement.EmptyStatement),
                          "for(i=0;i<10;i++){}");

            AssertCorrect(new JsForStatement(new JsVariableDeclarationStatement(new JsVariableDeclaration("i", JsExpression.Number(0)), new JsVariableDeclaration("j", JsExpression.Number(1))),
                                             JsExpression.Lesser(JsExpression.Identifier("i"), JsExpression.Number(10)),
                                             JsExpression.Comma(JsExpression.PostfixPlusPlus(JsExpression.Identifier("i")), JsExpression.PostfixPlusPlus(JsExpression.Identifier("j"))),
                                             JsBlockStatement.EmptyStatement),
                          "for(var i=0,j=1;i<10;i++,j++){}");

            AssertCorrect(new JsForStatement(new JsEmptyStatement(), null, null, JsBlockStatement.EmptyStatement), "for(;;){}");
        }
 private static JsStatement GenerateBody(string stateVariableName, List <Node> nodes)
 {
     return(JsStatement.Switch(JsExpression.Identifier(stateVariableName),
                               nodes.Select(n => JsStatement.SwitchSection(n.StateValues.Select(v => JsExpression.Number(v)),
                                                                           JsStatement.Try(
                                                                               n.Children.Count > 0 ? (JsStatement)JsStatement.Block(GenerateBody(stateVariableName, n.Children), JsStatement.Break()) : JsStatement.Break(),
                                                                               null,
                                                                               JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier(n.HandlerName), "call"), JsExpression.This))))));
 }
Beispiel #23
0
 public void IfAndElseIfStatementsAreChained()
 {
     AssertCorrect(new JsIfStatement(JsExpression.True, new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0))), null),
                   "if(true){i=0;}");
     AssertCorrect(new JsIfStatement(JsExpression.Identifier("a"), new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(0))),
                                     new JsIfStatement(JsExpression.Identifier("b"), new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(1))),
                                                       new JsIfStatement(JsExpression.Identifier("c"), new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(2))), new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("i"), JsExpression.Number(3)))))),
                   "if(a){i=0;}else if(b){i=1;}else if(c){i=2;}else{i=3;}");
 }
Beispiel #24
0
        private JsType ConvertType(JsClass type)
        {
            if (type.InstanceMethods.Any(m => m.Name == "runTests"))
            {
                _errorReporter.Region = type.CSharpTypeDefinition.Region;
                _errorReporter.Message(MessageSeverity.Error, 7019, string.Format("The type {0} cannot define a method named 'runTests' because it has a [TestFixtureAttribute].", type.CSharpTypeDefinition.FullName));
                return(type);
            }

            var instanceMethods = new List <JsMethod>();
            var tests           = new List <Tuple <string, string, bool, int?, JsFunctionDefinitionExpression> >();

            foreach (var method in type.InstanceMethods)
            {
                var testAttr = _attributeStore.AttributesFor(method.CSharpMember).GetAttribute <TestAttribute>();
                if (testAttr != null)
                {
                    if (!method.CSharpMember.IsPublic || !method.CSharpMember.ReturnType.IsKnownType(KnownTypeCode.Void) || ((IMethod)method.CSharpMember).Parameters.Count > 0 || ((IMethod)method.CSharpMember).TypeParameters.Count > 0)
                    {
                        _errorReporter.Region = method.CSharpMember.Region;
                        _errorReporter.Message(MessageSeverity.Error, 7020, string.Format("Method {0}: Methods decorated with a [TestAttribute] must be public, non-generic, parameterless instance methods that return void.", method.CSharpMember.FullName));
                    }

                    tests.Add(Tuple.Create(testAttr.Description ?? method.CSharpMember.Name, testAttr.Category, testAttr.IsAsync, testAttr.ExpectedAssertionCount >= 0 ? (int?)testAttr.ExpectedAssertionCount : null, method.Definition));
                }
                else
                {
                    instanceMethods.Add(method);
                }
            }

            var testInvocations = new List <JsExpression>();

            foreach (var category in tests.GroupBy(t => t.Item2).Select(g => new { Category = g.Key, Tests = g.Select(x => new { Description = x.Item1, IsAsync = x.Item3, ExpectedAssertionCount = x.Item4, Function = x.Item5 }) }).OrderBy(x => x.Category))
            {
                if (category.Category != null)
                {
                    testInvocations.Add(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("QUnit"), "module"), JsExpression.String(category.Category)));
                }
                testInvocations.AddRange(category.Tests.Select(t => JsExpression.Invocation(JsExpression.Identifier(t.IsAsync ? "asyncTest" : "test"), t.ExpectedAssertionCount != null ? new JsExpression[] { JsExpression.String(t.Description), JsExpression.Number(t.ExpectedAssertionCount.Value), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) } : new JsExpression[] { JsExpression.String(t.Description), _runtimeLibrary.Bind(t.Function, JsExpression.This, this) })));
            }

            instanceMethods.Add(new JsMethod(null, "runTests", null, JsExpression.FunctionDefinition(new string[0], JsStatement.Block(testInvocations.Select(t => (JsStatement)t)))));

            var result = type.Clone();

            result.InstanceMethods.Clear();
            foreach (var m in instanceMethods)
            {
                result.InstanceMethods.Add(m);
            }
            return(result);
        }
Beispiel #25
0
 public void SwitchStatementWorks()
 {
     AssertCorrect(new JsSwitchStatement(JsExpression.Identifier("x"),
                                         new JsSwitchSection(new[] { JsExpression.Number(0) }, new JsExpressionStatement(JsExpression.Identifier("a"))),
                                         new JsSwitchSection(new[] { JsExpression.Number(1), JsExpression.Number(2) }, new JsExpressionStatement(JsExpression.Identifier("b"))),
                                         new JsSwitchSection(new[] { null, JsExpression.Number(3) }, new JsExpressionStatement(JsExpression.Identifier("c")))
                                         ),
                   "switch(x){case 0:{a;}case 1:case 2:{b;}default:case 3:{c;}}");
 }
        public JsExpression Default(IType type, IRuntimeContext context)
        {
            if (type.IsReferenceType == true || type.Kind == TypeKind.Dynamic)
            {
                return(JsExpression.Null);
            }
            else if (type is ITypeParameter)
            {
                return(JsExpression.Invocation(JsExpression.Member(CreateTypeReferenceExpression(_systemScript), "getDefaultValue"), GetScriptType(type, TypeContext.GetScriptType, context)));
            }
            else if (type.Kind == TypeKind.Enum)
            {
                return(JsExpression.Number(0));
            }
            else
            {
                switch (type.GetDefinition().KnownTypeCode)
                {
                case KnownTypeCode.Boolean:
                    return(JsExpression.False);

                case KnownTypeCode.NullableOfT:
                    return(JsExpression.Null);

                case KnownTypeCode.DateTime:
                    return(JsExpression.New(CreateTypeReferenceExpression(KnownTypeReference.DateTime), JsExpression.Number(0)));

                case KnownTypeCode.Byte:
                case KnownTypeCode.SByte:
                case KnownTypeCode.Char:
                case KnownTypeCode.Int16:
                case KnownTypeCode.UInt16:
                case KnownTypeCode.Int32:
                case KnownTypeCode.UInt32:
                case KnownTypeCode.Int64:
                case KnownTypeCode.UInt64:
                case KnownTypeCode.Decimal:
                case KnownTypeCode.Single:
                case KnownTypeCode.Double:
                    return(JsExpression.Number(0));

                default:
                    return(JsExpression.Invocation(JsExpression.Member(InstantiateType(type, context), "getDefaultValue")));
                }
            }
        }
Beispiel #27
0
 public void InvocationArgumentListContainsNoSpaces()
 {
     AssertCorrect(JsExpression.Invocation(JsExpression.Identifier("x"), JsExpression.Number(1), JsExpression.Number(2), JsExpression.Number(3)), "x(1,2,3)");
 }
        public JsExpression GetExpressionForLocal(string name, JsExpression accessor, IType type, IRuntimeContext context)
        {
            var scriptType = TypeOf(type, context);

            JsExpression getterDefinition = JsExpression.FunctionDefinition(new string[0], JsStatement.Return(accessor));
            JsExpression setterDefinition = JsExpression.FunctionDefinition(new[] { "$" }, JsExpression.Assign(accessor, JsExpression.Identifier("$")));

            if (UsesThisVisitor.Analyze(accessor))
            {
                getterDefinition = JsExpression.Invocation(JsExpression.Member(getterDefinition, "bind"), JsExpression.This);
                setterDefinition = JsExpression.Invocation(JsExpression.Member(setterDefinition, "bind"), JsExpression.This);
            }

            return(JsExpression.ObjectLiteral(
                       new JsObjectLiteralProperty("ntype", JsExpression.Number((int)ExpressionType.MemberAccess)),
                       new JsObjectLiteralProperty("type", scriptType),
                       new JsObjectLiteralProperty("expression", JsExpression.ObjectLiteral(
                                                       new JsObjectLiteralProperty("ntype", JsExpression.Number((int)ExpressionType.Constant)),
                                                       new JsObjectLiteralProperty("type", scriptType),
                                                       new JsObjectLiteralProperty("value", JsExpression.ObjectLiteral())
                                                       )),
                       new JsObjectLiteralProperty("member", JsExpression.ObjectLiteral(
                                                       new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())),
                                                       new JsObjectLiteralProperty("name", JsExpression.String(name)),
                                                       new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Property)),
                                                       new JsObjectLiteralProperty("returnType", scriptType),
                                                       new JsObjectLiteralProperty("getter", JsExpression.ObjectLiteral(
                                                                                       new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())),
                                                                                       new JsObjectLiteralProperty("name", JsExpression.String("get_" + name)),
                                                                                       new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)),
                                                                                       new JsObjectLiteralProperty("returnType", scriptType),
                                                                                       new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral()),
                                                                                       new JsObjectLiteralProperty("def", getterDefinition)
                                                                                       )),
                                                       new JsObjectLiteralProperty("setter", JsExpression.ObjectLiteral(
                                                                                       new JsObjectLiteralProperty("typeDef", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Object).GetDefinition())),
                                                                                       new JsObjectLiteralProperty("name", JsExpression.String("set_" + name)),
                                                                                       new JsObjectLiteralProperty("type", JsExpression.Number((int)MemberTypes.Method)),
                                                                                       new JsObjectLiteralProperty("returnType", new JsTypeReferenceExpression(_compilation.FindType(KnownTypeCode.Void).GetDefinition())),
                                                                                       new JsObjectLiteralProperty("params", JsExpression.ArrayLiteral(scriptType)),
                                                                                       new JsObjectLiteralProperty("def", setterDefinition)
                                                                                       ))
                                                       ))
                       ));
        }
Beispiel #29
0
 public void ObjectLiteralWithFunctionValuesAreNotOutputOnMultipleLines()
 {
     AssertCorrect(JsExpression.ObjectLiteral(new JsObjectLiteralProperty("x", JsExpression.Number(1)),
                                              new JsObjectLiteralProperty("y", JsExpression.FunctionDefinition(new string[0], new JsReturnStatement())),
                                              new JsObjectLiteralProperty("z", JsExpression.Number(3))),
                   "{x:1,y:function(){return;},z:3}");
 }
        public void StatementsForEachPhaseAreSortedIndividuallyFirstByDependencyThenByTypeName()
        {
            var asm = Common.CreateMockAssembly();
            var a   = Common.CreateMockTypeDefinition("A", asm);
            var b   = Common.CreateMockTypeDefinition("B", asm);
            var c   = Common.CreateMockTypeDefinition("C", asm);
            var d   = Common.CreateMockTypeDefinition("D", asm);

            var phase1Deps = new Dictionary <ITypeDefinition, IEnumerable <ITypeDefinition> > {
                { a, new[] { b, c } },
                { b, new[] { d } },
                { c, new[] { d } },
                { d, new ITypeDefinition[0] },
            };
            var phase2Deps = new Dictionary <ITypeDefinition, IEnumerable <ITypeDefinition> > {
                { a, new[] { b, d } },
                { b, new[] { c } },
                { c, new ITypeDefinition[0] },
                { d, new[] { c } },
            };
            var phase3Deps = new Dictionary <ITypeDefinition, IEnumerable <ITypeDefinition> > {
                { a, new ITypeDefinition[0] },
                { b, new ITypeDefinition[0] },
                { c, new ITypeDefinition[0] },
                { d, new ITypeDefinition[0] },
            };

            AssertCorrect(new[] { new JsClass(a), new JsClass(b), new JsClass(c), new JsClass(d) },
                          @"D(1);
B(1);
C(1);
A(1);
C(2);
B(2);
D(2);
A(2);
A(3);
B(3);
C(3);
D(3);
", new MockOOPEmulator {
                EmulateType = t => new TypeOOPEmulation(new[] {
                    new TypeOOPEmulationPhase(phase1Deps[t.CSharpTypeDefinition], new[] { (JsStatement)JsExpression.Invocation(JsExpression.Identifier(t.CSharpTypeDefinition.Name), JsExpression.Number(1)) }),
                    new TypeOOPEmulationPhase(phase2Deps[t.CSharpTypeDefinition], new[] { (JsStatement)JsExpression.Invocation(JsExpression.Identifier(t.CSharpTypeDefinition.Name), JsExpression.Number(2)) }),
                    new TypeOOPEmulationPhase(phase3Deps[t.CSharpTypeDefinition], new[] { (JsStatement)JsExpression.Invocation(JsExpression.Identifier(t.CSharpTypeDefinition.Name), JsExpression.Number(3)) }),
                })
            }, null);
        }