Example #1
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var exType = uoe.Expression.GetActualType(TypeSystem);
            var opType = uoe.ActualType;
            if (IsLongOrULong(exType) && IsLongOrULong(opType)) //exType == TypeSystem.Int64 && opType == TypeSystem.Int64)
            {
                string verb;
                switch (uoe.Operator.Token)
                {
                    case "-":
                        verb = "op_UnaryNegation";
                        break;
                    case "~":
                        verb = "op_OnesComplement";
                        break;
                    default:
                        throw new NotSupportedException();
                }

                var method = new JSFakeMethod(verb, TypeSystem.Int64, new[] { TypeSystem.Int64 }, MethodTypeFactory);
                var replacement = JSInvocationExpression.InvokeStatic(exType, method, new[] { uoe.Expression }, true);
                ParentNode.ReplaceChild(uoe, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(uoe);
        }
Example #2
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var exType = uoe.Expression.GetActualType(TypeSystem);
            var opType = uoe.ActualType;

            if (IsLongOrULong(exType) && IsLongOrULong(opType)) //exType == TypeSystem.Int64 && opType == TypeSystem.Int64)
            {
                string verb;
                switch (uoe.Operator.Token)
                {
                case "-":
                    verb = "op_UnaryNegation";
                    break;

                case "~":
                    verb = "op_OnesComplement";
                    break;

                default:
                    throw new NotSupportedException();
                }

                var method      = new JSFakeMethod(verb, TypeSystem.Int64, new[] { TypeSystem.Int64 }, MethodTypeFactory);
                var replacement = JSInvocationExpression.InvokeStatic(exType, method, new[] { uoe.Expression }, true);
                ParentNode.ReplaceChild(uoe, replacement);
                VisitReplacement(replacement);
                return;
            }

            VisitChildren(uoe);
        }
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isIntegral = TypeUtil.Is32BitIntegral(type);

            if (isIntegral && (uoe.Operator is JSUnaryMutationOperator)) {
                if (
                    (uoe.Operator == JSOperator.PreIncrement) ||
                    (uoe.Operator == JSOperator.PreDecrement)
                ) {
                    var assignment = MakeUnaryMutation(
                        uoe.Expression,
                        (uoe.Operator == JSOperator.PreDecrement)
                            ? JSOperator.Subtract
                            : JSOperator.Add,
                        type
                    );

                    ParentNode.ReplaceChild(uoe, assignment);
                    VisitReplacement(assignment);
                    return;

                } else if (
                    (uoe.Operator == JSOperator.PostIncrement) ||
                    (uoe.Operator == JSOperator.PostDecrement)
                ) {
                    // FIXME: Terrible hack
                    var tempVariable = TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                    );
                    var makeTempCopy = new JSBinaryOperatorExpression(
                        JSOperator.Assignment, tempVariable, uoe.Expression, type
                    );
                    var assignment = MakeUnaryMutation(
                        uoe.Expression,
                        (uoe.Operator == JSOperator.PostDecrement)
                            ? JSOperator.Subtract
                            : JSOperator.Add,
                        type
                    );

                    var comma = new JSCommaExpression(
                        makeTempCopy,
                        assignment,
                        tempVariable
                    );

                    ParentNode.ReplaceChild(uoe, comma);
                    VisitReplacement(comma);
                    return;

                } else {
                    throw new NotImplementedException("Unary mutation not supported: " + uoe.ToString());
                }
            }

            VisitChildren(uoe);
        }
