diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-11-15 13:56:34 +0000 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-11-15 13:56:34 +0000 |
| commit | f4019f5ed78b0d9c0eb7c7a1b4d97e5c83003ff1 (patch) | |
| tree | 0d1993d8d965995ecfd26a21268c535630f3033a /src/main/java/org | |
| parent | 63956680fa5f6e61210e090036c797d94e4a340c (diff) | |
Split out statement and expression reading
Diffstat (limited to 'src/main/java/org')
4 files changed, 399 insertions, 364 deletions
diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java new file mode 100644 index 0000000..f9ba55e --- /dev/null +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaExpressionReader.java @@ -0,0 +1,279 @@ +package org.zwobble.couscous.frontends.java; + +import org.eclipse.jdt.core.dom.*; +import org.zwobble.couscous.ast.*; +import org.zwobble.couscous.values.BooleanValue; +import org.zwobble.couscous.values.IntegerValue; +import org.zwobble.couscous.values.ObjectValues; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static java.util.Arrays.asList; +import static org.zwobble.couscous.ast.LiteralNode.literal; +import static org.zwobble.couscous.ast.VariableDeclaration.var; +import static org.zwobble.couscous.ast.VariableReferenceNode.reference; +import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator; +import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; + +public class JavaExpressionReader { + static ExpressionNode readExpression(TypeName targetType, Expression expression) { + ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression); + return handleBoxing(targetType, couscousExpression); + } + + private static ExpressionNode handleBoxing(TypeName targetType, ExpressionNode couscousExpression) { + if (isIntegerBox(targetType, couscousExpression)) { + return StaticMethodCallNode.boxInt(couscousExpression); + } else if (isIntegerUnbox(targetType, couscousExpression)) { + return StaticMethodCallNode.unboxInt(couscousExpression); + } else if (isBooleanBox(targetType, couscousExpression)) { + return StaticMethodCallNode.boxBoolean(couscousExpression); + } else if (isBooleanUnbox(targetType, couscousExpression)) { + return StaticMethodCallNode.unboxBoolean(couscousExpression); + } else { + return couscousExpression; + } + } + + private static TypeName unboxedType(TypeName type) { + if (type.equals(ObjectValues.BOXED_INT)) { + return IntegerValue.REF; + } else if (type.equals(ObjectValues.BOXED_BOOLEAN)) { + return BooleanValue.REF; + } else { + return type; + } + } + + private static boolean isIntegerBox(TypeName targetType, ExpressionNode expression) { + return expression.getType().equals(IntegerValue.REF) && + !targetType.equals(IntegerValue.REF); + } + + private static boolean isIntegerUnbox(TypeName targetType, ExpressionNode expression) { + return !expression.getType().equals(IntegerValue.REF) && + targetType.equals(IntegerValue.REF); + } + + private static boolean isBooleanBox(TypeName targetType, ExpressionNode expression) { + return expression.getType().equals(BooleanValue.REF) && + !targetType.equals(BooleanValue.REF); + } + + private static boolean isBooleanUnbox(TypeName targetType, ExpressionNode expression) { + return !expression.getType().equals(BooleanValue.REF) && + targetType.equals(BooleanValue.REF); + } + + static ExpressionNode readExpressionWithoutBoxing(Expression expression) { + switch (expression.getNodeType()) { + case ASTNode.BOOLEAN_LITERAL: + return readBooleanLiteral((BooleanLiteral)expression); + + case ASTNode.NUMBER_LITERAL: + return readNumberLiteral((NumberLiteral)expression); + + case ASTNode.STRING_LITERAL: + return readStringLiteral((StringLiteral)expression); + + case ASTNode.SIMPLE_NAME: + return readSimpleName((SimpleName)expression); + + case ASTNode.THIS_EXPRESSION: + return readThisExpression((ThisExpression)expression); + + case ASTNode.FIELD_ACCESS: + return readFieldAccess((FieldAccess)expression); + + case ASTNode.METHOD_INVOCATION: + return readMethodInvocation((MethodInvocation)expression); + + case ASTNode.CLASS_INSTANCE_CREATION: + return readClassInstanceCreation((ClassInstanceCreation)expression); + + case ASTNode.INFIX_EXPRESSION: + return readInfixExpression((InfixExpression)expression); + + case ASTNode.PREFIX_EXPRESSION: + return readPrefixExpression((PrefixExpression)expression); + + case ASTNode.CONDITIONAL_EXPRESSION: + return readConditionalExpression((ConditionalExpression)expression); + + case ASTNode.ASSIGNMENT: + return readAssignment((Assignment)expression); + + default: + throw new RuntimeException("Unsupported expression: " + expression.getClass()); + + } + } + + private static ExpressionNode readBooleanLiteral(BooleanLiteral expression) { + return literal(expression.booleanValue()); + } + + private static LiteralNode readNumberLiteral(NumberLiteral expression) { + return literal(Integer.parseInt(expression.getToken())); + } + + private static ExpressionNode readStringLiteral(StringLiteral expression) { + return literal(expression.getLiteralValue()); + } + + private static ExpressionNode readSimpleName(SimpleName expression) { + IBinding binding = expression.resolveBinding(); + if (binding.getKind() == IBinding.VARIABLE) { + return readVariableBinding((IVariableBinding)binding); + } else { + throw new RuntimeException("Unsupported binding: " + binding.getClass()); + } + } + + private static ExpressionNode readVariableBinding(IVariableBinding binding) { + TypeName type = typeOf(binding); + if (binding.getDeclaringClass() == null) { + return reference(var(binding.getKey(), binding.getName(), type)); + } else { + return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type); + } + } + + private static ExpressionNode readThisExpression(ThisExpression expression) { + return ThisReferenceNode.thisReference(typeOf(expression)); + } + + private static ExpressionNode readFieldAccess(FieldAccess expression) { + return FieldAccessNode.fieldAccess(readExpressionWithoutBoxing(expression.getExpression()), expression.getName().getIdentifier(), typeOf(expression)); + } + + private static ExpressionNode readMethodInvocation(MethodInvocation expression) { + String methodName = expression.getName().getIdentifier(); + @SuppressWarnings("unchecked") + List<ExpressionNode> arguments = readArguments( + expression.resolveMethodBinding(), + expression.arguments()); + final TypeName type = typeOf(expression); + + IMethodBinding methodBinding = expression.resolveMethodBinding(); + TypeName receiverType = typeOf(methodBinding.getDeclaringClass()); + if ((methodBinding.getModifiers() & Modifier.STATIC) != 0) { + return StaticMethodCallNode.staticMethodCall( + receiverType, + methodName, + arguments, + type); + } else { + ExpressionNode receiver = expression.getExpression() == null + ? ThisReferenceNode.thisReference(receiverType) + : readExpressionWithoutBoxing(expression.getExpression()); + return MethodCallNode.methodCall( + receiver, + methodName, + arguments, + type); + } + } + + private static ExpressionNode readClassInstanceCreation(ClassInstanceCreation expression) { + @SuppressWarnings("unchecked") + List<Expression> arguments = expression.arguments(); + return ConstructorCallNode.constructorCall( + typeOf(expression), + readArguments(expression.resolveConstructorBinding(), arguments)); + } + + private static List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) { + return IntStream.range(0, javaArguments.size()) + .mapToObj(index -> readExpression( + typeOf(method.getParameterTypes()[index]), + javaArguments.get(index))) + .collect(Collectors.toList()); + } + + private static ExpressionNode readInfixExpression(InfixExpression expression) { + if (isPrimitiveOperation(expression)) { + Operator operator = readOperator(expression.getOperator()); + return readPrimitiveOperation( + operator, + expression.getLeftOperand(), + expression.getRightOperand()); + } else { + ExpressionNode left = readExpression(ObjectValues.OBJECT, expression.getLeftOperand()); + ExpressionNode right = readExpression(ObjectValues.OBJECT, expression.getRightOperand()); + if (expression.getOperator() == InfixExpression.Operator.EQUALS) { + return StaticMethodCallNode.same(left, right); + } else if (expression.getOperator() == InfixExpression.Operator.NOT_EQUALS) { + return MethodCallNode.not(StaticMethodCallNode.same(left, right)); + } else { + throw new IllegalArgumentException("Unsupported operator: " + expression.getOperator()); + } + } + } + + private static boolean isPrimitiveOperation(InfixExpression expression) { + TypeName leftOperandType = typeOf(expression.getLeftOperand()); + TypeName rightOperandType = typeOf(expression.getRightOperand()); + return isPrimitive(leftOperandType) + || isPrimitive(rightOperandType) + || (expression.getOperator() != InfixExpression.Operator.NOT_EQUALS + && expression.getOperator() != InfixExpression.Operator.EQUALS); + } + + private static boolean isPrimitive(TypeName type) { + return type.equals(BooleanValue.REF) || type.equals(IntegerValue.REF); + } + + private static ExpressionNode readPrefixExpression(PrefixExpression expression) { + Operator operator = readOperator(expression.getOperator()); + return AssignmentNode.assign( + (AssignableExpressionNode) readExpressionWithoutBoxing(expression.getOperand()), + MethodCallNode.methodCall( + readExpression(IntegerValue.REF, expression.getOperand()), + operator.getMethodName(), + asList(literal(1)), + IntegerValue.REF)); + } + + private static ExpressionNode readConditionalExpression(ConditionalExpression expression) { + TypeName type = typeOf(expression); + return TernaryConditionalNode.ternaryConditional( + readExpression(BooleanValue.REF, expression.getExpression()), + readExpression(type, expression.getThenExpression()), + readExpression(type, expression.getElseExpression())); + } + + private static ExpressionNode readAssignment(Assignment expression) { + AssignableExpressionNode left = (AssignableExpressionNode)readExpressionWithoutBoxing(expression.getLeftHandSide()); + if (expression.getOperator() == Assignment.Operator.ASSIGN) { + ExpressionNode right = readExpression(left.getType(), expression.getRightHandSide()); + return AssignmentNode.assign(left, right); + } else { + ExpressionNode right = readUnboxedExpression(expression.getRightHandSide()); + Operator operator = readOperator(expression.getOperator()); + return AssignmentNode.assign( + left, + handleBoxing( + left.getType(), + readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide()))); + } + } + + private static ExpressionNode readPrimitiveOperation(Operator operator, Expression leftJava, Expression rightJava) { + ExpressionNode left = readUnboxedExpression(leftJava); + ExpressionNode right = readUnboxedExpression(rightJava); + return MethodCallNode.methodCall( + left, + operator.getMethodName(), + asList(right), + operator.isBoolean() ? BooleanValue.REF : left.getType()); + } + + private static ExpressionNode readUnboxedExpression(Expression expression) { + return readExpression( + unboxedType(typeOf(expression)), + expression); + } +} diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java index 32662a6..a54ca55 100644 --- a/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaReader.java @@ -1,30 +1,17 @@ package org.zwobble.couscous.frontends.java; +import org.eclipse.jdt.core.dom.*; +import org.zwobble.couscous.ast.ClassNode; +import org.zwobble.couscous.ast.ClassNodeBuilder; +import org.zwobble.couscous.ast.StatementNode; + import java.io.IOException; import java.nio.file.Path; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import org.eclipse.jdt.core.dom.*; -import org.zwobble.couscous.ast.*; -import org.zwobble.couscous.ast.ClassNodeBuilder.MethodBuilder; -import org.zwobble.couscous.values.BooleanValue; -import org.zwobble.couscous.values.IntegerValue; -import org.zwobble.couscous.values.ObjectValues; -import static java.util.Arrays.asList; -import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement; -import static org.zwobble.couscous.ast.LiteralNode.literal; -import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration; -import static org.zwobble.couscous.ast.VariableDeclaration.var; -import static org.zwobble.couscous.ast.VariableReferenceNode.reference; -import static org.zwobble.couscous.ast.WhileNode.whileLoop; -import static org.zwobble.couscous.frontends.java.JavaOperators.readOperator; -import static org.zwobble.couscous.util.ExtraLists.eagerMap; +import static org.zwobble.couscous.frontends.java.JavaStatementReader.readStatement; +import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; public class JavaReader { - private final JavaParser parser = new JavaParser(); public ClassNode readClassFromFile(Path root, Path sourcePath) throws IOException { @@ -67,8 +54,8 @@ public class JavaReader { classBuilder.method(method.getName().getIdentifier(), true, builder -> buildMethod(method, builder)); } } - - private static <T> MethodBuilder<T> buildMethod(MethodDeclaration method, MethodBuilder<T> builder) { + + private static <T> ClassNodeBuilder.MethodBuilder<T> buildMethod(MethodDeclaration method, ClassNodeBuilder.MethodBuilder<T> builder) { for (IAnnotationBinding annotation : method.resolveBinding().getAnnotations()) { builder.annotation(typeOf(annotation.getAnnotationType())); } @@ -83,351 +70,9 @@ public class JavaReader { } return builder; } - - private static List<StatementNode> readStatement(Statement statement) { - switch (statement.getNodeType()) { - case ASTNode.BLOCK: - return readBlock((Block)statement); - - case ASTNode.RETURN_STATEMENT: - return asList(readReturnStatement((ReturnStatement)statement)); - - case ASTNode.EXPRESSION_STATEMENT: - return asList(readExpressionStatement((ExpressionStatement)statement)); - - case ASTNode.IF_STATEMENT: - return asList(readIfStatement((IfStatement)statement)); - - case ASTNode.WHILE_STATEMENT: - return asList(readWhileStatement((WhileStatement)statement)); - - case ASTNode.VARIABLE_DECLARATION_STATEMENT: - return readVariableDeclarationStatement((VariableDeclarationStatement)statement); - - default: - throw new RuntimeException("Unsupported statement: " + statement.getClass()); - } - } - - private static List<StatementNode> readBlock(Block block) { - @SuppressWarnings("unchecked") - List<Statement> statements = block.statements(); - return statements.stream() - .flatMap(statement -> readStatement(statement).stream()) - .collect(Collectors.toList()); - } - - private static StatementNode readReturnStatement(ReturnStatement statement) { - // TODO: set target type - return ReturnNode.returns(readExpressionWithoutBoxing(statement.getExpression())); - } - - private static StatementNode readExpressionStatement(ExpressionStatement statement) { - return expressionStatement(readExpressionWithoutBoxing(statement.getExpression())); - } - - private static StatementNode readIfStatement(IfStatement statement) { - return IfStatementNode.ifStatement( - readExpression(BooleanValue.REF, statement.getExpression()), - readStatement(statement.getThenStatement()), - readStatement(statement.getElseStatement())); - } - - private static WhileNode readWhileStatement(WhileStatement statement) { - return whileLoop( - readExpression(BooleanValue.REF, statement.getExpression()), - readStatement(statement.getBody())); - } - - private static List<StatementNode> readVariableDeclarationStatement(VariableDeclarationStatement statement) { - @SuppressWarnings("unchecked") - List<VariableDeclarationFragment> fragments = statement.fragments(); - TypeName type = typeOf(statement.getType()); - return eagerMap(fragments, fragment -> - localVariableDeclaration( - fragment.resolveBinding().getKey(), - fragment.getName().getIdentifier(), - type, - readExpression(type, fragment.getInitializer()))); - } - - private static ExpressionNode readExpression(TypeName targetType, Expression expression) { - ExpressionNode couscousExpression = readExpressionWithoutBoxing(expression); - return handleBoxing(targetType, couscousExpression); - } - - private static ExpressionNode handleBoxing(TypeName targetType, ExpressionNode couscousExpression) { - if (isIntegerBox(targetType, couscousExpression)) { - return StaticMethodCallNode.boxInt(couscousExpression); - } else if (isIntegerUnbox(targetType, couscousExpression)) { - return StaticMethodCallNode.unboxInt(couscousExpression); - } else if (isBooleanBox(targetType, couscousExpression)) { - return StaticMethodCallNode.boxBoolean(couscousExpression); - } else if (isBooleanUnbox(targetType, couscousExpression)) { - return StaticMethodCallNode.unboxBoolean(couscousExpression); - } else { - return couscousExpression; - } - } - - private static TypeName unboxedType(TypeName type) { - if (type.equals(ObjectValues.BOXED_INT)) { - return IntegerValue.REF; - } else if (type.equals(ObjectValues.BOXED_BOOLEAN)) { - return BooleanValue.REF; - } else { - return type; - } - } - - private static boolean isIntegerBox(TypeName targetType, ExpressionNode expression) { - return expression.getType().equals(IntegerValue.REF) && - !targetType.equals(IntegerValue.REF); - } - - private static boolean isIntegerUnbox(TypeName targetType, ExpressionNode expression) { - return !expression.getType().equals(IntegerValue.REF) && - targetType.equals(IntegerValue.REF); - } - - private static boolean isBooleanBox(TypeName targetType, ExpressionNode expression) { - return expression.getType().equals(BooleanValue.REF) && - !targetType.equals(BooleanValue.REF); - } - - private static boolean isBooleanUnbox(TypeName targetType, ExpressionNode expression) { - return !expression.getType().equals(BooleanValue.REF) && - targetType.equals(BooleanValue.REF); - } - - private static ExpressionNode readExpressionWithoutBoxing(Expression expression) { - switch (expression.getNodeType()) { - case ASTNode.BOOLEAN_LITERAL: - return readBooleanLiteral((BooleanLiteral)expression); - - case ASTNode.NUMBER_LITERAL: - return readNumberLiteral((NumberLiteral)expression); - - case ASTNode.STRING_LITERAL: - return readStringLiteral((StringLiteral)expression); - - case ASTNode.SIMPLE_NAME: - return readSimpleName((SimpleName)expression); - - case ASTNode.THIS_EXPRESSION: - return readThisExpression((ThisExpression)expression); - - case ASTNode.FIELD_ACCESS: - return readFieldAccess((FieldAccess)expression); - - case ASTNode.METHOD_INVOCATION: - return readMethodInvocation((MethodInvocation)expression); - - case ASTNode.CLASS_INSTANCE_CREATION: - return readClassInstanceCreation((ClassInstanceCreation)expression); - - case ASTNode.INFIX_EXPRESSION: - return readInfixExpression((InfixExpression)expression); - - case ASTNode.PREFIX_EXPRESSION: - return readPrefixExpression((PrefixExpression)expression); - - case ASTNode.CONDITIONAL_EXPRESSION: - return readConditionalExpression((ConditionalExpression)expression); - - case ASTNode.ASSIGNMENT: - return readAssignment((Assignment)expression); - - default: - throw new RuntimeException("Unsupported expression: " + expression.getClass()); - - } - } - - private static ExpressionNode readBooleanLiteral(BooleanLiteral expression) { - return literal(expression.booleanValue()); - } - - private static LiteralNode readNumberLiteral(NumberLiteral expression) { - return literal(Integer.parseInt(expression.getToken())); - } - - private static ExpressionNode readStringLiteral(StringLiteral expression) { - return literal(expression.getLiteralValue()); - } - - private static ExpressionNode readSimpleName(SimpleName expression) { - IBinding binding = expression.resolveBinding(); - if (binding.getKind() == IBinding.VARIABLE) { - return readVariableBinding((IVariableBinding)binding); - } else { - throw new RuntimeException("Unsupported binding: " + binding.getClass()); - } - } - - private static ExpressionNode readVariableBinding(IVariableBinding binding) { - TypeName type = typeOf(binding); - if (binding.getDeclaringClass() == null) { - return reference(var(binding.getKey(), binding.getName(), type)); - } else { - return FieldAccessNode.fieldAccess(ThisReferenceNode.thisReference(typeOf(binding.getDeclaringClass())), binding.getName(), type); - } - } - - private static ExpressionNode readThisExpression(ThisExpression expression) { - return ThisReferenceNode.thisReference(typeOf(expression)); - } - - private static ExpressionNode readFieldAccess(FieldAccess expression) { - return FieldAccessNode.fieldAccess(readExpressionWithoutBoxing(expression.getExpression()), expression.getName().getIdentifier(), typeOf(expression)); - } - - private static ExpressionNode readMethodInvocation(MethodInvocation expression) { - String methodName = expression.getName().getIdentifier(); - @SuppressWarnings("unchecked") - List<ExpressionNode> arguments = readArguments( - expression.resolveMethodBinding(), - expression.arguments()); - final TypeName type = typeOf(expression); - - IMethodBinding methodBinding = expression.resolveMethodBinding(); - TypeName receiverType = typeOf(methodBinding.getDeclaringClass()); - if ((methodBinding.getModifiers() & Modifier.STATIC) != 0) { - return StaticMethodCallNode.staticMethodCall( - receiverType, - methodName, - arguments, - type); - } else { - ExpressionNode receiver = expression.getExpression() == null - ? ThisReferenceNode.thisReference(receiverType) - : readExpressionWithoutBoxing(expression.getExpression()); - return MethodCallNode.methodCall( - receiver, - methodName, - arguments, - type); - } - } - - private static ExpressionNode readClassInstanceCreation(ClassInstanceCreation expression) { - @SuppressWarnings("unchecked") - List<Expression> arguments = expression.arguments(); - return ConstructorCallNode.constructorCall( - typeOf(expression), - readArguments(expression.resolveConstructorBinding(), arguments)); - } - - private static List<ExpressionNode> readArguments(IMethodBinding method, List<Expression> javaArguments) { - return IntStream.range(0, javaArguments.size()) - .mapToObj(index -> readExpression( - typeOf(method.getParameterTypes()[index]), - javaArguments.get(index))) - .collect(Collectors.toList()); - } - - private static ExpressionNode readInfixExpression(InfixExpression expression) { - if (isPrimitiveOperation(expression)) { - Operator operator = readOperator(expression.getOperator()); - return readPrimitiveOperation( - operator, - expression.getLeftOperand(), - expression.getRightOperand()); - } else { - ExpressionNode left = readExpression(ObjectValues.OBJECT, expression.getLeftOperand()); - ExpressionNode right = readExpression(ObjectValues.OBJECT, expression.getRightOperand()); - if (expression.getOperator() == InfixExpression.Operator.EQUALS) { - return StaticMethodCallNode.same(left, right); - } else if (expression.getOperator() == InfixExpression.Operator.NOT_EQUALS) { - return MethodCallNode.not(StaticMethodCallNode.same(left, right)); - } else { - throw new IllegalArgumentException("Unsupported operator: " + expression.getOperator()); - } - } - } - - private static boolean isPrimitiveOperation(InfixExpression expression) { - TypeName leftOperandType = typeOf(expression.getLeftOperand()); - TypeName rightOperandType = typeOf(expression.getRightOperand()); - return isPrimitive(leftOperandType) - || isPrimitive(rightOperandType) - || (expression.getOperator() != InfixExpression.Operator.NOT_EQUALS - && expression.getOperator() != InfixExpression.Operator.EQUALS); - } - - private static boolean isPrimitive(TypeName type) { - return type.equals(BooleanValue.REF) || type.equals(IntegerValue.REF); - } - - private static ExpressionNode readPrefixExpression(PrefixExpression expression) { - Operator operator = readOperator(expression.getOperator()); - return AssignmentNode.assign( - (AssignableExpressionNode) readExpressionWithoutBoxing(expression.getOperand()), - MethodCallNode.methodCall( - readExpression(IntegerValue.REF, expression.getOperand()), - operator.getMethodName(), - asList(literal(1)), - IntegerValue.REF)); - } - - private static ExpressionNode readConditionalExpression(ConditionalExpression expression) { - TypeName type = typeOf(expression); - return TernaryConditionalNode.ternaryConditional( - readExpression(BooleanValue.REF, expression.getExpression()), - readExpression(type, expression.getThenExpression()), - readExpression(type, expression.getElseExpression())); - } - - private static ExpressionNode readAssignment(Assignment expression) { - AssignableExpressionNode left = (AssignableExpressionNode)readExpressionWithoutBoxing(expression.getLeftHandSide()); - if (expression.getOperator() == Assignment.Operator.ASSIGN) { - ExpressionNode right = readExpression(left.getType(), expression.getRightHandSide()); - return AssignmentNode.assign(left, right); - } else { - ExpressionNode right = readUnboxedExpression(expression.getRightHandSide()); - Operator operator = readOperator(expression.getOperator()); - return AssignmentNode.assign( - left, - handleBoxing( - left.getType(), - readPrimitiveOperation(operator, expression.getLeftHandSide(), expression.getRightHandSide()))); - } - } - - private static ExpressionNode readPrimitiveOperation(Operator operator, Expression leftJava, Expression rightJava) { - ExpressionNode left = readUnboxedExpression(leftJava); - ExpressionNode right = readUnboxedExpression(rightJava); - return MethodCallNode.methodCall( - left, - operator.getMethodName(), - asList(right), - operator.isBoolean() ? BooleanValue.REF : left.getType()); - } - - private static ExpressionNode readUnboxedExpression(Expression expression) { - return readExpression( - unboxedType(typeOf(expression)), - expression); - } private static String generateClassName(CompilationUnit ast) { TypeDeclaration type = (TypeDeclaration)ast.types().get(0); return ast.getPackage().getName().getFullyQualifiedName() + "." + type.getName().getFullyQualifiedName(); } - - private static TypeName typeOf(Expression expression) { - return typeOf(expression.resolveTypeBinding()); - } - - private static TypeName typeOf(IVariableBinding variableBinding) { - return typeOf(variableBinding.getType()); - } - - private static TypeName typeOf(Type type) { - return typeOf(type.resolveBinding()); - } - - private static TypeName typeOf(ITypeBinding typeBinding) { - return TypeName.of(typeBinding.getQualifiedName()); - } }
\ No newline at end of file diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java new file mode 100644 index 0000000..c5194b4 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaStatementReader.java @@ -0,0 +1,86 @@ +package org.zwobble.couscous.frontends.java; + +import org.eclipse.jdt.core.dom.*; +import org.zwobble.couscous.ast.*; +import org.zwobble.couscous.values.BooleanValue; + +import java.util.List; +import java.util.stream.Collectors; + +import static java.util.Arrays.asList; +import static org.zwobble.couscous.ast.ExpressionStatementNode.expressionStatement; +import static org.zwobble.couscous.ast.LocalVariableDeclarationNode.localVariableDeclaration; +import static org.zwobble.couscous.ast.WhileNode.whileLoop; +import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpression; +import static org.zwobble.couscous.frontends.java.JavaExpressionReader.readExpressionWithoutBoxing; +import static org.zwobble.couscous.frontends.java.JavaTypes.typeOf; +import static org.zwobble.couscous.util.ExtraLists.eagerMap; + +public class JavaStatementReader { + static List<StatementNode> readStatement(Statement statement) { + switch (statement.getNodeType()) { + case ASTNode.BLOCK: + return readBlock((Block)statement); + + case ASTNode.RETURN_STATEMENT: + return asList(readReturnStatement((ReturnStatement)statement)); + + case ASTNode.EXPRESSION_STATEMENT: + return asList(readExpressionStatement((ExpressionStatement)statement)); + + case ASTNode.IF_STATEMENT: + return asList(readIfStatement((IfStatement)statement)); + + case ASTNode.WHILE_STATEMENT: + return asList(readWhileStatement((WhileStatement)statement)); + + case ASTNode.VARIABLE_DECLARATION_STATEMENT: + return readVariableDeclarationStatement((VariableDeclarationStatement)statement); + + default: + throw new RuntimeException("Unsupported statement: " + statement.getClass()); + } + } + + private static List<StatementNode> readBlock(Block block) { + @SuppressWarnings("unchecked") + List<Statement> statements = block.statements(); + return statements.stream() + .flatMap(statement -> readStatement(statement).stream()) + .collect(Collectors.toList()); + } + + private static StatementNode readReturnStatement(ReturnStatement statement) { + // TODO: set target type + return ReturnNode.returns(readExpressionWithoutBoxing(statement.getExpression())); + } + + private static StatementNode readExpressionStatement(ExpressionStatement statement) { + return expressionStatement(readExpressionWithoutBoxing(statement.getExpression())); + } + + private static StatementNode readIfStatement(IfStatement statement) { + return IfStatementNode.ifStatement( + readExpression(BooleanValue.REF, statement.getExpression()), + readStatement(statement.getThenStatement()), + readStatement(statement.getElseStatement())); + } + + private static WhileNode readWhileStatement(WhileStatement statement) { + return whileLoop( + readExpression(BooleanValue.REF, statement.getExpression()), + readStatement(statement.getBody())); + } + + private static List<StatementNode> readVariableDeclarationStatement(VariableDeclarationStatement statement) { + @SuppressWarnings("unchecked") + List<VariableDeclarationFragment> fragments = statement.fragments(); + TypeName type = typeOf(statement.getType()); + return eagerMap(fragments, fragment -> + localVariableDeclaration( + fragment.resolveBinding().getKey(), + fragment.getName().getIdentifier(), + type, + readExpression(type, fragment.getInitializer()))); + } +} diff --git a/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java new file mode 100644 index 0000000..d6b2160 --- /dev/null +++ b/src/main/java/org/zwobble/couscous/frontends/java/JavaTypes.java @@ -0,0 +1,25 @@ +package org.zwobble.couscous.frontends.java; + +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ITypeBinding; +import org.eclipse.jdt.core.dom.IVariableBinding; +import org.eclipse.jdt.core.dom.Type; +import org.zwobble.couscous.ast.TypeName; + +class JavaTypes { + static TypeName typeOf(Expression expression) { + return typeOf(expression.resolveTypeBinding()); + } + + static TypeName typeOf(IVariableBinding variableBinding) { + return typeOf(variableBinding.getType()); + } + + static TypeName typeOf(Type type) { + return typeOf(type.resolveBinding()); + } + + static TypeName typeOf(ITypeBinding typeBinding) { + return TypeName.of(typeBinding.getQualifiedName()); + } +} |
