Package com.strobel.decompiler.ast

Examples of com.strobel.decompiler.ast.Label


    }

    @SuppressWarnings("ConstantConditions")
    private AstNode transformByteCode(final com.strobel.decompiler.ast.Expression byteCode, final boolean isTopLevel) {
        final Object operand = byteCode.getOperand();
        final Label label = operand instanceof Label ? (Label) operand : null;
        final AstType operandType = operand instanceof TypeReference ? _astBuilder.convertType((TypeReference) operand) : AstType.NULL;
        final Variable variableOperand = operand instanceof Variable ? (Variable) operand : null;
        final FieldReference fieldOperand = operand instanceof FieldReference ? (FieldReference) operand : null;

        final List<Expression> arguments = new ArrayList<>();

        for (final com.strobel.decompiler.ast.Expression e : byteCode.getArguments()) {
            arguments.add((Expression) transformExpression(e, false));
        }

        final Expression arg1 = arguments.size() >= 1 ? arguments.get(0) : null;
        final Expression arg2 = arguments.size() >= 2 ? arguments.get(1) : null;
        final Expression arg3 = arguments.size() >= 3 ? arguments.get(2) : null;

        switch (byteCode.getCode()) {
            case Nop:
                return null;

            case AConstNull:
                return new NullReferenceExpression();

            case LdC: {
                if (operand instanceof TypeReference) {
                    operandType.getChildrenByRole(Roles.TYPE_ARGUMENT).clear();
                    return new ClassOfExpression(operandType);
                }

                final TypeReference type = byteCode.getInferredType() != null ? byteCode.getInferredType()
                                                                              : byteCode.getExpectedType();

                if (type != null) {
                    return new PrimitiveExpression(JavaPrimitiveCast.cast(type.getSimpleType(), operand));
                }

                return new PrimitiveExpression(operand);
            }

            case Pop:
            case Pop2:
            case Dup:
            case DupX1:
            case DupX2:
            case Dup2:
            case Dup2X1:
            case Dup2X2:
                return arg1;

            case Swap:
                return arg1;

            case I2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case I2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case I2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case L2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case L2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case L2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case F2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case F2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case F2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case D2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case D2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case D2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case I2B:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Byte), arg1);
            case I2C:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Character), arg1);
            case I2S:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Short), arg1);

            case Goto:
                return new GotoStatement(((Label) operand).getName());

            case GetStatic: {
                final ConvertTypeOptions options = new ConvertTypeOptions();
                options.setIncludeTypeParameterDefinitions(false);
                final MemberReferenceExpression fieldReference = _astBuilder.convertType(fieldOperand.getDeclaringType(), options)
                                                                            .member(fieldOperand.getName());
                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return fieldReference;
            }

            case PutStatic: {
                final ConvertTypeOptions options = new ConvertTypeOptions();
                options.setIncludeTypeParameterDefinitions(false);

                final FieldDefinition resolvedField = fieldOperand.resolve();
                final Expression fieldReference;

                if (resolvedField != null &&
                    resolvedField.isFinal() &&
                    Comparer.equals(fieldOperand.getDeclaringType(), _context.getCurrentType())) {

                    //
                    // Fields marked 'static final' cannot be initialized using a fully qualified name.
                    //

                    fieldReference = new IdentifierExpression(fieldOperand.getName());
                }
                else {
                    fieldReference = _astBuilder.convertType(fieldOperand.getDeclaringType(), options)
                                                .member(fieldOperand.getName());
                }

                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return new AssignmentExpression(fieldReference, arg1);
            }

            case GetField: {
                final MemberReferenceExpression fieldReference = arg1.member(fieldOperand.getName());
                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return fieldReference;
            }

            case PutField: {
                final MemberReferenceExpression fieldReference = arg1.member(fieldOperand.getName());
                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return new AssignmentExpression(fieldReference, arg2);
            }

            case InvokeVirtual:
                return transformCall(true, byteCode, arguments);
            case InvokeSpecial:
            case InvokeStatic:
                return transformCall(false, byteCode, arguments);
            case InvokeInterface:
                return transformCall(false, byteCode, arguments);

            case InvokeDynamic: {
                final DynamicCallSite callSite = (DynamicCallSite) operand;
                final MethodReference bootstrapMethod = callSite.getBootstrapMethod();

                if ("java/lang/invoke/LambdaMetafactory".equals(bootstrapMethod.getDeclaringType().getInternalName()) &&
                    "metaFactory".equals(bootstrapMethod.getName()) &&
                    callSite.getBootstrapArguments().size() == 3 &&
                    callSite.getBootstrapArguments().get(1) instanceof MethodHandle) {

                    final MethodHandle targetMethodHandle = (MethodHandle) callSite.getBootstrapArguments().get(1);
                    final MethodReference targetMethod = targetMethodHandle.getMethod();
                    final TypeReference declaringType = targetMethod.getDeclaringType();
                    final String methodName = targetMethod.isConstructor() ? "new" : targetMethod.getName();

                    final boolean hasInstanceArgument;

                    switch (targetMethodHandle.getHandleType()) {
                        case GetField:
                        case PutField:
                        case InvokeVirtual:
                        case InvokeInterface:
                        case InvokeSpecial:
                            assert arg1 != null;
                            hasInstanceArgument = true;
                            break;

                        default:
                            hasInstanceArgument = false;
                            break;
                    }

                    final MethodGroupExpression methodGroup = new MethodGroupExpression(
                        hasInstanceArgument ? arg1
                                            : new TypeReferenceExpression(_astBuilder.convertType(declaringType)),
                        methodName
                    );

                    methodGroup.getClosureArguments().addAll(
                        hasInstanceArgument ? arguments.subList(1, arguments.size()) : arguments
                    );

                    methodGroup.putUserData(Keys.DYNAMIC_CALL_SITE, callSite);
                    methodGroup.putUserData(Keys.MEMBER_REFERENCE, targetMethod);

                    return methodGroup;
                }

                break;
            }

            case ArrayLength:
                return arg1.member("length");

            case AThrow:
                return new ThrowStatement(arg1);

            case CheckCast:
                return new CastExpression(operandType, arg1);

            case InstanceOf:
                return new InstanceOfExpression(arg1, operandType);

            case MonitorEnter:
            case MonitorExit:
                break;

            case MultiANewArray: {
                final ArrayCreationExpression arrayCreation = new ArrayCreationExpression();

                int rank = 0;
                AstType elementType = operandType;

                while (elementType instanceof ComposedType) {
                    rank += ((ComposedType) elementType).getArraySpecifiers().size();
                    elementType = ((ComposedType) elementType).getBaseType();
                }

                arrayCreation.setType(elementType.clone());

                for (int i = 0; i < arguments.size(); i++) {
                    arrayCreation.getDimensions().add(arguments.get(i));
                    --rank;
                }

                for (int i = 0; i < rank; i++) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                }

                return arrayCreation;
            }

            case Breakpoint:
                return null;

            case Load: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }
                if (variableOperand.isParameter() && variableOperand.getOriginalParameter().getPosition() < 0) {
                    final ThisReferenceExpression self = new ThisReferenceExpression();
                    self.putUserData(Keys.TYPE_REFERENCE, _context.getCurrentType());
                    return self;
                }
                final IdentifierExpression name = new IdentifierExpression(variableOperand.getName());
                name.putUserData(Keys.VARIABLE, variableOperand);
                return name;
            }

            case Store: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }
                final IdentifierExpression name = new IdentifierExpression(variableOperand.getName());
                name.putUserData(Keys.VARIABLE, variableOperand);
                return new AssignmentExpression(name, arg1);
            }

            case LoadElement: {
                return new IndexerExpression(arg1, arg2);
            }
            case StoreElement: {
                return new AssignmentExpression(
                    new IndexerExpression(arg1, arg2),
                    arg3
                );
            }

            case Add:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.ADD, arg2);
            case Sub:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SUBTRACT, arg2);
            case Mul:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.MULTIPLY, arg2);
            case Div:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.DIVIDE, arg2);
            case Rem:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.MODULUS, arg2);
            case Neg:
                return new UnaryOperatorExpression(UnaryOperatorType.MINUS, arg1);
            case Shl:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SHIFT_LEFT, arg2);
            case Shr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SHIFT_RIGHT, arg2);
            case UShr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.UNSIGNED_SHIFT_RIGHT, arg2);
            case And:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.BITWISE_AND, arg2);
            case Or:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.BITWISE_OR, arg2);
            case Not:
                return new UnaryOperatorExpression(UnaryOperatorType.NOT, arg1);
            case Xor:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.EXCLUSIVE_OR, arg2);

            case Inc: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }

                final IdentifierExpression name = new IdentifierExpression(variableOperand.getName());

                name.getIdentifierToken().putUserData(Keys.VARIABLE, variableOperand);
                name.putUserData(Keys.VARIABLE, variableOperand);

                final PrimitiveExpression deltaExpression = (PrimitiveExpression) arg1;
                final int delta = (Integer) deltaExpression.getValue();

                switch (delta) {
                    case -1:
                        return new UnaryOperatorExpression(UnaryOperatorType.DECREMENT, name);
                    case 1:
                        return new UnaryOperatorExpression(UnaryOperatorType.INCREMENT, name);
                    default:
                        return new AssignmentExpression(name, AssignmentOperatorType.ADD, arg1);
                }
            }

            case CmpEq:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.EQUALITY, arg2);
            case CmpNe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.INEQUALITY, arg2);
            case CmpLt:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LESS_THAN, arg2);
            case CmpGe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.GREATER_THAN_OR_EQUAL, arg2);
            case CmpGt:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.GREATER_THAN, arg2);
            case CmpLe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LESS_THAN_OR_EQUAL, arg2);

            case Return:
                return new ReturnStatement(arg1);

            case NewArray: {
                final ArrayCreationExpression arrayCreation = new ArrayCreationExpression();

                TypeReference elementType = operandType.getUserData(Keys.TYPE_REFERENCE);

                while (elementType.isArray()) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                    elementType = elementType.getElementType();
                }

                arrayCreation.setType(_astBuilder.convertType(elementType));
                arrayCreation.getDimensions().add(arg1);

                return arrayCreation;
            }

            case LogicalNot:
                return new UnaryOperatorExpression(UnaryOperatorType.NOT, arg1);

            case LogicalAnd:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LOGICAL_AND, arg2);
            case LogicalOr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LOGICAL_OR, arg2);

            case InitObject:
                return transformCall(false, byteCode, arguments);

            case InitArray: {
                final ArrayCreationExpression arrayCreation = new ArrayCreationExpression();

                TypeReference elementType = operandType.getUserData(Keys.TYPE_REFERENCE);

                while (elementType.isArray()) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                    elementType = elementType.getElementType();
                }

                arrayCreation.setType(_astBuilder.convertType(elementType));
                arrayCreation.setInitializer(new ArrayInitializerExpression(arguments));

                return arrayCreation;
            }

            case Wrap:
                return null;

            case TernaryOp:
                return new ConditionalExpression(arg1, arg2, arg3);

            case LoopOrSwitchBreak:
                return label != null ? new GotoStatement(label.getName()) : new BreakStatement();

            case LoopContinue:
                return label != null ? new ContinueStatement(label.getName()) : new ContinueStatement();

            case CompoundAssignment:
                throw ContractUtils.unreachable();

            case PreIncrement: {
View Full Code Here


    }

    @SuppressWarnings("ConstantConditions")
    private AstNode transformByteCode(final com.strobel.decompiler.ast.Expression byteCode, final boolean isTopLevel) {
        final Object operand = byteCode.getOperand();
        final Label label = operand instanceof Label ? (Label) operand : null;
        final AstType operandType = operand instanceof TypeReference ? _astBuilder.convertType((TypeReference) operand) : AstType.NULL;
        final Variable variableOperand = operand instanceof Variable ? (Variable) operand : null;
        final FieldReference fieldOperand = operand instanceof FieldReference ? (FieldReference) operand : null;

        final List<Expression> arguments = new ArrayList<>();

        for (final com.strobel.decompiler.ast.Expression e : byteCode.getArguments()) {
            arguments.add((Expression) transformExpression(e, false));
        }

        final Expression arg1 = arguments.size() >= 1 ? arguments.get(0) : null;
        final Expression arg2 = arguments.size() >= 2 ? arguments.get(1) : null;
        final Expression arg3 = arguments.size() >= 3 ? arguments.get(2) : null;

        switch (byteCode.getCode()) {
            case Nop:
                return null;

            case AConstNull:
                return new NullReferenceExpression( byteCode.getOffset());

            case LdC: {
                if (operand instanceof TypeReference) {
                    operandType.getChildrenByRole(Roles.TYPE_ARGUMENT).clear();
                    return new ClassOfExpression(byteCode.getOffset(), operandType);
                }

                final TypeReference type = byteCode.getInferredType() != null ? byteCode.getInferredType()
                                                                              : byteCode.getExpectedType();

                if (type != null) {
                    switch (type.getSimpleType()) {
                        case Byte:
                        case Short:
                            return new PrimitiveExpression(
                                byteCode.getOffset(),
                                JavaPrimitiveCast.cast(JvmType.Integer, operand)
                            );

                        default:
                            return new PrimitiveExpression(
                                byteCode.getOffset(),
                                JavaPrimitiveCast.cast(type.getSimpleType(), operand)
                            );
                    }
                }

                return new PrimitiveExpression(byteCode.getOffset(), operand);
            }

            case Pop:
            case Pop2:
            case Dup:
            case DupX1:
            case DupX2:
            case Dup2:
            case Dup2X1:
            case Dup2X2:
                return arg1;

            case Swap:
                return arg1;

            case I2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case I2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case I2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case L2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case L2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case L2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case F2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case F2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case F2D:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Double), arg1);
            case D2I:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Integer), arg1);
            case D2L:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Long), arg1);
            case D2F:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Float), arg1);
            case I2B:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Byte), arg1);
            case I2C:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Character), arg1);
            case I2S:
                return new CastExpression(_astBuilder.convertType(BuiltinTypes.Short), arg1);

            case Goto:
                return new GotoStatement(byteCode.getOffset(), ((Label) operand).getName());

            case GetStatic: {
                final ConvertTypeOptions options = new ConvertTypeOptions();
                options.setIncludeTypeParameterDefinitions(false);
                final MemberReferenceExpression fieldReference = _astBuilder.convertType(fieldOperand.getDeclaringType(), options)
                                                                            .member(fieldOperand.getName());
                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return fieldReference;
            }

            case PutStatic: {
                final ConvertTypeOptions options = new ConvertTypeOptions();
                options.setIncludeTypeParameterDefinitions(false);

                final FieldDefinition resolvedField = fieldOperand.resolve();
                final Expression fieldReference;

                if (resolvedField != null &&
                    resolvedField.isFinal() &&
                    StringUtilities.equals(resolvedField.getDeclaringType().getInternalName(), _context.getCurrentType().getInternalName())) {

                    //
                    // Fields marked 'static final' cannot be initialized using a fully qualified name.
                    //

                    fieldReference = new IdentifierExpression( byteCode.getOffset(), fieldOperand.getName());
                }
                else {
                    fieldReference = _astBuilder.convertType(fieldOperand.getDeclaringType(), options)
                                                .member(fieldOperand.getName());
                }

                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return new AssignmentExpression(fieldReference, arg1);
            }

            case GetField: {
                final MemberReferenceExpression fieldReference;

                if (arg1 instanceof ThisReferenceExpression &&
                    MetadataHelper.isSubType(_context.getCurrentType(), fieldOperand.getDeclaringType()) &&
                    !StringUtilities.equals(fieldOperand.getDeclaringType().getInternalName(), _context.getCurrentType().getInternalName())) {

                    fieldReference = new SuperReferenceExpression(arg1.getOffset()).member(fieldOperand.getName());
                }
                else {
                    fieldReference = arg1.member(fieldOperand.getName());
                }

                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return fieldReference;
            }

            case PutField: {
                final MemberReferenceExpression fieldReference;

                if (arg1 instanceof ThisReferenceExpression &&
                    MetadataHelper.isSubType(_context.getCurrentType(), fieldOperand.getDeclaringType()) &&
                    !StringUtilities.equals(fieldOperand.getDeclaringType().getInternalName(), _context.getCurrentType().getInternalName())) {

                    fieldReference = new SuperReferenceExpression(arg1.getOffset()).member(fieldOperand.getName());
                }
                else {
                    fieldReference = arg1.member(fieldOperand.getName());
                }

                fieldReference.putUserData(Keys.MEMBER_REFERENCE, fieldOperand);
                return new AssignmentExpression(fieldReference, arg2);
            }

            case InvokeVirtual:
                return transformCall(true, byteCode, arguments);
            case InvokeSpecial:
            case InvokeStatic:
                return transformCall(false, byteCode, arguments);
            case InvokeInterface:
                return transformCall(false, byteCode, arguments);

            case InvokeDynamic: {
                final DynamicCallSite callSite = (DynamicCallSite) operand;
                final MethodReference bootstrapMethod = callSite.getBootstrapMethod();

                if ("java/lang/invoke/LambdaMetafactory".equals(bootstrapMethod.getDeclaringType().getInternalName()) &&
                    (StringUtilities.equals("metafactory", bootstrapMethod.getName(), StringComparison.OrdinalIgnoreCase) ||
                     StringUtilities.equals("altMetafactory", bootstrapMethod.getName(), StringComparison.OrdinalIgnoreCase)) &&
                    callSite.getBootstrapArguments().size() >= 3 &&
                    callSite.getBootstrapArguments().get(1) instanceof MethodHandle) {

                    final MethodHandle targetMethodHandle = (MethodHandle) callSite.getBootstrapArguments().get(1);
                    final MethodReference targetMethod = targetMethodHandle.getMethod();
                    final TypeReference declaringType = targetMethod.getDeclaringType();
                    final String methodName = targetMethod.isConstructor() ? "new" : targetMethod.getName();

                    final boolean hasInstanceArgument;

                    switch (targetMethodHandle.getHandleType()) {
                        case GetField:
                        case PutField:
                        case InvokeVirtual:
                        case InvokeInterface:
                        case InvokeSpecial:
//                            assert arg1 != null;
                            hasInstanceArgument = arg1 != null;
                            break;

                        default:
                            hasInstanceArgument = false;
                            break;
                    }

                    final MethodGroupExpression methodGroup = new MethodGroupExpression(
                        byteCode.getOffset(),
                        hasInstanceArgument ? arg1
                                            : new TypeReferenceExpression( byteCode.getOffset(), _astBuilder.convertType(declaringType)),
                        methodName
                    );

                    methodGroup.getClosureArguments().addAll(
                        hasInstanceArgument ? arguments.subList(1, arguments.size()) : arguments
                    );

                    methodGroup.putUserData(Keys.DYNAMIC_CALL_SITE, callSite);
                    methodGroup.putUserData(Keys.MEMBER_REFERENCE, targetMethod);

                    if (byteCode.getInferredType() != null) {
                        methodGroup.putUserData(Keys.TYPE_REFERENCE, byteCode.getInferredType());
                    }

                    return methodGroup;
                }

                break;
            }

            case Bind: {
                final Lambda lambda = (Lambda) byteCode.getOperand();
                final LambdaExpression lambdaExpression = new LambdaExpression(byteCode.getOffset());
                final AstNodeCollection<ParameterDeclaration> declarations = lambdaExpression.getParameters();

                for (final Variable v : lambda.getParameters()) {
                    final ParameterDefinition p = v.getOriginalParameter();
                    final ParameterDeclaration d = new ParameterDeclaration(v.getName(), null);

                    d.putUserData(Keys.PARAMETER_DEFINITION, p);
                    d.putUserData(Keys.VARIABLE, v);

                    for (final CustomAnnotation annotation : p.getAnnotations()) {
                        d.getAnnotations().add(_astBuilder.createAnnotation(annotation));
                    }

                    declarations.add(d);

                    if (p.isFinal()) {
                        EntityDeclaration.addModifier(d, Modifier.FINAL);
                    }
                }

                final BlockStatement body = transformBlock(lambda.getBody());
                final Match m = LAMBDA_BODY_PATTERN.match(body);

                if (m.success()) {
                    final AstNode bodyNode = first(m.<AstNode>get("body"));
                    bodyNode.remove();
                    lambdaExpression.setBody(bodyNode);

                    if (EMPTY_LAMBDA_BODY_PATTERN.matches(bodyNode)) {
                        bodyNode.getChildrenByRole(BlockStatement.STATEMENT_ROLE).clear();
                    }
                }
                else {
                    lambdaExpression.setBody(body);
                }

                lambdaExpression.putUserData(Keys.TYPE_REFERENCE, byteCode.getInferredType());

                final DynamicCallSite callSite = lambda.getCallSite();

                if (callSite != null) {
                    lambdaExpression.putUserData(Keys.DYNAMIC_CALL_SITE, callSite);
                }

                return lambdaExpression;
            }

            case ArrayLength:
                final MemberReferenceExpression length = arg1.member("length");
                final TypeReference arrayType = single(byteCode.getArguments()).getInferredType();

                if (arrayType != null) {
                    length.putUserData(
                        Keys.MEMBER_REFERENCE,
                        _parser.parseField(arrayType, "length", "I")
                    );
                }

                return length;

            case AThrow:
                return new ThrowStatement(arg1);

            case CheckCast:
                return new CastExpression(operandType, arg1);

            case InstanceOf:
                return new InstanceOfExpression( byteCode.getOffset(), arg1, operandType);

            case MonitorEnter:
            case MonitorExit:
                break;

            case MultiANewArray: {
                final ArrayCreationExpression arrayCreation =
                        new ArrayCreationExpression( byteCode.getOffset());

                int rank = 0;
                AstType elementType = operandType;

                while (elementType instanceof ComposedType) {
                    rank += ((ComposedType) elementType).getArraySpecifiers().size();
                    elementType = ((ComposedType) elementType).getBaseType();
                }

                arrayCreation.setType(elementType.clone());

                for (int i = 0; i < arguments.size(); i++) {
                    arrayCreation.getDimensions().add(arguments.get(i));
                    --rank;
                }

                for (int i = 0; i < rank; i++) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                }

                return arrayCreation;
            }

            case Breakpoint:
                return null;

            case Load: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }
                if (variableOperand.isParameter() && variableOperand.getOriginalParameter().getPosition() < 0) {
                    final ThisReferenceExpression self = new ThisReferenceExpression( byteCode.getOffset());
                    self.putUserData(Keys.TYPE_REFERENCE, _context.getCurrentType());
                    return self;
                }
                final IdentifierExpression name = new IdentifierExpression( byteCode.getOffset(),
                        variableOperand.getName());
                name.putUserData(Keys.VARIABLE, variableOperand);
                return name;
            }

            case Store: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }
                final IdentifierExpression name = new IdentifierExpression( byteCode.getOffset(),
                        variableOperand.getName());
                name.putUserData(Keys.VARIABLE, variableOperand);
                return new AssignmentExpression(name, arg1);
            }

            case LoadElement: {
                return new IndexerExpression( byteCode.getOffset(), arg1, arg2);
            }
            case StoreElement: {
                return new AssignmentExpression(
                    new IndexerExpression( byteCode.getOffset(), arg1, arg2),
                    arg3
                );
            }

            case Add:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.ADD, arg2);
            case Sub:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SUBTRACT, arg2);
            case Mul:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.MULTIPLY, arg2);
            case Div:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.DIVIDE, arg2);
            case Rem:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.MODULUS, arg2);
            case Neg:
                return new UnaryOperatorExpression(UnaryOperatorType.MINUS, arg1);
            case Shl:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SHIFT_LEFT, arg2);
            case Shr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.SHIFT_RIGHT, arg2);
            case UShr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.UNSIGNED_SHIFT_RIGHT, arg2);
            case And:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.BITWISE_AND, arg2);
            case Or:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.BITWISE_OR, arg2);
            case Not:
                return new UnaryOperatorExpression(UnaryOperatorType.NOT, arg1);
            case Xor:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.EXCLUSIVE_OR, arg2);

            case Inc: {
                if (!variableOperand.isParameter()) {
                    _localVariablesToDefine.add(variableOperand);
                }

                final IdentifierExpression name = new IdentifierExpression( byteCode.getOffset(),
                        variableOperand.getName());

                name.getIdentifierToken().putUserData(Keys.VARIABLE, variableOperand);
                name.putUserData(Keys.VARIABLE, variableOperand);

                final PrimitiveExpression deltaExpression = (PrimitiveExpression) arg1;
                final int delta = (int) JavaPrimitiveCast.cast(JvmType.Integer, deltaExpression.getValue());

                switch (delta) {
                    case -1:
                        return new UnaryOperatorExpression(UnaryOperatorType.DECREMENT, name);
                    case 1:
                        return new UnaryOperatorExpression(UnaryOperatorType.INCREMENT, name);
                    default:
                        return new AssignmentExpression(name, AssignmentOperatorType.ADD, arg1);
                }
            }

            case CmpEq:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.EQUALITY, arg2);
            case CmpNe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.INEQUALITY, arg2);
            case CmpLt:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LESS_THAN, arg2);
            case CmpGe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.GREATER_THAN_OR_EQUAL, arg2);
            case CmpGt:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.GREATER_THAN, arg2);
            case CmpLe:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LESS_THAN_OR_EQUAL, arg2);

            case Return:
                return new ReturnStatement(byteCode.getOffset(), arg1);

            case NewArray: {
                final ArrayCreationExpression arrayCreation =
                        new ArrayCreationExpression( byteCode.getOffset());

                TypeReference elementType = operandType.getUserData(Keys.TYPE_REFERENCE);

                while (elementType.isArray()) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                    elementType = elementType.getElementType();
                }

                arrayCreation.setType(_astBuilder.convertType(elementType));
                arrayCreation.getDimensions().add(arg1);

                return arrayCreation;
            }

            case LogicalNot:
                return new UnaryOperatorExpression(UnaryOperatorType.NOT, arg1);

            case LogicalAnd:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LOGICAL_AND, arg2);
            case LogicalOr:
                return new BinaryOperatorExpression(arg1, BinaryOperatorType.LOGICAL_OR, arg2);

            case InitObject:
                return transformCall(false, byteCode, arguments);

            case InitArray: {
                final ArrayCreationExpression arrayCreation =
                        new ArrayCreationExpression( byteCode.getOffset());

                TypeReference elementType = operandType.getUserData(Keys.TYPE_REFERENCE);

                while (elementType.isArray()) {
                    arrayCreation.getAdditionalArraySpecifiers().add(new ArraySpecifier());
                    elementType = elementType.getElementType();
                }

                arrayCreation.setType(_astBuilder.convertType(elementType));
                arrayCreation.setInitializer(new ArrayInitializerExpression(arguments));

                return arrayCreation;
            }

            case Wrap:
                return null;

            case TernaryOp:
                return new ConditionalExpression(arg1, arg2, arg3);

            case LoopOrSwitchBreak:
                return label != null ? new GotoStatement(byteCode.getOffset(), label.getName()) : new BreakStatement(byteCode.getOffset());

            case LoopContinue:
                return label != null ? new ContinueStatement(byteCode.getOffset(), label.getName()) : new ContinueStatement( byteCode.getOffset());

            case CompoundAssignment:
                throw ContractUtils.unreachable();

            case PreIncrement: {
View Full Code Here

TOP

Related Classes of com.strobel.decompiler.ast.Label

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.