Example #4
0
        public static bool ExtractOffsetFromPointerExpression(JSExpression pointer, TypeSystem typeSystem, out JSExpression newPointer, out JSExpression offset)
        {
            pointer = JSPointerExpressionUtil.UnwrapExpression(pointer);

            offset     = null;
            newPointer = pointer;

            var boe = pointer as JSBinaryOperatorExpression;

            if (boe == null)
            {
                return(false);
            }

            if (boe.Right.IsNull)
            {
                return(false);
            }

            var right = JSPointerExpressionUtil.UnwrapExpression(boe.Right);

            var rightType  = right.GetActualType(typeSystem);
            var resultType = boe.GetActualType(typeSystem);

            if (!resultType.IsPointer)
            {
                return(false);
            }

            if (
                !TypeUtil.IsIntegral(rightType) &&
                // Adding pointers together shouldn't be valid but ILSpy generates it. Pfft.
                !TypeUtil.IsPointer(rightType)
                )
            {
                return(false);
            }

            if (boe.Operator == JSOperator.Subtract)
            {
                newPointer = boe.Left;
                offset     = new JSUnaryOperatorExpression(JSOperator.Negation, right, rightType);
                return(true);
            }
            else if (boe.Operator == JSOperator.Add)
            {
                newPointer = boe.Left;
                offset     = right;
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #5
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var isBoolean = TypeUtil.IsBoolean(uoe.GetActualType(TypeSystem));

            if (isBoolean)
            {
                if (uoe.Operator == JSOperator.IsTrue)
                {
                    ParentNode.ReplaceChild(
                        uoe, uoe.Expression
                        );

                    VisitReplacement(uoe.Expression);
                    return;
                }
                else if (uoe.Operator == JSOperator.LogicalNot)
                {
                    var nestedUoe = uoe.Expression as JSUnaryOperatorExpression;
                    var boe       = uoe.Expression as JSBinaryOperatorExpression;

                    JSBinaryOperator newOperator;
                    if ((boe != null) &&
                        InvertedOperators.TryGetValue(boe.Operator, out newOperator)
                        )
                    {
                        var newBoe = new JSBinaryOperatorExpression(
                            newOperator, boe.Left, boe.Right, boe.ActualType
                            );

                        ParentNode.ReplaceChild(uoe, newBoe);
                        VisitReplacement(newBoe);

                        return;
                    }
                    else if (
                        (nestedUoe != null) &&
                        (nestedUoe.Operator == JSOperator.LogicalNot)
                        )
                    {
                        var nestedExpression = nestedUoe.Expression;

                        ParentNode.ReplaceChild(uoe, nestedExpression);
                        VisitReplacement(nestedExpression);

                        return;
                    }
                }
            }

            VisitChildren(uoe);
        }
Example #6
0
        public void VisitNode(JSUnaryOperatorExpression uop)
        {
            if (!uop.IsPostfix)
            {
                Output.WriteRaw(uop.Operator.Token);
            }

            Visit(uop.Expression);

            if (uop.IsPostfix)
            {
                Output.WriteRaw(uop.Operator.Token);
            }
        }
Example #7
0
        public static JSExpression DecomposeUnaryMutation(
            JSUnaryOperatorExpression uoe, Func <JSRawOutputIdentifier> makeTemporaryVariable, TypeReference type, TypeSystem typeSystem
            )
        {
            if (
                (uoe.Operator == JSOperator.PreIncrement) ||
                (uoe.Operator == JSOperator.PreDecrement)
                )
            {
                var assignment = MakeUnaryMutation(
                    uoe.Expression,
                    (uoe.Operator == JSOperator.PreDecrement)
                        ? JSOperator.Subtract
                        : JSOperator.Add,
                    type, typeSystem
                    );

                return(assignment);
            }
            else if (
                (uoe.Operator == JSOperator.PostIncrement) ||
                (uoe.Operator == JSOperator.PostDecrement)
                )
            {
                // FIXME: Terrible hack
                var tempVariable = makeTemporaryVariable();
                var makeTempCopy = new JSBinaryOperatorExpression(
                    JSOperator.Assignment, tempVariable, uoe.Expression, type
                    );
                var assignment = MakeUnaryMutation(
                    uoe.Expression,
                    (uoe.Operator == JSOperator.PostDecrement)
                        ? JSOperator.Subtract
                        : JSOperator.Add,
                    type, typeSystem
                    );

                var comma = new JSCommaExpression(
                    makeTempCopy,
                    assignment,
                    tempVariable
                    );

                return(comma);
            }
            else
            {
                throw new NotImplementedException("Unary mutation not supported: " + uoe);
            }
        }
Example #8
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var isBoolean = TypeUtil.IsBoolean(uoe.GetActualType(TypeSystem));

            if (isBoolean) {
                if (uoe.Operator == JSOperator.IsTrue) {
                    ParentNode.ReplaceChild(
                        uoe, uoe.Expression
                    );

                    VisitReplacement(uoe.Expression);
                    return;
                } else if (uoe.Operator == JSOperator.LogicalNot) {
                    var nestedUoe = uoe.Expression as JSUnaryOperatorExpression;
                    var boe = uoe.Expression as JSBinaryOperatorExpression;

                    JSBinaryOperator newOperator;
                    if ((boe != null) &&
                        InvertedOperators.TryGetValue(boe.Operator, out newOperator)
                    ) {
                        var newBoe = new JSBinaryOperatorExpression(
                            newOperator, boe.Left, boe.Right, boe.ActualType
                        );

                        ParentNode.ReplaceChild(uoe, newBoe);
                        VisitReplacement(newBoe);

                        return;
                    } else if (
                        (nestedUoe != null) &&
                        (nestedUoe.Operator == JSOperator.LogicalNot)
                    ) {
                        var nestedExpression = nestedUoe.Expression;

                        ParentNode.ReplaceChild(uoe, nestedExpression);
                        VisitReplacement(nestedExpression);

                        return;
                    }
                }
            }

            VisitChildren(uoe);
        }
