diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java index 2afe27991c1..0c8c1c3bb50 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java @@ -2,21 +2,15 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.JetNodeTypes; /** * @author max */ -public class JetPostfixExpression extends JetExpression { +public class JetPostfixExpression extends JetUnaryExpression { public JetPostfixExpression(@NotNull ASTNode node) { super(node); } - @Override - public void accept(JetVisitor visitor) { - visitor.visitPostfixExpression(this); - } - @NotNull public JetExpression getBaseExpression() { JetExpression answer = findChildByClass(JetExpression.class); @@ -24,8 +18,9 @@ public class JetPostfixExpression extends JetExpression { return answer; } - @NotNull - public JetSimpleNameExpression getOperationSign() { - return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); + @Override + public void accept(JetVisitor visitor) { + visitor.visitPostfixExpression(this); } + } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java index 60ffd310fd3..e4c9fd15325 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java @@ -8,7 +8,7 @@ import org.jetbrains.jet.JetNodeTypes; /** * @author max */ -public class JetPrefixExpression extends JetExpression { +public class JetPrefixExpression extends JetUnaryExpression { public JetPrefixExpression(@NotNull ASTNode node) { super(node); } @@ -27,9 +27,4 @@ public class JetPrefixExpression extends JetExpression { assert expression != null; return (JetExpression) expression; } - - @NotNull - public JetSimpleNameExpression getOperationSign() { - return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); - } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java new file mode 100644 index 00000000000..404fd88d90f --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/JetUnaryExpression.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.lang.psi; + +import com.intellij.lang.ASTNode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetNodeTypes; + +/** + * @author abreslav + */ +public abstract class JetUnaryExpression extends JetExpression { + public JetUnaryExpression(ASTNode node) { + super(node); + } + + @NotNull + public abstract JetExpression getBaseExpression(); + + @NotNull + public JetSimpleNameExpression getOperationSign() { + return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java index 66e9b019b8d..2c88293a238 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java @@ -151,10 +151,14 @@ public class JetVisitor extends PsiElementVisitor { } public void visitPrefixExpression(JetPrefixExpression expression) { - visitExpression(expression); + visitUnaryExpression(expression); } public void visitPostfixExpression(JetPostfixExpression expression) { + visitUnaryExpression(expression); + } + + public void visitUnaryExpression(JetUnaryExpression expression) { visitExpression(expression); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 0c50773a7bd..94c11712c77 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -525,21 +525,21 @@ public class JetTypeInferrer { } @Override - public void visitPrefixExpression(JetPrefixExpression expression) { + public void visitUnaryExpression(JetUnaryExpression expression) { JetSimpleNameExpression operationSign = expression.getOperationSign(); - if (operationSign.getReferencedNameElementType() == JetTokens.EXCL) { - JetExpression baseExpression = expression.getBaseExpression(); - JetType type = getType(scope, baseExpression, false); + String name = unaryOperationNames.get(operationSign.getReferencedNameElementType()); + if (name == null) { + semanticServices.getErrorHandler().structuralError(operationSign.getNode(), "Unknown unary operation"); + } + else { + JetType type = getType(scope, expression.getBaseExpression(), false); if (type != null) { - FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, "not", type, Collections.emptyList()); + FunctionDescriptor functionDescriptor = lookupFunction(scope, expression.getOperationSign(), name, type, Collections.emptyList()); if (functionDescriptor != null) { result = functionDescriptor.getUnsubstitutedReturnType(); } } } - else { - throw new UnsupportedOperationException(); // TODO - } } @Override @@ -550,8 +550,8 @@ public class JetTypeInferrer { if (operationType == JetTokens.IDENTIFIER) { result = getTypeForBinaryCall(expression, operationSign.getReferencedName(), scope); } - else if (operationType == JetTokens.PLUS) { - result = getTypeForBinaryCall(expression, "plus", scope); + else if (binaryOperationNames.containsKey(operationType)) { + result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), scope); } else if (operationType == JetTokens.EQ) { JetExpression left = expression.getLeft(); @@ -566,7 +566,7 @@ public class JetTypeInferrer { } result = null; // TODO : This is not an expression, in fact! } - else if (operationType == JetTokens.LT) { + else if (comparisonOperations.contains(operationType)) { JetExpression left = expression.getLeft(); JetExpression deparenthesized = deparenthesize(left); if (deparenthesized instanceof JetArrayAccessExpression) { @@ -579,7 +579,7 @@ public class JetTypeInferrer { } result = null; // TODO : This is not an expression, in fact! } else { - throw new UnsupportedOperationException(); // TODO + semanticServices.getErrorHandler().structuralError(operationSign.getNode(), "Unknown operation"); } } @@ -637,38 +637,35 @@ public class JetTypeInferrer { } } - { - Map operationToMethodName = new HashMap(); + private static final Map unaryOperationNames = new HashMap(); + static { + unaryOperationNames.put(JetTokens.PLUSPLUS, "inc"); + unaryOperationNames.put(JetTokens.MINUSMINUS, "dec"); + unaryOperationNames.put(JetTokens.EXCL, "not"); + } -// operationToMethodName.put(JetTokens.EXCL, "excl"); -// -// operationToMethodName.put(JetTokens.LT, "lt"); -// operationToMethodName.put(JetTokens.GT, "gt"); -// operationToMethodName.put(JetTokens.LTEQ, "lteq"); -// operationToMethodName.put(JetTokens.GTEQ, "gteq"); -// -// operationToMethodName.put(JetTokens.EQEQ, "eqeq"); -// operationToMethodName.put(JetTokens.EXCLEQ, "excleq"); -// -// operationToMethodName.put(JetTokens.MULTEQ, "multeq"); -// operationToMethodName.put(JetTokens.DIVEQ, "diveq"); -// operationToMethodName.put(JetTokens.PERCEQ, "perceq"); -// operationToMethodName.put(JetTokens.PLUSEQ, "pluseq"); -// operationToMethodName.put(JetTokens.MINUSEQ, "minuseq"); -// -// operationToMethodName.put(JetTokens.PLUSPLUS, "plusplus"); -// operationToMethodName.put(JetTokens.MINUSMINUS, "minusminus"); + private static final Map binaryOperationNames = new HashMap(); + static { + binaryOperationNames.put(JetTokens.MUL, "times"); + binaryOperationNames.put(JetTokens.PLUS, "plus"); + binaryOperationNames.put(JetTokens.MINUS, "minus"); + binaryOperationNames.put(JetTokens.DIV, "div"); + binaryOperationNames.put(JetTokens.PERC, "mod"); + binaryOperationNames.put(JetTokens.ARROW, "arrow"); + binaryOperationNames.put(JetTokens.RANGE, "rangeTo"); + } - operationToMethodName.put(JetTokens.MUL, "times"); - operationToMethodName.put(JetTokens.PLUS, "plus"); - operationToMethodName.put(JetTokens.MINUS, "minus"); - operationToMethodName.put(JetTokens.DIV, "div"); - operationToMethodName.put(JetTokens.PERC, "mod"); - operationToMethodName.put(JetTokens.ARROW, "arrow"); - operationToMethodName.put(JetTokens.RANGE, "rangeTo"); + private static final Set comparisonOperations = new HashSet(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ)); + private static final Set equalsOperations = new HashSet(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ)); + private static final Set inOperations = new HashSet(Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.NOT_IN)); -// operationToMethodName.put(JetTokens.IN_KEYWORD, "contains"); -// operationToMethodName.put(JetTokens.NOT_IN, "not_in"); + private static final Map assignmentOperationNames = new HashMap(); + static { + assignmentOperationNames.put(JetTokens.MULTEQ, "timesAssign"); + assignmentOperationNames.put(JetTokens.DIVEQ, "divAssign"); + assignmentOperationNames.put(JetTokens.PERCEQ, "modAssign"); + assignmentOperationNames.put(JetTokens.PLUSEQ, "plusAssign"); + assignmentOperationNames.put(JetTokens.MINUSEQ, "minusAssign"); } diff --git a/idea/testData/resolve/ResolveOfInfixExpressions.jet b/idea/testData/resolve/ResolveOfInfixExpressions.jet index 571ab1b5ff0..b0e92bca501 100644 --- a/idea/testData/resolve/ResolveOfInfixExpressions.jet +++ b/idea/testData/resolve/ResolveOfInfixExpressions.jet @@ -4,6 +4,11 @@ import util.* ~X~class X<~T~T> { fun foo(a : `T`T) : `X`X<`T`T>{} ~plus~fun plus(t : `T`T) : Int {} + ~minus~fun minus(t : String) : Int {} + ~times~fun times(t : String) : Int {} + ~div~fun div(t : String) : Int {} + ~mod~fun mod(t : String) : Int {} + ~rangeTo~fun rangeTo(t : String) : Int {} } ~t~fun <~t.T~T> t(~t.t~t : `t.T`T) : `t.T`T { @@ -14,6 +19,12 @@ import util.* new X() `plus`+ "1" new X() `plus`plus "sadfas" new X().`plus`plus("") + val x = new X + x `minus`- "" + x `times`* "" + x `div`/ "" + x `mod`% "" + x `rangeTo`.. "" } ~Foo~class Foo { @@ -25,6 +36,8 @@ import util.* ~Bar~class Bar : Foo { ~not~fun not() : String {} + ~inc~fun inc() : Unit + ~dec~fun dec() : Unit } fun tt(t : T) : T { @@ -41,4 +54,10 @@ fun tt(t : T) : T { x`!`[null] = null (x`!`[null, 2]) = null (`not`!foo)[1]`:std::Char` + val y = new Bar + y`inc`++ + `inc`++y + `dec`--y + y`dec`-- + }