Prefix, postfix and basic infix operations

This commit is contained in:
Andrey Breslav
2011-03-15 18:00:03 +03:00
parent 0708db49a7
commit 69f40ac81e
6 changed files with 90 additions and 58 deletions
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
}
@@ -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);
}
@@ -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.<JetType>emptyList());
FunctionDescriptor functionDescriptor = lookupFunction(scope, expression.getOperationSign(), name, type, Collections.<JetType>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<IElementType, String> operationToMethodName = new HashMap<IElementType, String>();
private static final Map<IElementType, String> unaryOperationNames = new HashMap<IElementType, String>();
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<IElementType, String> binaryOperationNames = new HashMap<IElementType, String>();
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<IElementType> comparisonOperations = new HashSet<IElementType>(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ));
private static final Set<IElementType> equalsOperations = new HashSet<IElementType>(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ));
private static final Set<IElementType> inOperations = new HashSet<IElementType>(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<IElementType, String> assignmentOperationNames = new HashMap<IElementType, String>();
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");
}
@@ -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<String>() `plus`+ "1"
new X<String>() `plus`plus "sadfas"
new X<String>().`plus`plus("")
val x = new X<String>
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 <T> tt(t : T) : T {
@@ -41,4 +54,10 @@ fun <T> 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`--
}