Example #9
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type = uoe.Expression.GetExpectedType(TypeSystem);
            var isEnum = ILBlockTranslator.IsEnum(type);

            if (isEnum) {
                var cast = JSInvocationExpression.InvokeMethod(
                    new JSFakeMethod("valueOf", TypeSystem.Int32, type), uoe.Expression, null, true
                );

                if (LogicalOperators.Contains(uoe.Operator)) {
                    uoe.ReplaceChild(uoe.Expression, cast);
                } else if (uoe.Operator == JSOperator.Negation) {
                    uoe.ReplaceChild(uoe.Expression, cast);
                }
            }

            VisitChildren(uoe);
        }
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            JSUnaryMutationOperator op;
            JSExpression            target;
            TypeReference           type;

            if (UnpackUnaryMutation(uoe, out op, out target, out type))
            {
                var tempVar = TemporaryVariable.ForFunction(
                    Stack.Last() as JSFunctionExpression, type
                    );
                var store = new JSBinaryOperatorExpression(
                    JSOperator.Assignment, tempVar, target, type
                    );

                var delta = (
                    (op == JSOperator.PostIncrement) ||
                    (op == JSOperator.PreIncrement)
                    )
                    ? 1
                    : -1;

                JSExpression replacement;
                if (
                    (op == JSOperator.PostIncrement) ||
                    (op == JSOperator.PostDecrement)
                    )
                {
                    var mutated = new JSPointerAddExpression(target, JSLiteral.New(delta), false);
                    replacement = new JSCommaExpression(store, mutated, tempVar);
                }
                else
                {
                    replacement = new JSPointerAddExpression(target, JSLiteral.New(delta), true);
                }

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

            VisitChildren(uoe);
        }
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            JSExpression expr;

            if (!JSReferenceExpression.TryDereference(JSIL, uoe.Expression, out expr))
            {
                expr = uoe.Expression;
            }

            var eVar        = expr as JSVariable;
            var eChangeType = expr as JSChangeTypeExpression;

            if (eChangeType != null)
            {
                eVar = eChangeType.Expression as JSVariable;
            }

            var type = uoe.Expression.GetActualType(TypeSystem);

            if (
                (eVar != null) &&
                (eVar.Identifier == Variable.Identifier) &&
                (uoe.Operator is JSUnaryMutationOperator)
                )
            {
                var newValue = DecomposeMutationOperators.DecomposeUnaryMutation(
                    uoe, () => TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                        ), type, TypeSystem
                    );
                var replacement = new JSWriteThroughReferenceExpression(
                    Variable, newValue
                    );
                ParentNode.ReplaceChild(uoe, replacement);
                VisitReplacement(replacement);
            }
            else
            {
                VisitChildren(uoe);
            }
        }
Example #12
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type       = uoe.Expression.GetActualType(TypeSystem);
            var isIntegral = TypeUtil.Is32BitIntegral(type);

            if (isIntegral && (uoe.Operator is JSUnaryMutationOperator))
            {
                var replacement = DecomposeUnaryMutation(
                    uoe,
                    () => TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                        ),
                    type, TypeSystem
                    );

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

            VisitChildren(uoe);
        }
Example #13
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var variable  = ExtractAffectedVariable(uoe.Expression);
            var isMutator = uoe.Operator is JSUnaryMutationOperator;

            VisitChildren(uoe);

            if (isMutator)
            {
                if (variable != null)
                {
                    State.Assignments.Add(
                        new FunctionAnalysis1stPass.Assignment(
                            GetParentNodeIndices(), StatementIndex, NodeIndex,
                            variable, uoe, uoe.Operator,
                            variable.GetActualType(TypeSystem), uoe.GetActualType(TypeSystem)
                            )
                        );

                    ModifiedVariable(variable);
                }
            }
        }
        private bool UnpackUnaryMutation(
            JSUnaryOperatorExpression uoe,
            out JSUnaryMutationOperator op,
            out JSExpression target,
            out TypeReference type
            )
        {
            type = uoe.Expression.GetActualType(TypeSystem);

            if (
                TypeUtil.IsPointer(type) &&
                (uoe.Operator is JSUnaryMutationOperator)
                )
            {
                target = uoe.Expression;
                op     = (JSUnaryMutationOperator)uoe.Operator;
                return(true);
            }

            target = null;
            op     = null;
            return(false);
        }
Example #15
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type   = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum)
            {
                var cast = JSInvocationExpression.InvokeStatic(
                    JS.Number(TypeSystem.Int32), new[] { uoe.Expression }, true
                    );

                if (LogicalOperators.Contains(uoe.Operator))
                {
                    uoe.ReplaceChild(uoe.Expression, cast);
                }
                else if (uoe.Operator == JSOperator.Negation)
                {
                    uoe.ReplaceChild(uoe.Expression, cast);
                }
            }

            VisitChildren(uoe);
        }
Example #16
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum) {
                var cast = JSInvocationExpression.InvokeMethod(
                    JS.valueOf(TypeSystem.Int32), uoe.Expression, null, true
                );

                if (LogicalOperators.Contains(uoe.Operator)) {
                    uoe.ReplaceChild(uoe.Expression, cast);
                } else if (uoe.Operator == JSOperator.Negation) {
                    uoe.ReplaceChild(uoe.Expression, cast);
                }
            }

            VisitChildren(uoe);
        }
Example #17
0
        private bool UnpackUnaryMutation (
            JSUnaryOperatorExpression uoe,
            out JSUnaryMutationOperator op,
            out JSExpression target,
            out TypeReference type
        ) {
            type = uoe.Expression.GetActualType(TypeSystem);

            if (
                TypeUtil.IsPointer(type) &&
                (uoe.Operator is JSUnaryMutationOperator)
            ) {
                target = uoe.Expression;
                op = (JSUnaryMutationOperator)uoe.Operator;
                return true;
            }

            target = null;
            op = null;
            return false;
        }
