public void VisitNode (JSDefaultValueLiteral dvl) {
            var parentBoe = ParentNode as JSBinaryOperatorExpression;

            if (CurrentName != "DefaultValue") {
                var thisReferenceType = dvl.GetActualType(TypeSystem);
                if (TypeUtil.IsStruct(thisReferenceType) && (parentBoe != null))
                    Initializations.Add(new InitializationInfo {
                        Type = thisReferenceType,
                        DefaultValueLiteral = dvl,
                        ParentBinaryExpression = parentBoe,
                        BinaryExpressionParent = Stack.Skip(2).First()
                    });
            }

            VisitChildren(dvl);
        }
예제 #2
0
        public void VisitNode (JSDefaultValueLiteral dvl) {
            var literalType = dvl.GetActualType(TypeSystem);
            if (IsLongOrULong(literalType)) {
                JSNode replacement;

                if (literalType.MetadataType == MetadataType.Int64)
                    replacement = GetLongLiteralExpression(0);
                else
                    replacement = GetLongLiteralExpression(0, unsigned: true);

                ParentNode.ReplaceChild(dvl, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(dvl);
        }
예제 #3
0
        public void VisitNode(JSDefaultValueLiteral dvl)
        {
            var expectedType = dvl.GetActualType(TypeSystem);

            if (
                IsNullable(expectedType)
                )
            {
                ParentNode.ReplaceChild(
                    dvl, JSLiteral.Null(expectedType)
                    );
            }
            else
            {
                VisitChildren(dvl);
            }
        }
예제 #4
0
        public void VisitNode(JSDefaultValueLiteral dvl)
        {
            var parentBoe = ParentNode as JSBinaryOperatorExpression;

            if (CurrentName != "DefaultValue")
            {
                var thisReferenceType = dvl.GetActualType(TypeSystem);
                if (TypeUtil.IsStruct(thisReferenceType) && (parentBoe != null))
                {
                    Initializations.Add(new InitializationInfo {
                        Type = thisReferenceType,
                        DefaultValueLiteral    = dvl,
                        ParentBinaryExpression = parentBoe,
                        BinaryExpressionParent = Stack.Skip(2).First()
                    });
                }
            }

            VisitChildren(dvl);
        }
예제 #5
0
파일: EmulateInt64.cs 프로젝트: ticuth/JSIL
        public void VisitNode(JSDefaultValueLiteral dvl)
        {
            var literalType = dvl.GetActualType(TypeSystem);

            if (IsLongOrULong(literalType))
            {
                JSNode replacement;

                if (literalType.MetadataType == MetadataType.Int64)
                {
                    replacement = GetLongLiteralExpression(0);
                }
                else
                {
                    replacement = GetLongLiteralExpression(0, unsigned: true);
                }

                ParentNode.ReplaceChild(dvl, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(dvl);
        }
예제 #6
0
        public void VisitNode(JSInvocationExpression ie)
        {
            var type = ie.JSType;
            var method = ie.JSMethod;
            var thisExpression = ie.ThisReference;

            if (method != null) {
                if (
                    (type != null) &&
                    (type.Type.FullName == "System.Object")
                ) {
                    switch (method.Method.Member.Name) {
                        case "GetType":
                            JSNode replacement;

                            var thisType = JSExpression.DeReferenceType(thisExpression.GetExpectedType(TypeSystem), false);
                            if ((thisType is GenericInstanceType) && thisType.FullName.StartsWith("System.Nullable")) {
                                replacement = new JSType(thisType);
                            } else {
                                replacement = JSIL.GetType(thisExpression);
                            }

                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);

                            return;
                    }
                } else if (
                    (type != null) &&
                    (type.Type.FullName.StartsWith("System.Nullable")) &&
                    (type.Type is GenericInstanceType)
                ) {
                    var t = (type.Type as GenericInstanceType).GenericArguments[0];
                    var @null = JSLiteral.Null(t);
                    var @default = new JSDefaultValueLiteral(t);

                    switch (method.Method.Member.Name) {
                        case ".ctor":
                            JSExpression value;
                            if (ie.Arguments.Count == 0) {
                                value = @null;
                            } else {
                                value = ie.Arguments[0];
                            }

                            var boe = new JSBinaryOperatorExpression(
                                JSOperator.Assignment, ie.ThisReference, value, type.Type
                            );
                            ParentNode.ReplaceChild(ie, boe);
                            VisitReplacement(boe);

                            break;
                        case "GetValueOrDefault":
                            var isNull = new JSBinaryOperatorExpression(
                                JSOperator.Equal, ie.ThisReference, @null, TypeSystem.Boolean
                            );

                            JSTernaryOperatorExpression ternary;
                            if (ie.Arguments.Count == 0) {
                                ternary = new JSTernaryOperatorExpression(
                                    isNull, @default, ie.ThisReference, type.Type
                                );
                            } else {
                                ternary = new JSTernaryOperatorExpression(
                                    isNull, ie.Arguments[0], ie.ThisReference, type.Type
                                );
                            }

                            ParentNode.ReplaceChild(ie, ternary);
                            VisitReplacement(ternary);

                            break;
                        default:
                            throw new NotImplementedException(method.Method.Member.FullName);
                    }

                    return;
                } else if (
                    (type != null) &&
                    ILBlockTranslator.TypesAreEqual(TypeSystem.String, type.Type) &&
                    (method.Method.Name == "Concat")
                ) {
                    if (ie.Arguments.Count > 2) {
                        if (ie.Arguments.All(
                            (arg) => ILBlockTranslator.TypesAreEqual(
                                TypeSystem.String, arg.GetExpectedType(TypeSystem)
                            )
                        )) {
                            var boe = JSBinaryOperatorExpression.New(
                                JSOperator.Add,
                                ie.Arguments,
                                TypeSystem.String
                            );

                            ParentNode.ReplaceChild(
                                ie,
                                boe
                            );

                            VisitReplacement(boe);
                        }
                    } else if (
                        ie.Arguments.Count == 2
                    ) {
                        var lhs = ie.Arguments[0];
                        var lhsType = ILBlockTranslator.DereferenceType(lhs.GetExpectedType(TypeSystem));
                        if (!(
                            ILBlockTranslator.TypesAreEqual(TypeSystem.String, lhsType) ||
                            ILBlockTranslator.TypesAreEqual(TypeSystem.Char, lhsType)
                        )) {
                            lhs = JSInvocationExpression.InvokeMethod(lhsType, JS.toString, lhs, null);
                        }

                        var rhs = ie.Arguments[1];
                        var rhsType = ILBlockTranslator.DereferenceType(rhs.GetExpectedType(TypeSystem));
                        if (!(
                            ILBlockTranslator.TypesAreEqual(TypeSystem.String, rhsType) ||
                            ILBlockTranslator.TypesAreEqual(TypeSystem.Char, rhsType)
                        )) {
                            rhs = JSInvocationExpression.InvokeMethod(rhsType, JS.toString, rhs, null);
                        }

                        var boe = new JSBinaryOperatorExpression(
                            JSOperator.Add, lhs, rhs, TypeSystem.String
                        );

                        ParentNode.ReplaceChild(
                            ie, boe
                        );

                        VisitReplacement(boe);
                    } else if (
                        ILBlockTranslator.GetTypeDefinition(ie.Arguments[0].GetExpectedType(TypeSystem)).FullName == "System.Array"
                    ) {
                    } else {
                        var firstArg = ie.Arguments.FirstOrDefault();

                        ParentNode.ReplaceChild(
                            ie, firstArg
                        );

                        if (firstArg != null)
                            VisitReplacement(firstArg);
                    }
                    return;
                } else if (
                    ILBlockTranslator.IsDelegateType(method.Reference.DeclaringType) &&
                    (method.Method.Name == "Invoke")
                ) {
                    var newIe = new JSDelegateInvocationExpression(
                        thisExpression, ie.GetExpectedType(TypeSystem), ie.Arguments.ToArray()
                    );
                    ParentNode.ReplaceChild(ie, newIe);

                    VisitReplacement(newIe);
                    return;
                } else if (
                    (method.Reference.DeclaringType.FullName == "System.Type") &&
                    (method.Method.Name == "GetTypeFromHandle")
                ) {
                    var typeObj = ie.Arguments.FirstOrDefault();
                    ParentNode.ReplaceChild(ie, typeObj);

                    VisitReplacement(typeObj);
                    return;
                } else if (
                    (method.Reference.DeclaringType.Name == "RuntimeHelpers") &&
                    (method.Method.Name == "InitializeArray")
                ) {
                    var array = ie.Arguments[0];
                    var arrayType = array.GetExpectedType(TypeSystem);
                    var field = ie.Arguments[1].SelfAndChildrenRecursive.OfType<JSField>().First();
                    var initializer = JSArrayExpression.UnpackArrayInitializer(arrayType, field.Field.Member.InitialValue);

                    var copy = JSIL.ShallowCopy(array, initializer, arrayType);
                    ParentNode.ReplaceChild(ie, copy);
                    VisitReplacement(copy);
                    return;
                } else if (
                    method.Method.DeclaringType.Definition.FullName == "System.Array" &&
                    (ie.Arguments.Count == 1)
                ) {
                    switch (method.Method.Name) {
                        case "GetLength":
                        case "GetUpperBound": {
                                var index = ie.Arguments[0] as JSLiteral;
                                if (index != null) {
                                    var newDot = JSDotExpression.New(thisExpression, new JSStringIdentifier(
                                        String.Format("length{0}", Convert.ToInt32(index.Literal)),
                                        TypeSystem.Int32
                                    ));

                                    if (method.Method.Name == "GetUpperBound") {
                                        var newExpr = new JSBinaryOperatorExpression(
                                            JSOperator.Subtract, newDot, JSLiteral.New(1), TypeSystem.Int32
                                        );
                                        ParentNode.ReplaceChild(ie, newExpr);
                                    } else {
                                        ParentNode.ReplaceChild(ie, newDot);
                                    }
                                }
                                break;
                            }
                        case "GetLowerBound":
                            ParentNode.ReplaceChild(ie, JSLiteral.New(0));
                            break;
                    }
                }
            }

            VisitChildren(ie);
        }
예제 #7
0
 public void VisitNode(JSDefaultValueLiteral dvl)
 {
     var expectedType = dvl.GetExpectedType(TypeSystem);
     if (
         (expectedType != null) &&
         expectedType.FullName.StartsWith("System.Nullable")
     ) {
         ParentNode.ReplaceChild(
             dvl, JSLiteral.Null(expectedType)
         );
     } else {
         VisitChildren(dvl);
     }
 }
예제 #8
0
        public void VisitNode (JSInvocationExpression ie) {
            var type = ie.JSType;
            var method = ie.JSMethod;
            var thisExpression = ie.ThisReference;

            if (method != null) {
                if (
                    (type != null) &&
                    (type.Type.FullName == "System.Object")
                ) {
                    switch (method.Method.Member.Name) {
                        case ".ctor": {
                            var replacement = new JSNullExpression();
                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);

                            return;
                        }

                        case "ReferenceEquals": {
                            var lhs = ie.Arguments[0];
                            var rhs = ie.Arguments[1];

                            var lhsType = lhs.GetActualType(TypeSystem);
                            var rhsType = rhs.GetActualType(TypeSystem);

                            JSNode replacement;

                            // Structs can never compare equal with ReferenceEquals
                            if (TypeUtil.IsStruct(lhsType) || TypeUtil.IsStruct(rhsType))
                                replacement = JSLiteral.New(false);
                            else
                                replacement = new JSBinaryOperatorExpression(
                                    JSOperator.Equal,
                                    lhs, rhs,
                                    TypeSystem.Boolean
                                );

                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);

                            return;
                        }

                        case "GetType": {
                            JSNode replacement;

                            var thisType = JSExpression.DeReferenceType(thisExpression.GetActualType(TypeSystem), false);
                            if ((thisType is GenericInstanceType) && thisType.FullName.StartsWith("System.Nullable")) {
                                var git = (GenericInstanceType)thisType;

                                replacement = new JSTernaryOperatorExpression(
                                    new JSBinaryOperatorExpression(
                                        JSOperator.NotEqual,
                                        thisExpression, new JSNullLiteral(thisType),
                                        TypeSystem.Boolean
                                    ),
                                    new JSTypeOfExpression(git.GenericArguments[0]),
                                    JSIL.ThrowNullReferenceException(),
                                    TypeSystem.SystemType()
                                );
                            } else {
                                replacement = JSIL.GetTypeOf(thisExpression);
                            }

                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);

                            return;
                        }
                    }
                } else if (
                    (type != null) &&
                    (type.Type.FullName == "System.ValueType")
                ) {
                    switch (method.Method.Member.Name) {
                        case "Equals": {
                            var replacement = JSIL.StructEquals(ie.ThisReference, ie.Arguments.First());
                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);

                            return;
                        }
                    }
                } else if (
                    (type != null) &&
                    IsNullable(type.Type)
                ) {
                    var t = (type.Type as GenericInstanceType).GenericArguments[0];
                    var @null = JSLiteral.Null(t);
                    var @default = new JSDefaultValueLiteral(t);

                    switch (method.Method.Member.Name) {
                        case ".ctor":
                            JSExpression value;
                            if (ie.Arguments.Count == 0) {
                                value = @null;
                            } else {
                                value = ie.Arguments[0];
                            }

                            var boe = new JSBinaryOperatorExpression(
                                JSOperator.Assignment, ie.ThisReference, value, type.Type
                            );
                            ParentNode.ReplaceChild(ie, boe);
                            VisitReplacement(boe);

                            break;

                        case "GetValueOrDefault": {
                            var replacement = JSIL.ValueOfNullableOrDefault(
                                ie.ThisReference,
                                (ie.Arguments.Count == 0)
                                    ? @default
                                    : ie.Arguments[0]
                            );

                            if (ParentNode is JSResultReferenceExpression) {
                                // HACK: Replacing the invocation inside a result reference is incorrect, so we need to walk up the stack
                                //  and replace the result reference with the ternary instead.
                                _ResultReferenceReplacement = replacement;
                            } else {
                                ParentNode.ReplaceChild(ie, replacement);
                                VisitReplacement(replacement);
                            }

                            break;
                        }

                        case "Equals":
                            JSBinaryOperatorExpression equality = new JSBinaryOperatorExpression(JSOperator.Equal, ie.ThisReference, ie.Parameters.First().Value, type.Type);
                            ParentNode.ReplaceChild(ie, equality);
                            VisitReplacement(equality);
                            break;

                        default:
                            throw new NotImplementedException(method.Method.Member.FullName);
                    }

                    return;
                } else if (
                    (type != null) &&
                    TypeUtil.TypesAreEqual(TypeSystem.String, type.Type) &&
                    (method.Method.Name == "Concat")
                ) {
                    if (ie.Arguments.Count > 2) {
                        if (ie.Arguments.All(
                            (arg) => TypeUtil.TypesAreEqual(
                                TypeSystem.String, arg.GetActualType(TypeSystem)
                            )
                        )) {
                            var boe = JSBinaryOperatorExpression.New(
                                JSOperator.Add,
                                ie.Arguments,
                                TypeSystem.String
                            );

                            ParentNode.ReplaceChild(
                                ie,
                                boe
                            );

                            VisitReplacement(boe);
                        }
                    } else if (
                        // HACK: Fix for #239, only convert concat call into + if both sides are non-null literals
                        (ie.Arguments.Count == 2)
                    ) {
                        var lhs = ie.Arguments[0];
                        var rhs = ie.Arguments[1];

                        var isAddOk = (lhs is JSStringLiteral) && (rhs is JSStringLiteral);

                        var lhsType = TypeUtil.DereferenceType(lhs.GetActualType(TypeSystem));
                        if (!(
                            TypeUtil.TypesAreEqual(TypeSystem.String, lhsType) ||
                            TypeUtil.TypesAreEqual(TypeSystem.Char, lhsType)
                        )) {
                            lhs = JSInvocationExpression.InvokeMethod(lhsType, JS.toString, lhs, null);
                            isAddOk = true;
                        }

                        var rhsType = TypeUtil.DereferenceType(rhs.GetActualType(TypeSystem));
                        if (!(
                            TypeUtil.TypesAreEqual(TypeSystem.String, rhsType) ||
                            TypeUtil.TypesAreEqual(TypeSystem.Char, rhsType)
                        )) {
                            rhs = JSInvocationExpression.InvokeMethod(rhsType, JS.toString, rhs, null);
                            isAddOk = true;
                        }

                        if (isAddOk) {
                            var boe = new JSBinaryOperatorExpression(
                                JSOperator.Add, lhs, rhs, TypeSystem.String
                            );

                            ParentNode.ReplaceChild(
                                ie, boe
                            );

                            VisitReplacement(boe);
                        }
                    } else if (
                        TypeUtil.GetTypeDefinition(ie.Arguments[0].GetActualType(TypeSystem)).FullName == "System.Array"
                    ) {
                    } else {
                        var firstArg = ie.Arguments.FirstOrDefault();

                        ParentNode.ReplaceChild(
                            ie, firstArg
                        );

                        if (firstArg != null)
                            VisitReplacement(firstArg);
                    }
                    return;
                } else if (
                    TypeUtil.IsDelegateType(method.Reference.DeclaringType) &&
                    (method.Method.Name == "Invoke")
                ) {
                    var newIe = new JSDelegateInvocationExpression(
                        thisExpression, ie.GetActualType(TypeSystem), ie.Arguments.ToArray()
                    );
                    ParentNode.ReplaceChild(ie, newIe);

                    VisitReplacement(newIe);
                    return;
                } else if (
                    (method.Reference.DeclaringType.Name == "RuntimeHelpers") &&
                    (method.Method.Name == "InitializeArray")
                ) {
                    var array = ie.Arguments[0];
                    var arrayType = array.GetActualType(TypeSystem);
                    var field = ie.Arguments[1].SelfAndChildrenRecursive.OfType<JSField>().First();
                    var initializer = JSArrayExpression.UnpackArrayInitializer(arrayType, field.Field.Member.InitialValue);

                    var copy = JSIL.ShallowCopy(array, initializer, arrayType);
                    ParentNode.ReplaceChild(ie, copy);
                    VisitReplacement(copy);
                    return;
                } else if (
                    method.Reference.DeclaringType.FullName == "System.Reflection.Assembly"
                ) {
                    switch (method.Reference.Name) {
                        case "GetExecutingAssembly": {
                            var assembly = Method.DeclaringType.Module.Assembly;
                            var asmNode = new JSReflectionAssembly(assembly);
                            ParentNode.ReplaceChild(ie, asmNode);
                            VisitReplacement(asmNode);

                            return;
                        }
                    }
                } else if (
                    method.Method.DeclaringType.Definition.FullName == "System.Array" &&
                    (ie.Arguments.Count == 1)
                ) {
                    switch (method.Method.Name) {
                        case "GetLength":
                        case "GetUpperBound": {
                                var index = ie.Arguments[0] as JSLiteral;
                                if (index != null) {
                                    var newDot = JSDotExpression.New(thisExpression, new JSStringIdentifier(
                                        String.Format("length{0}", Convert.ToInt32(index.Literal), true),
                                        TypeSystem.Int32
                                    ));

                                    if (method.Method.Name == "GetUpperBound") {
                                        var newExpr = new JSBinaryOperatorExpression(
                                            JSOperator.Subtract, newDot, JSLiteral.New(1), TypeSystem.Int32
                                        );
                                        ParentNode.ReplaceChild(ie, newExpr);
                                    } else {
                                        ParentNode.ReplaceChild(ie, newDot);
                                    }
                                }
                                break;
                            }
                        case "GetLowerBound":
                            ParentNode.ReplaceChild(ie, JSLiteral.New(0));
                            break;
                    }
                }
            }

            VisitChildren(ie);
        }
예제 #9
0
        public void VisitNode (JSDefaultValueLiteral dvl) {
            var expectedType = dvl.GetActualType(TypeSystem);

            if (
                IsNullable(expectedType)
            ) {
                ParentNode.ReplaceChild(
                    dvl, JSLiteral.Null(expectedType)
                );
            } else {
                VisitChildren(dvl);
            }
        }
예제 #10
0
        protected void TransformVariableIntoReference(JSVariable variable, JSVariableDeclarationStatement statement, int declarationIndex, JSBlockStatement enclosingBlock)
        {
            var oldDeclaration = statement.Declarations[declarationIndex];
            var valueType = oldDeclaration.Right.GetActualType(JSIL.TypeSystem);
            var newVariable = variable.Reference();
            var enclosingFunction = Stack.OfType<JSFunctionExpression>().First();

            JSExpression initialValue;
            // If the declaration was in function scope originally we can hoist the initial value
            //  into our new variable declaration. If not, we need to initialize the ref variable
            //  to the default value for its type. It will get the correct value assigned later.
            if (enclosingBlock == enclosingFunction.Body)
                initialValue = oldDeclaration.Right;
            else
                initialValue = new JSDefaultValueLiteral(valueType);

            var newDeclaration = new JSVariableDeclarationStatement(new JSBinaryOperatorExpression(
                JSOperator.Assignment,
                // We have to use a constructed ref to the variable here, otherwise
                //  the declaration will look like 'var x.value = foo'
                new JSVariable(variable.Identifier, variable.IdentifierType, variable.Function),
                JSIL.NewReference(initialValue),
                newVariable.IdentifierType
            ));

            if (Tracing)
                Debug.WriteLine(String.Format("Transformed {0} into {1} in {2}", variable, newVariable, statement));

            // Insert the new declaration directly before the top-level block containing the original
            //  declaration. This ensures that if its initial value has a dependency on external state,
            //  the declaration will not precede the values it depends on.
            // Note that for declarations that were hoisted out of inner blocks (conditionals, loops)
            //  it doesn't actually matter where the insert occurs, since we initialize with a default
            //  value in that case.
            enclosingFunction.Body.InsertNearChildRecursive(
                statement, newDeclaration, 0
            );

            // If the reference is being declared in function scope, it doesn't need a separate assignment
            //  for its initialization. Otherwise, we need to insert an assignment after the original variable
            //  declaration statement to ensure that the reference variable is initialized to the right value
            //  at the exact right point in the function's execution.
            if (enclosingBlock != enclosingFunction.Body) {
                var newAssignment = new JSExpressionStatement(
                    new JSBinaryOperatorExpression(
                        JSOperator.Assignment, newVariable, oldDeclaration.Right, valueType
                    )
                );
                var insertLocation = enclosingBlock.Statements.IndexOf(statement) + 1;
                enclosingBlock.Statements.Insert(insertLocation, newAssignment);
            }

            Variables[variable.Identifier] = newVariable;
            statement.Declarations.RemoveAt(declarationIndex);
            TransformedVariables.Add(variable.Identifier);
        }
        protected void TransformVariableIntoReference(JSVariable variable, JSVariableDeclarationStatement statement, int declarationIndex, JSBlockStatement enclosingBlock)
        {
            var oldDeclaration    = statement.Declarations[declarationIndex];
            var valueType         = oldDeclaration.Right.GetActualType(JSIL.TypeSystem);
            var newVariable       = variable.Reference();
            var enclosingFunction = Stack.OfType <JSFunctionExpression>().First();

            JSExpression initialValue;

            // If the declaration was in function scope originally we can hoist the initial value
            //  into our new variable declaration. If not, we need to initialize the ref variable
            //  to the default value for its type. It will get the correct value assigned later.
            if (enclosingBlock == enclosingFunction.Body)
            {
                initialValue = oldDeclaration.Right;
            }
            else
            {
                initialValue = new JSDefaultValueLiteral(valueType);
            }

            var newDeclaration = new JSVariableDeclarationStatement(new JSBinaryOperatorExpression(
                                                                        JSOperator.Assignment,
                                                                        // We have to use a constructed ref to the variable here, otherwise
                                                                        //  the declaration will look like 'var x.value = foo'
                                                                        new JSVariable(variable.Identifier, variable.IdentifierType, variable.Function),
                                                                        JSIL.NewReference(initialValue),
                                                                        newVariable.IdentifierType
                                                                        ));

            if (Tracing)
            {
                Console.WriteLine(String.Format("Transformed {0} into {1} in {2}", variable, newVariable, statement));
            }

            // Insert the new declaration directly before the top-level block containing the original
            //  declaration. This ensures that if its initial value has a dependency on external state,
            //  the declaration will not precede the values it depends on.
            // Note that for declarations that were hoisted out of inner blocks (conditionals, loops)
            //  it doesn't actually matter where the insert occurs, since we initialize with a default
            //  value in that case.
            enclosingFunction.Body.InsertNearChildRecursive(
                statement, newDeclaration, 0
                );

            // If the reference is being declared in function scope, it doesn't need a separate assignment
            //  for its initialization. Otherwise, we need to insert an assignment after the original variable
            //  declaration statement to ensure that the reference variable is initialized to the right value
            //  at the exact right point in the function's execution.
            if (enclosingBlock != enclosingFunction.Body)
            {
                var newAssignment = new JSExpressionStatement(
                    new JSBinaryOperatorExpression(
                        JSOperator.Assignment, newVariable, oldDeclaration.Right, valueType
                        )
                    );
                var insertLocation = enclosingBlock.Statements.IndexOf(statement) + 1;
                enclosingBlock.Statements.Insert(insertLocation, newAssignment);
            }

            Variables[variable.Identifier] = newVariable;
            statement.Declarations.RemoveAt(declarationIndex);
            TransformedVariables.Add(variable.Identifier);
        }