Example #18
0
        public void VisitNode (JSBinaryOperatorExpression boe) {
            if (!boe.CanSimplify) {
                VisitChildren(boe);
                return;
            }

            JSExpression left, right, nestedLeft;
            if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left))
                left = boe.Left;
            if (!JSReferenceExpression.TryDereference(JSIL, boe.Right, out right))
                right = boe.Right;

            var nestedBoe = right as JSBinaryOperatorExpression;
            var isAssignment = (boe.Operator == JSOperator.Assignment);
            var leftNew = left as JSNewExpression;
            var rightNew = right as JSNewExpression;
            var leftVar = left as JSVariable;

            if (
                isAssignment && (nestedBoe != null) && 
                (left.IsConstant || (leftVar != null) || left is JSDotExpressionBase) &&
                !(ParentNode is JSVariableDeclarationStatement)
            ) {
                if (!nestedBoe.CanSimplify) {
                    VisitChildren(boe);
                    return;
                }

                JSUnaryOperator prefixOperator;
                JSAssignmentOperator compoundOperator;

                if (!JSReferenceExpression.TryDereference(JSIL, nestedBoe.Left, out nestedLeft))
                    nestedLeft = nestedBoe.Left;

                var rightLiteral = nestedBoe.Right as JSIntegerLiteral;
                var areEqual = left.Equals(nestedLeft);

                if (
                    areEqual &&
                    PrefixOperators.TryGetValue(nestedBoe.Operator, out prefixOperator) &&
                    (rightLiteral != null) && (rightLiteral.Value == 1)
                ) {
                    var newUoe = new JSUnaryOperatorExpression(
                        prefixOperator, boe.Left,
                        boe.GetActualType(TypeSystem)
                    );

                    ParentNode.ReplaceChild(boe, newUoe);
                    VisitReplacement(newUoe);

                    return;
                } else if (
                    areEqual && 
                    CompoundAssignments.TryGetValue(nestedBoe.Operator, out compoundOperator)
                ) {
                    var newBoe = new JSBinaryOperatorExpression(
                        compoundOperator, boe.Left, nestedBoe.Right,
                        boe.GetActualType(TypeSystem)
                    );

                    ParentNode.ReplaceChild(boe, newBoe);
                    VisitReplacement(newBoe);

                    return;
                }
            } else if (
                isAssignment && (leftNew != null) &&
                (rightNew != null)
            ) {
                // FIXME
                /*
                var rightType = rightNew.Type as JSDotExpressionBase;
                if (
                    (rightType != null) &&
                    (rightType.Member.Identifier == "CollectionInitializer")
                ) {
                    var newInitializer = new JSInitializerApplicationExpression(
                        boe.Left, new JSArrayExpression(
                            TypeSystem.Object,
                            rightNew.Arguments.ToArray()
                        )
                    );

                    ParentNode.ReplaceChild(boe, newInitializer);
                    VisitReplacement(newInitializer);

                    return;
                }
                */
            } else if (
                isAssignment && (leftVar != null) &&
                leftVar.IsThis
            ) {
                var leftType = leftVar.GetActualType(TypeSystem);
                if (!TypeUtil.IsStruct(leftType)) {
                    ParentNode.ReplaceChild(boe, new JSUntranslatableExpression(boe));

                    return;
                } else {
                    var newInvocation = JSInvocationExpression.InvokeStatic(
                        JSIL.CopyMembers, new[] { boe.Right, leftVar }
                    );

                    ParentNode.ReplaceChild(boe, newInvocation);
                    VisitReplacement(newInvocation);

                    return;
                }
            }

            VisitChildren(boe);
        }
Example #19
0
        public void VisitNode (JSUnaryOperatorExpression uoe) {
            JSUnaryMutationOperator op;
            JSExpression target;
            TypeReference type;

            if (UnpackUnaryMutation(uoe, out op, out target, out type)) {
                var tempVar = TemporaryVariable.ForFunction(
                    Stack.Last() as JSFunctionExpression, type
                );
                var store = new JSBinaryOperatorExpression(
                    JSOperator.Assignment, tempVar, target, type
                );

                var delta = (
                    (op == JSOperator.PostIncrement) ||
                    (op == JSOperator.PreIncrement)
                )
                    ? 1
                    : -1;

                JSExpression replacement;
                if (
                    (op == JSOperator.PostIncrement) ||
                    (op == JSOperator.PostDecrement)
                ) {
                    var mutated = new JSPointerAddExpression(target, JSLiteral.New(delta), false);
                    replacement = new JSCommaExpression(store, mutated, tempVar);
                } else {
                    replacement = new JSPointerAddExpression(target, JSLiteral.New(delta), true);
                }

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

            VisitChildren(uoe);
        }
Example #20
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum) {
                var castToInt = JSInvocationExpression.InvokeMethod(
                    JS.valueOf(TypeSystem.Int32), uoe.Expression, null, true
                );

                if (LogicalOperators.Contains(uoe.Operator)) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator == JSOperator.Negation) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator is JSUnaryMutationOperator) {
                    if (
                        (uoe.Operator == JSOperator.PreIncrement) ||
                        (uoe.Operator == JSOperator.PreDecrement)
                    ) {
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PreDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                        );

                        ParentNode.ReplaceChild(uoe, assignment);
                        VisitReplacement(assignment);
                        return;

                    } else if (
                        (uoe.Operator == JSOperator.PostIncrement) ||
                        (uoe.Operator == JSOperator.PostDecrement)
                    ) {
                        // FIXME: Terrible hack oh god (also not strict mode safe)
                        var tempVariable = new JSRawOutputIdentifier(
                            (output) => output.WriteRaw("$temp"), type
                        );
                        var makeTempCopy = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, tempVariable, uoe.Expression, type
                        );
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PostDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                        );

                        var comma = new JSCommaExpression(
                            makeTempCopy,
                            assignment,
                            tempVariable
                        );

                        ParentNode.ReplaceChild(uoe, comma);
                        VisitReplacement(comma);
                        return;

                    } else {
                        throw new NotImplementedException("Unary mutation of enum not supported: " + uoe.ToString());
                    }
                }
            }

            VisitChildren(uoe);
        }
        public void VisitNode (JSUnaryOperatorExpression uoe) {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isIntegral = TypeUtil.Is32BitIntegral(type);

            if (isIntegral && (uoe.Operator is JSUnaryMutationOperator)) {
                var replacement = DecomposeUnaryMutation(
                    uoe, 
                    () => TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                    ),
                    type, TypeSystem
                );

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

            VisitChildren(uoe);
        }