예제 #12
0
        public void VisitNode(JSInvocationExpression ie)
        {
            var type           = ie.JSType;
            var method         = ie.JSMethod;
            var thisExpression = ie.ThisReference;

            if (method != null)
            {
                if (
                    (type != null) &&
                    (type.Type.FullName == "System.Object")
                    )
                {
                    switch (method.Method.Member.Name)
                    {
                    case ".ctor": {
                        var replacement = new JSNullExpression();
                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }

                    case "ReferenceEquals": {
                        var lhs = ie.Arguments[0];
                        var rhs = ie.Arguments[1];

                        var lhsType = lhs.GetActualType(TypeSystem);
                        var rhsType = rhs.GetActualType(TypeSystem);

                        JSNode replacement;

                        // Structs can never compare equal with ReferenceEquals
                        if (TypeUtil.IsStruct(lhsType) || TypeUtil.IsStruct(rhsType))
                        {
                            replacement = JSLiteral.New(false);
                        }
                        else
                        {
                            replacement = new JSBinaryOperatorExpression(
                                JSOperator.Equal,
                                lhs, rhs,
                                TypeSystem.Boolean
                                );
                        }

                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }

                    case "GetType": {
                        JSNode replacement;

                        var thisType = JSExpression.DeReferenceType(thisExpression.GetActualType(TypeSystem), false);
                        if ((thisType is GenericInstanceType) && thisType.FullName.StartsWith("System.Nullable"))
                        {
                            var git = (GenericInstanceType)thisType;

                            replacement = new JSTernaryOperatorExpression(
                                new JSBinaryOperatorExpression(
                                    JSOperator.NotEqual,
                                    thisExpression, new JSNullLiteral(thisType),
                                    TypeSystem.Boolean
                                    ),
                                new JSTypeOfExpression(git.GenericArguments[0]),
                                JSIL.ThrowNullReferenceException(),
                                new TypeReference("System", "Type", TypeSystem.Object.Module, TypeSystem.Object.Scope, false)
                                );
                        }
                        else
                        {
                            replacement = JSIL.GetTypeOf(thisExpression);
                        }

                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }
                    }
                }
                else if (
                    (type != null) &&
                    (type.Type.FullName == "System.ValueType")
                    )
                {
                    switch (method.Method.Member.Name)
                    {
                    case "Equals": {
                        var replacement = JSIL.StructEquals(ie.ThisReference, ie.Arguments.First());
                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }
                    }
                }
                else if (
                    (type != null) &&
                    IsNullable(type.Type)
                    )
                {
                    var t        = (type.Type as GenericInstanceType).GenericArguments[0];
                    var @null    = JSLiteral.Null(t);
                    var @default = new JSDefaultValueLiteral(t);

                    switch (method.Method.Member.Name)
                    {
                    case ".ctor":
                        JSExpression value;
                        if (ie.Arguments.Count == 0)
                        {
                            value = @null;
                        }
                        else
                        {
                            value = ie.Arguments[0];
                        }

                        var boe = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, ie.ThisReference, value, type.Type
                            );
                        ParentNode.ReplaceChild(ie, boe);
                        VisitReplacement(boe);

                        break;

                    case "GetValueOrDefault": {
                        var replacement = JSIL.ValueOfNullableOrDefault(
                            ie.ThisReference,
                            (ie.Arguments.Count == 0)
                                    ? @default
                                    : ie.Arguments[0]
                            );

                        if (ParentNode is JSResultReferenceExpression)
                        {
                            // HACK: Replacing the invocation inside a result reference is incorrect, so we need to walk up the stack
                            //  and replace the result reference with the ternary instead.
                            _ResultReferenceReplacement = replacement;
                        }
                        else
                        {
                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);
                        }

                        break;
                    }

                    case "get_HasValue": {
                        var replacement = JSIL.NullableHasValue(ie.ThisReference);
                        if (ParentNode is JSResultReferenceExpression)
                        {
                            _ResultReferenceReplacement = replacement;
                        }
                        else
                        {
                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);
                        }

                        break;
                    }

                    case "get_Value": {
                        var replacement = JSIL.ValueOfNullable(ie.ThisReference);
                        if (ParentNode is JSResultReferenceExpression)
                        {
                            _ResultReferenceReplacement = replacement;
                        }
                        else
                        {
                            ParentNode.ReplaceChild(ie, replacement);
                            VisitReplacement(replacement);
                        }

                        break;
                    }

                    case "Equals":
                        JSBinaryOperatorExpression equality = new JSBinaryOperatorExpression(JSOperator.Equal, ie.ThisReference, ie.Parameters.First().Value, type.Type);
                        ParentNode.ReplaceChild(ie, equality);
                        VisitReplacement(equality);
                        break;

                    default:
                        throw new NotImplementedException(method.Method.Member.FullName);
                    }

                    return;
                }
                else if (
                    (type != null) &&
                    TypeUtil.TypesAreEqual(TypeSystem.String, type.Type) &&
                    (method.Method.Name == "Concat")
                    )
                {
                    if (ie.Arguments.Count > 2)
                    {
                        if (ie.Arguments.All(
                                (arg) => TypeUtil.TypesAreEqual(
                                    TypeSystem.String, arg.GetActualType(TypeSystem)
                                    )
                                ))
                        {
                            var boe = JSBinaryOperatorExpression.New(
                                JSOperator.Add,
                                ie.Arguments,
                                TypeSystem.String
                                );

                            ParentNode.ReplaceChild(
                                ie,
                                boe
                                );

                            VisitReplacement(boe);
                        }
                    }
                    else if (
                        // HACK: Fix for #239, only convert concat call into + if both sides are non-null literals
                        (ie.Arguments.Count == 2)
                        )
                    {
                        var lhs = ie.Arguments[0];
                        var rhs = ie.Arguments[1];

                        var isAddOk = (lhs is JSStringLiteral) && (rhs is JSStringLiteral);

                        var lhsType = TypeUtil.DereferenceType(lhs.GetActualType(TypeSystem));
                        if (!(
                                TypeUtil.TypesAreEqual(TypeSystem.String, lhsType) ||
                                TypeUtil.TypesAreEqual(TypeSystem.Char, lhsType)
                                ))
                        {
                            lhs     = JSInvocationExpression.InvokeMethod(lhsType, JS.toString, lhs, null);
                            isAddOk = true;
                        }

                        var rhsType = TypeUtil.DereferenceType(rhs.GetActualType(TypeSystem));
                        if (!(
                                TypeUtil.TypesAreEqual(TypeSystem.String, rhsType) ||
                                TypeUtil.TypesAreEqual(TypeSystem.Char, rhsType)
                                ))
                        {
                            rhs     = JSInvocationExpression.InvokeMethod(rhsType, JS.toString, rhs, null);
                            isAddOk = true;
                        }

                        if (isAddOk)
                        {
                            var boe = new JSBinaryOperatorExpression(
                                JSOperator.Add, lhs, rhs, TypeSystem.String
                                );

                            ParentNode.ReplaceChild(
                                ie, boe
                                );

                            VisitReplacement(boe);
                        }
                    }
                    else if (
                        TypeUtil.GetTypeDefinition(ie.Arguments[0].GetActualType(TypeSystem)).FullName == "System.Array"
                        )
                    {
                    }
                    else
                    {
                        var firstArg = ie.Arguments.FirstOrDefault();

                        ParentNode.ReplaceChild(
                            ie, firstArg
                            );

                        if (firstArg != null)
                        {
                            VisitReplacement(firstArg);
                        }
                    }
                    return;
                }
                else if (
                    TypeUtil.IsDelegateType(method.Reference.DeclaringType) &&
                    (method.Method.Name == "Invoke")
                    )
                {
                    var newIe = new JSDelegateInvocationExpression(
                        thisExpression, ie.GetActualType(TypeSystem), ie.Arguments.ToArray()
                        );
                    ParentNode.ReplaceChild(ie, newIe);

                    VisitReplacement(newIe);
                    return;
                }
                else if (
                    (method.Reference.DeclaringType.Name == "RuntimeHelpers") &&
                    (method.Method.Name == "InitializeArray")
                    )
                {
                    var array       = ie.Arguments[0];
                    var arrayType   = array.GetActualType(TypeSystem);
                    var field       = ie.Arguments[1].SelfAndChildrenRecursive.OfType <JSField>().First();
                    var initializer = JSArrayExpression.UnpackArrayInitializer(arrayType, field.Field.Member.InitialValue);

                    var copy = JSIL.ShallowCopy(array, initializer, arrayType);
                    ParentNode.ReplaceChild(ie, copy);
                    VisitReplacement(copy);
                    return;
                }
                else if (
                    method.Reference.DeclaringType.FullName == "System.Reflection.Assembly"
                    )
                {
                    switch (method.Reference.Name)
                    {
                    case "GetExecutingAssembly": {
                        var assembly = Method.DeclaringType.Module.Assembly;
                        var asmNode  = new JSReflectionAssembly(assembly);
                        ParentNode.ReplaceChild(ie, asmNode);
                        VisitReplacement(asmNode);

                        return;
                    }
                    }
                }
                else if (
                    method.Method.DeclaringType.Definition.FullName == "System.Array" &&
                    (ie.Arguments.Count == 1)
                    )
                {
                    switch (method.Method.Name)
                    {
                    case "GetLength":
                    case "GetUpperBound": {
                        var index = ie.Arguments[0] as JSLiteral;
                        if (index != null)
                        {
                            var newDot = JSDotExpression.New(thisExpression, new JSStringIdentifier(
                                                                 String.Format("length{0}", Convert.ToInt32(index.Literal)),
                                                                 TypeSystem.Int32
                                                                 ));

                            if (method.Method.Name == "GetUpperBound")
                            {
                                var newExpr = new JSBinaryOperatorExpression(
                                    JSOperator.Subtract, newDot, JSLiteral.New(1), TypeSystem.Int32
                                    );
                                ParentNode.ReplaceChild(ie, newExpr);
                            }
                            else
                            {
                                ParentNode.ReplaceChild(ie, newDot);
                            }
                        }
                        break;
                    }

                    case "GetLowerBound":
                        ParentNode.ReplaceChild(ie, JSLiteral.New(0));
                        break;
                    }
                }
            }

            VisitChildren(ie);
        }
예제 #13
0
        public void VisitNode(JSCastExpression ce)
        {
            var currentType = ce.Expression.GetActualType(TypeSystem);
            var targetType = ce.NewType;

            JSExpression newExpression = null;

            if (targetType.FullName == "System.ValueType") {
                var replacement = ce.Expression;
                ParentNode.ReplaceChild(ce, replacement);
                VisitReplacement(replacement);
                return;
            } else if (targetType.MetadataType == MetadataType.Char) {
                newExpression = JSInvocationExpression.InvokeStatic(
                    JS.fromCharCode, new[] { ce.Expression }, true
                );
            } else if (
                (currentType.MetadataType == MetadataType.Char) &&
                TypeUtil.IsIntegral(targetType)
            ) {
                newExpression = JSInvocationExpression.InvokeMethod(
                    JS.charCodeAt, ce.Expression, new[] { JSLiteral.New(0) }, true
                );
            } else if (
                IntroduceEnumCasts.IsEnumOrNullableEnum(currentType)
            ) {
                var enumInfo = TypeInfo.Get(currentType);
                var isNullable = TypeUtil.IsNullable(currentType);

                if (targetType.MetadataType == MetadataType.Boolean) {
                    EnumMemberInfo enumMember;
                    if (enumInfo.ValueToEnumMember.TryGetValue(0, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.NotEqual, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else if (enumInfo.ValueToEnumMember.TryGetValue(1, out enumMember)) {
                        newExpression = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ce.Expression,
                            new JSEnumLiteral(enumMember.Value, enumMember), TypeSystem.Boolean
                        );
                    } else {
                        newExpression = new JSUntranslatableExpression(String.Format(
                            "Could not cast enum of type '{0}' to boolean because it has no zero value or one value",
                            currentType.FullName
                        ));
                    }
                } else if (TypeUtil.IsNumeric(targetType)) {
                    if (isNullable) {
                        newExpression = JSIL.ValueOfNullable(
                            ce.Expression
                        );
                    } else {
                        newExpression = JSInvocationExpression.InvokeMethod(
                            JS.valueOf(targetType), ce.Expression, null, true
                        );
                    }
                } else if (targetType.FullName == "System.Enum") {
                    newExpression = ce.Expression;
                } else {
                    // Debugger.Break();
                }
            } else if (
                (targetType.MetadataType == MetadataType.Boolean) &&
                // A cast from Object to Boolean can occur in two forms:
                // An implied conversion, where an object expression is treated as a boolean (logicnot operation, etc).
                //  In this case, we want to do 'obj != null' to make it a boolean.
                // An explicit conversion, where an object expression is unboxed to boolean.
                //  In this case we want to leave it as-is.
                (ce.IsCoercion || (currentType.FullName != "System.Object"))
            ) {
                JSLiteral nullLiteral;

                // HACK: Necessary because we represent Char instances as JS strings. Issue #150
                // Is this right?
                if (currentType.FullName == "System.Char")
                    nullLiteral = new JSDefaultValueLiteral(currentType);
                else
                    nullLiteral = new JSNullLiteral(currentType);

                newExpression = new JSBinaryOperatorExpression(
                    JSBinaryOperator.NotEqual,
                    ce.Expression, nullLiteral,
                    TypeSystem.Boolean
                );
            } else if (
                TypeUtil.IsNumeric(targetType) &&
                TypeUtil.IsNumeric(currentType) &&
                !TypeUtil.TypesAreEqual(targetType, currentType, true)
            ) {
                if (currentType.MetadataType == MetadataType.Int64) {
                    if (targetType.MetadataType == MetadataType.UInt64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToUInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (currentType.MetadataType == MetadataType.UInt64) {
                    if (targetType.MetadataType == MetadataType.Int64) {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToInt64", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                    else {
                        newExpression = JSInvocationExpression
                            .InvokeMethod(
                                TypeSystem.Int64,
                                new JSFakeMethod("ToNumber", TypeSystem.Int32, new TypeReference[] { }, MethodTypeFactory),
                                ce.Expression);
                    }
                }
                else if (targetType.MetadataType == MetadataType.Int64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.Int64),
                        new JSFakeMethod("FromNumber", TypeSystem.Int64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (targetType.MetadataType == MetadataType.UInt64) {
                    newExpression = JSInvocationExpression.InvokeStatic(
                        new JSType(TypeSystem.UInt64),
                        new JSFakeMethod("FromNumber", TypeSystem.UInt64, new[] { currentType }, MethodTypeFactory),
                        new[] { ce.Expression },
                        true);
                }
                else if (
                    TypeUtil.IsIntegral(currentType) ||
                    !TypeUtil.IsIntegral(targetType))
                {
                    newExpression = ce.Expression;
                }
                else
                {
                    newExpression = new JSTruncateExpression(ce.Expression);
                }
            } else {
                // newExpression = JSIL.Cast(ce.Expression, targetType);
            }

            if (newExpression != null) {
                ParentNode.ReplaceChild(ce, newExpression);
                VisitReplacement(newExpression);
            } else {
                // Debugger.Break();
                VisitChildren(ce);
            }
        }
예제 #14
0
        public void VisitNode(JSDefaultValueLiteral dvl)
        {
            // We need to check this since it's a literal and it could show up in the tree multiple times.
            if (!dvl.CachedTypeIndex.HasValue) {
                var ct = GetCachedType(dvl.Value);
                if (ct != null)
                    dvl.CachedTypeIndex = ct.Index;
            }

            VisitChildren(dvl);
        }
예제 #15
0
        public void VisitNode(JSInvocationExpression ie)
        {
            var type           = ie.JSType;
            var method         = ie.JSMethod;
            var thisExpression = ie.ThisReference;

            if (method != null)
            {
                if (
                    (type != null) &&
                    (type.Type.FullName == "System.Object")
                    )
                {
                    switch (method.Method.Member.Name)
                    {
                    case ".ctor": {
                        var replacement = new JSNullExpression();
                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }

                    case "GetType": {
                        JSNode replacement;

                        var thisType = JSExpression.DeReferenceType(thisExpression.GetActualType(TypeSystem), false);
                        if ((thisType is GenericInstanceType) && thisType.FullName.StartsWith("System.Nullable"))
                        {
                            replacement = new JSType(thisType);
                        }
                        else
                        {
                            replacement = JSIL.GetTypeOf(thisExpression);
                        }

                        ParentNode.ReplaceChild(ie, replacement);
                        VisitReplacement(replacement);

                        return;
                    }
                    }
                }
                else if (
                    IsNullable(type.Type)
                    )
                {
                    var t        = (type.Type as GenericInstanceType).GenericArguments[0];
                    var @null    = JSLiteral.Null(t);
                    var @default = new JSDefaultValueLiteral(t);

                    switch (method.Method.Member.Name)
                    {
                    case ".ctor":
                        JSExpression value;
                        if (ie.Arguments.Count == 0)
                        {
                            value = @null;
                        }
                        else
                        {
                            value = ie.Arguments[0];
                        }

                        var boe = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, ie.ThisReference, value, type.Type
                            );
                        ParentNode.ReplaceChild(ie, boe);
                        VisitReplacement(boe);

                        break;

                    case "GetValueOrDefault":
                        var isNull = new JSBinaryOperatorExpression(
                            JSOperator.Equal, ie.ThisReference, @null, TypeSystem.Boolean
                            );

                        JSTernaryOperatorExpression ternary;
                        if (ie.Arguments.Count == 0)
                        {
                            ternary = new JSTernaryOperatorExpression(
                                isNull, @default, ie.ThisReference, type.Type
                                );
                        }
                        else
                        {
                            ternary = new JSTernaryOperatorExpression(
                                isNull, ie.Arguments[0], ie.ThisReference, type.Type
                                );
                        }

                        ParentNode.ReplaceChild(ie, ternary);
                        VisitReplacement(ternary);

                        break;

                    default:
                        throw new NotImplementedException(method.Method.Member.FullName);
                    }

                    return;
                }
                else if (
                    (type != null) &&
                    TypeUtil.TypesAreEqual(TypeSystem.String, type.Type) &&
                    (method.Method.Name == "Concat")
                    )
                {
                    if (ie.Arguments.Count > 2)
                    {
                        if (ie.Arguments.All(
                                (arg) => TypeUtil.TypesAreEqual(
                                    TypeSystem.String, arg.GetActualType(TypeSystem)
                                    )
                                ))
                        {
                            var boe = JSBinaryOperatorExpression.New(
                                JSOperator.Add,
                                ie.Arguments,
                                TypeSystem.String
                                );

                            ParentNode.ReplaceChild(
                                ie,
                                boe
                                );

                            VisitReplacement(boe);
                        }
                    }
                    else if (
                        ie.Arguments.Count == 2
                        )
                    {
                        var lhs     = ie.Arguments[0];
                        var lhsType = TypeUtil.DereferenceType(lhs.GetActualType(TypeSystem));
                        if (!(
                                TypeUtil.TypesAreEqual(TypeSystem.String, lhsType) ||
                                TypeUtil.TypesAreEqual(TypeSystem.Char, lhsType)
                                ))
                        {
                            lhs = JSInvocationExpression.InvokeMethod(lhsType, JS.toString, lhs, null);
                        }

                        var rhs     = ie.Arguments[1];
                        var rhsType = TypeUtil.DereferenceType(rhs.GetActualType(TypeSystem));
                        if (!(
                                TypeUtil.TypesAreEqual(TypeSystem.String, rhsType) ||
                                TypeUtil.TypesAreEqual(TypeSystem.Char, rhsType)
                                ))
                        {
                            rhs = JSInvocationExpression.InvokeMethod(rhsType, JS.toString, rhs, null);
                        }

                        var boe = new JSBinaryOperatorExpression(
                            JSOperator.Add, lhs, rhs, TypeSystem.String
                            );

                        ParentNode.ReplaceChild(
                            ie, boe
                            );

                        VisitReplacement(boe);
                    }
                    else if (
                        TypeUtil.GetTypeDefinition(ie.Arguments[0].GetActualType(TypeSystem)).FullName == "System.Array"
                        )
                    {
                    }
                    else
                    {
                        var firstArg = ie.Arguments.FirstOrDefault();

                        ParentNode.ReplaceChild(
                            ie, firstArg
                            );

                        if (firstArg != null)
                        {
                            VisitReplacement(firstArg);
                        }
                    }
                    return;
                }
                else if (
                    TypeUtil.IsDelegateType(method.Reference.DeclaringType) &&
                    (method.Method.Name == "Invoke")
                    )
                {
                    var newIe = new JSDelegateInvocationExpression(
                        thisExpression, ie.GetActualType(TypeSystem), ie.Arguments.ToArray()
                        );
                    ParentNode.ReplaceChild(ie, newIe);

                    VisitReplacement(newIe);
                    return;
                }
                else if (
                    (method.Reference.DeclaringType.FullName == "System.Type") &&
                    (method.Method.Name == "GetTypeFromHandle")
                    )
                {
                    var typeObj = ie.Arguments.FirstOrDefault();
                    ParentNode.ReplaceChild(ie, typeObj);

                    VisitReplacement(typeObj);
                    return;
                }
                else if (
                    (method.Reference.DeclaringType.Name == "RuntimeHelpers") &&
                    (method.Method.Name == "InitializeArray")
                    )
                {
                    var array       = ie.Arguments[0];
                    var arrayType   = array.GetActualType(TypeSystem);
                    var field       = ie.Arguments[1].SelfAndChildrenRecursive.OfType <JSField>().First();
                    var initializer = JSArrayExpression.UnpackArrayInitializer(arrayType, field.Field.Member.InitialValue);

                    var copy = JSIL.ShallowCopy(array, initializer, arrayType);
                    ParentNode.ReplaceChild(ie, copy);
                    VisitReplacement(copy);
                    return;
                }
                else if (
                    method.Reference.DeclaringType.FullName == "System.Reflection.Assembly"
                    )
                {
                    switch (method.Reference.Name)
                    {
                    case "GetExecutingAssembly": {
                        var assembly = Method.DeclaringType.Module.Assembly;
                        var asmNode  = new JSAssembly(assembly);
                        ParentNode.ReplaceChild(ie, asmNode);
                        VisitReplacement(asmNode);

                        return;
                    }

                    case "GetType": {
                        switch (method.Method.Parameters.Length)
                        {
                        case 1:
                        case 2:
                            JSExpression throwOnFail = new JSBooleanLiteral(false);
                            if (method.Method.Parameters.Length == 2)
                            {
                                throwOnFail = ie.Arguments[1];
                            }

                            var invocation = JSIL.GetTypeFromAssembly(
                                ie.ThisReference, ie.Arguments[0], throwOnFail
                                );
                            ParentNode.ReplaceChild(ie, invocation);
                            VisitReplacement(invocation);

                            return;
                        }

                        break;
                    }
                    }
                }
                else if (
                    method.Method.DeclaringType.Definition.FullName == "System.Array" &&
                    (ie.Arguments.Count == 1)
                    )
                {
                    switch (method.Method.Name)
                    {
                    case "GetLength":
                    case "GetUpperBound": {
                        var index = ie.Arguments[0] as JSLiteral;
                        if (index != null)
                        {
                            var newDot = JSDotExpression.New(thisExpression, new JSStringIdentifier(
                                                                 String.Format("length{0}", Convert.ToInt32(index.Literal)),
                                                                 TypeSystem.Int32
                                                                 ));

                            if (method.Method.Name == "GetUpperBound")
                            {
                                var newExpr = new JSBinaryOperatorExpression(
                                    JSOperator.Subtract, newDot, JSLiteral.New(1), TypeSystem.Int32
                                    );
                                ParentNode.ReplaceChild(ie, newExpr);
                            }
                            else
                            {
                                ParentNode.ReplaceChild(ie, newDot);
                            }
                        }
                        break;
                    }

                    case "GetLowerBound":
                        ParentNode.ReplaceChild(ie, JSLiteral.New(0));
                        break;
                    }
                }
            }

            VisitChildren(ie);
        }
예제 #16
0
        public void VisitNode(JSDefaultValueLiteral dvl)
        {
            var ct = GetCachedType(dvl.Value);
            if (ct != null)
                dvl.CachedTypeIndex = ct.Index;

            VisitChildren(dvl);
        }