Example #22
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type       = uoe.Expression.GetActualType(TypeSystem);
            var isIntegral = TypeUtil.Is32BitIntegral(type);

            if (isIntegral && (uoe.Operator is JSUnaryMutationOperator))
            {
                if (
                    (uoe.Operator == JSOperator.PreIncrement) ||
                    (uoe.Operator == JSOperator.PreDecrement)
                    )
                {
                    var assignment = MakeUnaryMutation(
                        uoe.Expression,
                        (uoe.Operator == JSOperator.PreDecrement)
                            ? JSOperator.Subtract
                            : JSOperator.Add,
                        type
                        );

                    ParentNode.ReplaceChild(uoe, assignment);
                    VisitReplacement(assignment);
                    return;
                }
                else if (
                    (uoe.Operator == JSOperator.PostIncrement) ||
                    (uoe.Operator == JSOperator.PostDecrement)
                    )
                {
                    // FIXME: Terrible hack
                    var tempVariable = TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type
                        );
                    var makeTempCopy = new JSBinaryOperatorExpression(
                        JSOperator.Assignment, tempVariable, uoe.Expression, type
                        );
                    var assignment = MakeUnaryMutation(
                        uoe.Expression,
                        (uoe.Operator == JSOperator.PostDecrement)
                            ? JSOperator.Subtract
                            : JSOperator.Add,
                        type
                        );

                    var comma = new JSCommaExpression(
                        makeTempCopy,
                        assignment,
                        tempVariable
                        );

                    ParentNode.ReplaceChild(uoe, comma);
                    VisitReplacement(comma);
                    return;
                }
                else
                {
                    throw new NotImplementedException("Unary mutation not supported: " + uoe);
                }
            }

            VisitChildren(uoe);
        }
        public static JSExpression DecomposeUnaryMutation (
            JSUnaryOperatorExpression uoe, Func<JSRawOutputIdentifier> makeTemporaryVariable, TypeReference type, TypeSystem typeSystem
        ) {
            if (
                (uoe.Operator == JSOperator.PreIncrement) ||
                (uoe.Operator == JSOperator.PreDecrement)
            ) {
                var assignment = MakeUnaryMutation(
                    uoe.Expression,
                    (uoe.Operator == JSOperator.PreDecrement)
                        ? JSOperator.Subtract
                        : JSOperator.Add,
                    type, typeSystem
                );

                return assignment;
            } else if (
                (uoe.Operator == JSOperator.PostIncrement) ||
                (uoe.Operator == JSOperator.PostDecrement)
            ) {
                // FIXME: Terrible hack
                var tempVariable = makeTemporaryVariable();
                var makeTempCopy = new JSBinaryOperatorExpression(
                    JSOperator.Assignment, tempVariable, uoe.Expression, type
                );
                var assignment = MakeUnaryMutation(
                    uoe.Expression,
                    (uoe.Operator == JSOperator.PostDecrement)
                        ? JSOperator.Subtract
                        : JSOperator.Add,
                    type, typeSystem
                );

                var comma = new JSCommaExpression(
                    makeTempCopy,
                    assignment,
                    tempVariable
                );

                return comma;
            } else {
                throw new NotImplementedException("Unary mutation not supported: " + uoe);
            }
        }
Example #24
0
        public void VisitNode(JSBinaryOperatorExpression boe)
        {
            JSExpression left, right, nestedLeft;

            if (!JSReferenceExpression.TryDereference(JSIL, boe.Left, out left))
            {
                left = boe.Left;
            }
            if (!JSReferenceExpression.TryDereference(JSIL, boe.Right, out right))
            {
                right = boe.Right;
            }

            var nestedBoe    = right as JSBinaryOperatorExpression;
            var isAssignment = (boe.Operator == JSOperator.Assignment);
            var leftNew      = left as JSNewExpression;
            var rightNew     = right as JSNewExpression;
            var leftVar      = left as JSVariable;

            if (
                isAssignment && (nestedBoe != null) &&
                (left.IsConstant || (leftVar != null) || left is JSDotExpressionBase) &&
                !(ParentNode is JSVariableDeclarationStatement)
                )
            {
                JSUnaryOperator      prefixOperator;
                JSAssignmentOperator compoundOperator;

                if (!JSReferenceExpression.TryDereference(JSIL, nestedBoe.Left, out nestedLeft))
                {
                    nestedLeft = nestedBoe.Left;
                }

                var rightLiteral = nestedBoe.Right as JSIntegerLiteral;
                var areEqual     = left.Equals(nestedLeft);

                if (
                    areEqual &&
                    PrefixOperators.TryGetValue(nestedBoe.Operator, out prefixOperator) &&
                    (rightLiteral != null) && (rightLiteral.Value == 1)
                    )
                {
                    var newUoe = new JSUnaryOperatorExpression(
                        prefixOperator, boe.Left,
                        boe.GetActualType(TypeSystem)
                        );

                    ParentNode.ReplaceChild(boe, newUoe);
                    VisitReplacement(newUoe);

                    return;
                }
                else if (
                    areEqual &&
                    CompoundAssignments.TryGetValue(nestedBoe.Operator, out compoundOperator)
                    )
                {
                    var newBoe = new JSBinaryOperatorExpression(
                        compoundOperator, boe.Left, nestedBoe.Right,
                        boe.GetActualType(TypeSystem)
                        );

                    ParentNode.ReplaceChild(boe, newBoe);
                    VisitReplacement(newBoe);

                    return;
                }
            }
            else if (
                isAssignment && (leftNew != null) &&
                (rightNew != null)
                )
            {
                var rightType = rightNew.Type as JSDotExpressionBase;
                if (
                    (rightType != null) &&
                    (rightType.Member.Identifier == "CollectionInitializer")
                    )
                {
                    var newInitializer = new JSInitializerApplicationExpression(
                        boe.Left, new JSArrayExpression(
                            TypeSystem.Object,
                            rightNew.Arguments.ToArray()
                            )
                        );

                    ParentNode.ReplaceChild(boe, newInitializer);
                    VisitReplacement(newInitializer);

                    return;
                }
            }
            else if (
                isAssignment && (leftVar != null) &&
                leftVar.IsThis
                )
            {
                var leftType = leftVar.GetActualType(TypeSystem);
                if (!TypeUtil.IsStruct(leftType))
                {
                    ParentNode.ReplaceChild(boe, new JSUntranslatableExpression(boe));

                    return;
                }
                else
                {
                    var newInvocation = JSInvocationExpression.InvokeStatic(
                        JSIL.CopyMembers, new[] { boe.Right, leftVar }
                        );

                    ParentNode.ReplaceChild(boe, newInvocation);
                    VisitReplacement(newInvocation);

                    return;
                }
            }

            VisitChildren(boe);
        }
Example #25
0
        private JSForLoop ReplaceWhileLoopAndEnumerator(JSWhileLoop wl, JSExpression backingStore, JSExpression enumerator, TypeInfo enumeratorType, string arrayMember, string lengthMember)
        {
            var loopId = _NextLoopId++;
            var arrayVariableName = String.Format("a${0:x}", loopId);
            var indexVariableName = String.Format("i${0:x}", loopId);
            var lengthVariableName = String.Format("l${0:x}", loopId);

            var currentPropertyReference = enumeratorType.Definition.Properties.First((p) => p.Name == "Current");
            var currentPropertyInfo = enumeratorType.Source.GetProperty(currentPropertyReference);

            var itemType = currentPropertyInfo.ReturnType;
            var arrayType = new ArrayType(itemType);

            var arrayVariable = new JSVariable(
                arrayVariableName, arrayType, Function.Method.Reference,
                JSDotExpression.New(backingStore, new JSStringIdentifier(arrayMember, arrayType))
            );
            var indexVariable = new JSVariable(
                indexVariableName, TypeSystem.Int32, Function.Method.Reference,
                JSLiteral.New(0)
            );
            var lengthVariable = new JSVariable(
                lengthVariableName, TypeSystem.Int32, Function.Method.Reference,
                JSDotExpression.New(backingStore, new JSStringIdentifier(lengthMember, TypeSystem.Int32))
            );

            var initializer = new JSVariableDeclarationStatement(
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, arrayVariable, arrayVariable.DefaultValue, arrayVariable.IdentifierType
                ),
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, indexVariable, indexVariable.DefaultValue, indexVariable.IdentifierType
                ),
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, lengthVariable, lengthVariable.DefaultValue, lengthVariable.IdentifierType
                )
            );

            var condition = new JSBinaryOperatorExpression(
                JSBinaryOperator.LessThan,
                indexVariable, lengthVariable, TypeSystem.Boolean
            );

            var increment = new JSUnaryOperatorExpression(
                JSUnaryOperator.PostIncrement,
                indexVariable, TypeSystem.Int32
            );

            var result = new JSForLoop(
                initializer, condition, new JSExpressionStatement(increment),
                wl.Statements.ToArray()
            );
            result.Index = wl.Index;

            new PropertyAccessReplacer(
                enumerator, new JSProperty(currentPropertyReference, currentPropertyInfo),
                new JSIndexerExpression(
                    arrayVariable, indexVariable,
                    itemType
                )
            ).Visit(result);

            return result;
        }
        private JSForLoop ReplaceWhileLoopAndEnumerator(JSWhileLoop wl, JSExpression backingStore, JSExpression enumerator, TypeInfo enumeratorType, string arrayMember, string lengthMember)
        {
            var loopId             = _NextLoopId++;
            var arrayVariableName  = String.Format("a${0:x}", loopId);
            var indexVariableName  = String.Format("i${0:x}", loopId);
            var lengthVariableName = String.Format("l${0:x}", loopId);

            var currentPropertyReference = enumeratorType.Definition.Properties.First((p) => p.Name == "Current");
            var currentPropertyInfo      = enumeratorType.Source.GetProperty(currentPropertyReference);

            var itemType  = currentPropertyInfo.ReturnType;
            var arrayType = new ArrayType(itemType);

            var arrayVariable = new JSVariable(
                arrayVariableName, arrayType, Function.Method.Reference,
                JSDotExpression.New(backingStore, new JSStringIdentifier(arrayMember, arrayType))
                );
            var indexVariable = new JSVariable(
                indexVariableName, TypeSystem.Int32, Function.Method.Reference,
                JSLiteral.New(0)
                );
            var lengthVariable = new JSVariable(
                lengthVariableName, TypeSystem.Int32, Function.Method.Reference,
                JSDotExpression.New(backingStore, new JSStringIdentifier(lengthMember, TypeSystem.Int32))
                );

            var initializer = new JSVariableDeclarationStatement(
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, arrayVariable, arrayVariable.DefaultValue, arrayVariable.IdentifierType
                    ),
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, indexVariable, indexVariable.DefaultValue, indexVariable.IdentifierType
                    ),
                new JSBinaryOperatorExpression(
                    JSOperator.Assignment, lengthVariable, lengthVariable.DefaultValue, lengthVariable.IdentifierType
                    )
                );

            var condition = new JSBinaryOperatorExpression(
                JSOperator.LessThan,
                indexVariable, lengthVariable, TypeSystem.Boolean
                );

            var increment = new JSUnaryOperatorExpression(
                JSOperator.PostIncrement,
                indexVariable, TypeSystem.Int32
                );

            var result = new JSForLoop(
                initializer, condition, new JSExpressionStatement(increment),
                wl.Statements.ToArray()
                );

            result.Index = wl.Index;

            new PropertyAccessReplacer(
                enumerator, new JSProperty(currentPropertyReference, currentPropertyInfo),
                new JSIndexerExpression(
                    arrayVariable, indexVariable,
                    itemType
                    )
                ).Visit(result);

            return(result);
        }
        public void VisitNode (JSUnaryOperatorExpression uoe) {
            JSExpression expr;

            if (!JSReferenceExpression.TryDereference(JSIL, uoe.Expression, out expr))
                expr = uoe.Expression;

            var eVar = expr as JSVariable;
            var eChangeType = expr as JSChangeTypeExpression;

            if (eChangeType != null)
                eVar = eChangeType.Expression as JSVariable;

            var type = uoe.Expression.GetActualType(TypeSystem);
            if (
                (eVar != null) && 
                (eVar.Identifier == Variable.Identifier) &&
                (uoe.Operator is JSUnaryMutationOperator)
            ) {
                var newValue = DecomposeMutationOperators.DecomposeUnaryMutation(
                    uoe, () => TemporaryVariable.ForFunction(
                        Stack.Last() as JSFunctionExpression, type, FunctionSource
                    ), type, TypeSystem
                );
                var replacement = new JSWriteThroughReferenceExpression(
                    Variable, newValue
                );
                ParentNode.ReplaceChild(uoe, replacement);
                VisitReplacement(replacement);
            } else {
                VisitChildren(uoe);
            }
        }
Example #28
0
        public static bool ExtractOffsetFromPointerExpression (JSExpression pointer, TypeSystem typeSystem, out JSExpression newPointer, out JSExpression offset) {
            pointer = JSPointerExpressionUtil.UnwrapExpression(pointer);

            offset = null;
            newPointer = pointer;

            var boe = pointer as JSBinaryOperatorExpression;
            if (boe == null)
                return false;

            if (boe.Right.IsNull)
                return false;

            var right = JSPointerExpressionUtil.UnwrapExpression(boe.Right);

            var rightType = right.GetActualType(typeSystem);
            var resultType = boe.GetActualType(typeSystem);

            if (!resultType.IsPointer)
                return false;

            if (
                !TypeUtil.IsIntegral(rightType) &&
                // Adding pointers together shouldn't be valid but ILSpy generates it. Pfft.
                !TypeUtil.IsPointer(rightType)
            )
                return false;

            if (boe.Operator == JSOperator.Subtract) {
                newPointer = boe.Left;
                offset = new JSUnaryOperatorExpression(JSOperator.Negation, right, rightType);
                return true;
            } else if (boe.Operator == JSOperator.Add) {
                newPointer = boe.Left;
                offset = right;
                return true;
            } else {
                return false;
            }
        }
Example #29
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var type   = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum)
            {
                var castToInt = JSInvocationExpression.InvokeMethod(
                    JS.valueOf(TypeSystem.Int32), uoe.Expression, null, true
                    );

                if (LogicalOperators.Contains(uoe.Operator))
                {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                }
                else if (uoe.Operator == JSOperator.Negation)
                {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                }
                else if (uoe.Operator is JSUnaryMutationOperator)
                {
                    if (
                        (uoe.Operator == JSOperator.PreIncrement) ||
                        (uoe.Operator == JSOperator.PreDecrement)
                        )
                    {
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PreDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                            );

                        ParentNode.ReplaceChild(uoe, assignment);
                        VisitReplacement(assignment);
                        return;
                    }
                    else if (
                        (uoe.Operator == JSOperator.PostIncrement) ||
                        (uoe.Operator == JSOperator.PostDecrement)
                        )
                    {
                        // FIXME: Terrible hack
                        var tempVariable = TemporaryVariable.ForFunction(
                            Stack.Last() as JSFunctionExpression, type
                            );
                        var makeTempCopy = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, tempVariable, uoe.Expression, type
                            );
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PostDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                            );

                        var comma = new JSCommaExpression(
                            makeTempCopy,
                            assignment,
                            tempVariable
                            );

                        ParentNode.ReplaceChild(uoe, comma);
                        VisitReplacement(comma);
                        return;
                    }
                    else
                    {
                        throw new NotImplementedException("Unary mutation of enum not supported: " + uoe.ToString());
                    }
                }
            }

            VisitChildren(uoe);
        }
Example #30
0
        public void VisitNode(JSUnaryOperatorExpression uoe)
        {
            var resultType = uoe.GetActualType(TypeSystem);
            var typeToken  = WasmUtil.PickTypeKeyword(resultType);

            if (typeToken == null)
            {
                Console.WriteLine("Unhandled unary operator type {0}", resultType);
                return;
            }

            if (uoe.Operator == JSOperator.LogicalNot)
            {
                Formatter.WriteRaw("({0}.xor ", typeToken);
                Visit(uoe.Expression);
                Formatter.WriteRaw(" ({0}.const 1))", typeToken);
                return;
            }
            else if (uoe.Operator == JSOperator.Negation)
            {
                Formatter.WriteRaw("({0}.sub ({0}.const 0) ", typeToken);
                Visit(uoe.Expression);
                Formatter.WriteRaw(")", typeToken);
                return;
            }

            string keyword;

            if (!OperatorTable.TryGetValue(uoe.Operator, out keyword))
            {
                Console.WriteLine("Unimplemented operator {0}", uoe.Operator);
                return;
            }

            var operandType = uoe.Expression.GetActualType(TypeSystem);
            var sign        = TypeUtil.IsSigned(operandType);

            var signSuffix = "";

            if (
                (sign.HasValue && TypeUtil.IsIntegral(operandType)) ||
                // HACK
                (operandType.FullName == "System.Char")
                )
            {
                signSuffix = sign.GetValueOrDefault(true)
                    ? "_s"
                    : "_u";
            }

            var actualKeyword = string.Format(
                typeToken + "." + keyword,
                signSuffix
                );

            Formatter.WriteSExpr(
                actualKeyword,
                (_) => EmitArgumentList(_, new[] { uoe.Expression }, true),
                true, false
                );
        }
Example #31
0
        public void VisitNode (JSUnaryOperatorExpression uoe) {
            var type = uoe.Expression.GetActualType(TypeSystem);
            var isEnum = IsEnumOrNullableEnum(type);

            if (isEnum) {
                var castToInt = JSInvocationExpression.InvokeMethod(
                    JS.valueOf(TypeSystem.Int32), uoe.Expression, null, true
                );

                if (LogicalOperators.Contains(uoe.Operator)) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator == JSOperator.Negation) {
                    uoe.ReplaceChild(uoe.Expression, castToInt);
                } else if (uoe.Operator is JSUnaryMutationOperator) {
                    if (
                        (uoe.Operator == JSOperator.PreIncrement) || 
                        (uoe.Operator == JSOperator.PreDecrement)
                    ) {
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PreDecrement) 
                                ? JSOperator.Subtract 
                                : JSOperator.Add,
                            type
                        );

                        ParentNode.ReplaceChild(uoe, assignment);
                        VisitReplacement(assignment);
                        return;

                    } else if (
                        (uoe.Operator == JSOperator.PostIncrement) || 
                        (uoe.Operator == JSOperator.PostDecrement)
                    ) {
                        // FIXME: Terrible hack
                        var tempVariable = TemporaryVariable.ForFunction(
                            Stack.Last() as JSFunctionExpression, type, FunctionSource
                        );
                        var makeTempCopy = new JSBinaryOperatorExpression(
                            JSOperator.Assignment, tempVariable, uoe.Expression, type
                        );
                        var assignment = MakeUnaryMutation(
                            uoe.Expression,
                            (uoe.Operator == JSOperator.PostDecrement)
                                ? JSOperator.Subtract
                                : JSOperator.Add,
                            type
                        );

                        var comma = new JSCommaExpression(
                            makeTempCopy,
                            assignment,
                            tempVariable
                        );

                        ParentNode.ReplaceChild(uoe, comma);
                        VisitReplacement(comma);
                        return;

                    } else {
                        throw new NotImplementedException("Unary mutation of enum not supported: " + uoe);
                    }
                }
            }

            VisitChildren(uoe);
        }