Merge branch 'master' of ssh://git.labs.intellij.net/jet

This commit is contained in:
svtk
2011-11-03 21:07:48 +04:00
45 changed files with 1072 additions and 611 deletions
+4
View File
@@ -3,3 +3,7 @@ examples/.idea/dictionaries
examples/.idea/workspace.xml
confluence/target
confluence/target
out
.idea/dictionaries/yozh.xml
.idea/codeStyleSettings.xml
.idea/workspace.xml
@@ -1,10 +1,10 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -23,12 +23,12 @@ public abstract class ClassBodyCodegen {
protected final JetClassOrObject myClass;
protected final OwnerKind kind;
protected final ClassDescriptor descriptor;
protected final ClassVisitor v;
protected final ClassBuilder v;
protected final ClassContext context;
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>();
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
public ClassBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
this.state = state;
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
myClass = aClass;
@@ -46,7 +46,7 @@ public abstract class ClassBodyCodegen {
generateStaticInitializer();
v.visitEnd();
v.done();
}
protected abstract void generateDeclaration();
@@ -62,7 +62,7 @@ public abstract class ClassBodyCodegen {
generateDeclaration(propertyCodegen, declaration, functionCodegen);
}
generatePrimaryConstructorProperties(propertyCodegen);
generatePrimaryConstructorProperties(propertyCodegen, myClass);
}
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
@@ -82,20 +82,20 @@ public abstract class ClassBodyCodegen {
functionCodegen.gen(declaration);
}
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, PsiElement origin) {
OwnerKind kind = context.getContextKind();
for (JetParameter p : getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, origin);
}
//noinspection ConstantConditions
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
v.visitField(Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
v.newField(p, Opcodes.ACC_PRIVATE, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, null);
}
}
}
@@ -111,8 +111,8 @@ public abstract class ClassBodyCodegen {
private void generateStaticInitializer() {
if (staticInitializerChunks.size() > 0) {
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<clinit>", "()V", null, null);
final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<clinit>", "()V", null, null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
@@ -0,0 +1,59 @@
/*
* @author max
*/
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
public class ClassBuilder {
private final ClassVisitor v;
public ClassBuilder(ClassVisitor v) {
this.v = v;
}
public FieldVisitor newField(@Nullable PsiElement origin,
int access,
String name,
String desc,
String signature,
Object value) {
return v.visitField(access, name, desc, signature, value);
}
public MethodVisitor newMethod(@Nullable PsiElement origin,
int access,
String name,
String desc,
@Nullable String signature,
@Nullable String[] exceptions) {
return v.visitMethod(access, name, desc, signature, exceptions);
}
public AnnotationVisitor newAnnotation(PsiElement origin,
String desc,
boolean visible) {
return v.visitAnnotation(desc, visible);
}
public void done() {
v.visitEnd();
}
public ClassVisitor getVisitor() {
return v;
}
public void defineClass(int version, int access, String name, String signature, String superName, String[] interfaces) {
v.visit(version, access, name, signature, superName, interfaces);
}
public void visitSource(String name, String debug) {
v.visitSource(name, debug);
}
}
@@ -3,7 +3,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
/**
* @author max
@@ -33,7 +32,7 @@ public class ClassCodegen {
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
ClassVisitor v = state.forClassImplementation(descriptor);
ClassBuilder v = state.forClassImplementation(descriptor);
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
@@ -17,7 +17,7 @@ public class ClassFileFactory {
private final Project project;
private final boolean isText;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassVisitor> generators = new LinkedHashMap<String, ClassVisitor>();
private final Map<String, ClassBuilder> generators = new LinkedHashMap<String, ClassBuilder>();
private boolean isDone = false;
public final GenerationState state;
@@ -27,7 +27,7 @@ public class ClassFileFactory {
this.state = state;
}
ClassVisitor newVisitor(String filePath) {
ClassBuilder newVisitor(String filePath) {
ClassVisitor visitor;
if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
@@ -36,11 +36,12 @@ public class ClassFileFactory {
visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
generators.put(filePath, visitor);
return visitor;
final ClassBuilder answer = new ClassBuilder(visitor);
generators.put(filePath, answer);
return answer;
}
ClassVisitor forAnonymousSubclass(String className) {
ClassBuilder forAnonymousSubclass(String className) {
return newVisitor(className + ".class");
}
@@ -49,8 +50,8 @@ public class ClassFileFactory {
String fqName = namespace.getFQName();
NamespaceCodegen codegen = ns2codegen.get(fqName);
if (codegen == null) {
final ClassVisitor classVisitor = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class");
codegen = new NamespaceCodegen(classVisitor, fqName, state, namespace.getContainingFile());
final ClassBuilder builder = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class");
codegen = new NamespaceCodegen(builder, fqName, state, namespace.getContainingFile());
ns2codegen.put(fqName, codegen);
}
@@ -71,7 +72,7 @@ public class ClassFileFactory {
done();
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file);
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file).getVisitor();
StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer));
@@ -84,7 +85,7 @@ public class ClassFileFactory {
done();
ClassWriter visitor = (ClassWriter) generators.get(file);
ClassWriter visitor = (ClassWriter) generators.get(file).getVisitor();
return visitor.toByteArray();
}
@@ -5,13 +5,18 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.*;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureWriter;
@@ -44,7 +49,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
}
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
final Pair<String, ClassVisitor> nameAndVisitor = state.forAnonymousSubclass(fun);
final Pair<String, ClassBuilder> nameAndVisitor = state.forAnonymousSubclass(fun);
final FunctionDescriptor funDescriptor = (FunctionDescriptor) state.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, fun);
@@ -63,32 +68,32 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
appendType(signatureWriter, funDescriptor.getReturnType(), '=');
signatureWriter.visitEnd();
cv.visit(V1_6,
ACC_PUBLIC,
name,
null,
funClass,
new String[0]
cv.defineClass(V1_6,
ACC_PUBLIC,
name,
null,
funClass,
new String[0]
);
cv.visitSource(fun.getContainingFile().getName(), null);
generateBridge(name, funDescriptor, cv);
generateBridge(name, funDescriptor, fun, cv);
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
if (enclosingType == null) captureThis = false;
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType());
final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
if (captureThis) {
cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null);
cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
}
if(isConst()) {
generateConstInstance();
generateConstInstance(fun);
}
cv.visitEnd();
cv.done();
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis);
for (DeclarationDescriptor descriptor : closure.keySet()) {
@@ -98,41 +103,23 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
return answer;
}
private void generateConstInstance() {
cv.visitField(ACC_PRIVATE| ACC_STATIC, "$instance", "Ljava/lang/ref/SoftReference;", null, null);
private void generateConstInstance(JetFunctionLiteralExpression fun) {
String classDescr = "L" + name + ";";
cv.newField(fun, ACC_PRIVATE | ACC_STATIC, "$instance", classDescr, null, null);
MethodVisitor mv = cv.visitMethod(ACC_PUBLIC | ACC_STATIC, "$getInstance", "()L" + name + ";", null, new String[0]);
MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC | ACC_STATIC, "$getInstance", "()" + classDescr, null, new String[0]);
mv.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;");
mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
mv.visitInsn(DUP);
Label makeNew = new Label();
mv.visitJumpInsn(IFNULL, makeNew);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/ref/SoftReference", "get", "()Ljava/lang/Object;");
mv.visitInsn(DUP);
Label ret = new Label();
mv.visitJumpInsn(IFNULL, makeNew);
mv.visitTypeInsn(CHECKCAST, name);
mv.visitJumpInsn(GOTO, ret);
mv.visitJumpInsn(IFNONNULL, ret);
mv.visitLabel(makeNew);
mv.visitInsn(POP);
mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference");
mv.visitInsn(DUP);
mv.visitTypeInsn(NEW, name);
mv.visitInsn(DUP);
mv.visitVarInsn(ASTORE, 0);
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V");
mv.visitFieldInsn(PUTSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;");
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
mv.visitLabel(ret);
mv.visitInsn(ARETURN);
@@ -140,21 +127,21 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd();
}
private boolean generateBody(FunctionDescriptor funDescriptor, ClassVisitor cv, JetFunctionLiteral body) {
private boolean generateBody(FunctionDescriptor funDescriptor, ClassBuilder cv, JetFunctionLiteral body) {
final ClassContext closureContext = context.intoClosure(name, this);
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
return closureContext.isThisWasUsed();
}
private void generateBridge(String className, FunctionDescriptor funDescriptor, ClassVisitor cv) {
private void generateBridge(String className, FunctionDescriptor funDescriptor, JetFunctionLiteralExpression fun, ClassBuilder cv) {
final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor);
if(bridge.getDescriptor().equals(delegate.getDescriptor()))
return;
final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -185,7 +172,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd();
}
private Method generateConstructor(String funClass, boolean captureThis, JetType returnType) {
private Method generateConstructor(String funClass, boolean captureThis, JetFunctionLiteralExpression fun, JetType returnType) {
int argCount = closure.size();
if (captureThis) {
@@ -208,7 +195,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
}
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
final MethodVisitor mv = cv.newMethod(fun, ACC_PUBLIC, "<init>", constructor.getDescriptor(), null, new String[0]);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
@@ -12,7 +12,6 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
@@ -53,7 +52,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private int myLastLineNumber = -1;
private final InstructionAdapter v;
private final FrameMap myMap;
private final FrameMap myFrameMap;
private final JetTypeMapper typeMapper;
private final GenerationState state;
@@ -69,7 +68,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type returnType,
ClassContext context,
GenerationState state) {
this.myMap = myMap;
this.myFrameMap = myMap;
this.typeMapper = state.getTypeMapper();
this.returnType = returnType;
this.state = state;
@@ -265,7 +264,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType);
int iteratorVar = myMap.enterTemp();
int iteratorVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType);
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
v.store(iteratorVar, asmIterType);
@@ -290,7 +289,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
v.ifeq(end);
myMap.enter(parameterDescriptor, asmParamType.getSize());
myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
v.load(iteratorVar, asmIterType);
invokeFunctionNoParams(nextDescriptor, asmParamType, v);
@@ -305,10 +304,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.goTo(begin);
v.mark(end);
int paramIndex = myMap.leave(parameterDescriptor);
int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myMap.leaveTemp();
myFrameMap.leaveTemp();
myBreakTargets.pop();
myContinueTargets.pop();
}
@@ -339,7 +338,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType);
myMap.enter(parameterDescriptor, asmParamType.getSize());
myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
generatePrologue();
Label condition = new Label();
@@ -359,7 +358,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end);
cleanupTemp();
final int paramIndex = myMap.leave(parameterDescriptor);
final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop();
@@ -387,11 +386,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
protected void generatePrologue() {
myLengthVar = myMap.enterTemp();
myLengthVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType);
v.arraylength();
v.store(myLengthVar, Type.INT_TYPE);
myIndexVar = myMap.enterTemp();
myIndexVar = myFrameMap.enterTemp();
v.iconst(0);
v.store(myIndexVar, Type.INT_TYPE);
}
@@ -415,7 +414,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
protected void cleanupTemp() {
myMap.leaveTemp(2);
myFrameMap.leaveTemp(2);
}
}
@@ -428,7 +427,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
protected void generatePrologue() {
myEndVar = myMap.enterTemp();
myEndVar = myFrameMap.enterTemp();
if(isIntRangeExpr(expression.getLoopRange())) {
JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange();
//noinspection ConstantConditions
@@ -462,7 +461,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
protected void cleanupTemp() {
myMap.leaveTemp(1);
myFrameMap.leaveTemp(1);
}
}
@@ -635,7 +634,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, type.getSize());
myFrameMap.enter(variableDescriptor, type.getSize());
}
}
@@ -659,7 +658,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null;
int index = myMap.leave(variableDescriptor);
int index = myFrameMap.leave(variableDescriptor);
final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
@@ -860,7 +859,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
public int lookupLocal(DeclarationDescriptor descriptor) {
return myMap.getIndex(descriptor);
return myFrameMap.getIndex(descriptor);
}
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) {
@@ -1123,8 +1122,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;
final StackValue outer;
if (!thisDone && myMap instanceof ConstructorFrameMap) {
outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
if (!thisDone && myFrameMap instanceof ConstructorFrameMap) {
outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
}
else {
thisToStack();
@@ -1189,12 +1188,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else if(resolvedValueArgument instanceof VarargValueArgument) {
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
JetType outType = valueParameterDescriptor.getOutType();
Type type = typeMapper.mapType(outType);
assert type.getSort() == Type.ARRAY;
Type elementType = type.getElementType();
int size = valueArgument.getArgumentExpressions().size();
v.iconst(valueArgument.getArgumentExpressions().size());
v.newarray(elementType);
for(int i = 0; i != size; ++i) {
@@ -1203,7 +1202,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
gen(valueArgument.getArgumentExpressions().get(i), elementType);
StackValue.arrayElement(elementType, false).store(v);
}
// throw new UnsupportedOperationException("Varargs are not supported yet");
}
else {
@@ -1632,12 +1631,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
final Callable callable = resolveToCallable(op);
final JetExpression lhs = expression.getLeft();
// if(lhs instanceof JetArrayAccessExpression) {
// JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) lhs;
// if(arrayAccessExpression.getIndexExpressions().size() != 1) {
// throw new UnsupportedOperationException("Augmented assignment with multi-index");
// }
// }
Type lhsType = expressionType(lhs);
//noinspection ConstantConditions
if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) {
if (callable instanceof IntrinsicMethod) {
StackValue value = gen(lhs); // receiver
value.dupReceiver(v, 0); // receiver receiver
value.dupReceiver(v); // receiver receiver
value.put(lhsType, v); // receiver lhs
final IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
//noinspection NullableProblems
@@ -1660,7 +1667,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) {
StackValue value = gen(expression.getLeft());
if (keepReturnValue) {
value.dupReceiver(v, 0);
value.dupReceiver(v);
}
value.put(lhsType, v);
genToJVMStack(expression.getRight());
@@ -1748,7 +1755,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
StackValue value = genQualified(receiver, operand);
value.dupReceiver(v, 0);
value.dupReceiver(v);
value.put(asmType, v);
if (asmType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing
@@ -1915,7 +1922,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
if(args.size() == 2) {
int sizeIndex = myMap.enterTemp(2);
int sizeIndex = myFrameMap.enterTemp(2);
int indexIndex = sizeIndex+1;
v.dup();
@@ -1947,7 +1954,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.visitLabel(end);
v.pop();
myMap.leaveTemp(2);
myFrameMap.leaveTemp(2);
}
}
@@ -1957,8 +1964,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
gen(array, arrayType);
generateArrayIndex(expression);
if (arrayType.getSort() == Type.ARRAY) {
final List<JetExpression> indices = expression.getIndexExpressions();
FunctionDescriptor operationDescriptor = (FunctionDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, expression);
if (arrayType.getSort() == Type.ARRAY && indices.size() == 1 && operationDescriptor.getValueParameters().get(0).getOutType().equals(state.getStandardLibrary().getIntType())) {
for (JetExpression index : indices) {
gen(index, Type.INT_TYPE);
}
if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
JetType elementType = type.getArguments().get(0).getType();
Type notBoxed = typeMapper.mapType(elementType);
@@ -1970,23 +1981,39 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
else {
final PsiElement declaration = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, expression);
assert declaration != null : "No declaration found for " + expression.getText();
final CallableMethod accessor;
if (declaration instanceof PsiMethod) {
accessor = typeMapper.mapToCallableMethod((PsiMethod) declaration);
}
else if (declaration instanceof JetNamedFunction) {
accessor = typeMapper.mapToCallableMethod((JetNamedFunction) declaration, null);
CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION);
boolean isGetter = accessor.getSignature().getName().equals("get");
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION);
ResolvedCall<FunctionDescriptor> resolvedGetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
FunctionDescriptor getterDescriptor = resolvedGetCall == null ? null : resolvedGetCall.getResultingDescriptor();
CallableMethod getter = resolvedGetCall == null ? null : typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION);
Type asmType;
Type[] argumentTypes = accessor.getSignature().getArgumentTypes();
int index = 0;
if(isGetter) {
if(getterDescriptor.getReceiverParameter().exists()) {
index++;
}
asmType = accessor.getSignature().getReturnType();
}
else {
throw new UnsupportedOperationException("unknown accessor type: " + declaration);
if(setterDescriptor.getReceiverParameter().exists()) {
index++;
}
asmType = argumentTypes[argumentTypes.length-1];
}
boolean isGetter = accessor.getSignature().getName().equals("get");
return StackValue.collectionElement(
isGetter ? accessor.getSignature().getReturnType() : accessor.getSignature().getArgumentTypes()[1],
isGetter ? accessor : null,
isGetter ? null : accessor);
for (JetExpression jetExpression : expression.getIndexExpressions()) {
gen(jetExpression, argumentTypes[index]);
index++;
}
return StackValue.collectionElement(asmType, getter, setter, myFrameMap);
}
}
@@ -2030,13 +2057,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
private void generateArrayIndex(JetArrayAccessExpression expression) {
final List<JetExpression> indices = expression.getIndexExpressions();
for (JetExpression index : indices) {
gen(index, Type.INT_TYPE);
}
}
@Override
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT);
@@ -2079,21 +2099,21 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter());
assert descriptor != null;
Type descriptorType = typeMapper.mapType(descriptor.getOutType());
myMap.enter(descriptor, 1);
myFrameMap.enter(descriptor, 1);
int index = lookupLocal(descriptor);
v.store(index, descriptorType);
gen(clause.getCatchBody(), Type.VOID_TYPE);
v.goTo(end); // TODO don't generate goto if there's no code following try/catch
myMap.leave(descriptor);
myFrameMap.leave(descriptor);
v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
}
if (finallyBlock != null) {
Label finallyStart = new Label();
v.mark(finallyStart);
int index = myMap.enterTemp();
int index = myFrameMap.enterTemp();
v.store(index, THROWABLE_TYPE);
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
@@ -2101,7 +2121,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(index, THROWABLE_TYPE);
v.athrow();
myMap.leaveTemp();
myFrameMap.leaveTemp();
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
}
@@ -2156,7 +2176,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (pattern instanceof JetTypePattern) {
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
expressionToMatch.dupReceiver(v, 0);
expressionToMatch.dupReceiver(v);
generateInstanceOf(expressionToMatch, jetType, false);
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
return negated ? StackValue.not(value) : value;
@@ -2166,7 +2186,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else if (pattern instanceof JetExpressionPattern) {
final Type subjectType = expressionToMatch.type;
expressionToMatch.dupReceiver(v, 0);
expressionToMatch.dupReceiver(v);
expressionToMatch.put(subjectType, v);
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE;
@@ -2181,10 +2201,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null;
final Type varType = typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, varType.getSize());
expressionToMatch.dupReceiver(v, 0);
myFrameMap.enter(variableDescriptor, varType.getSize());
expressionToMatch.dupReceiver(v);
expressionToMatch.put(varType, v);
final int varIndex = myMap.getIndex(variableDescriptor);
final int varIndex = myFrameMap.getIndex(variableDescriptor);
v.store(varIndex, varType);
return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null);
}
@@ -2199,7 +2219,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label lblFail = new Label();
Label lblDone = new Label();
expressionToMatch.dupReceiver(v, 0);
expressionToMatch.dupReceiver(v);
expressionToMatch.put(OBJECT_TYPE, v);
v.dup();
final String tupleClassName = "jet/Tuple" + entries.size();
@@ -2381,7 +2401,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) {
JetExpression expr = expression.getSubjectExpression();
final Type subjectType = expressionType(expr);
final int subjectLocal = myMap.enterTemp(subjectType.getSize());
final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
gen(expr, subjectType);
v.store(subjectLocal, subjectType);
@@ -2393,7 +2413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(nextCondition);
}
nextCondition = new Label();
FrameMap.Mark mark = myMap.mark();
FrameMap.Mark mark = myFrameMap.mark();
Label thisEntry = new Label();
if (!whenEntry.isElse()) {
final JetWhenCondition[] conditions = whenEntry.getConditions();
@@ -2421,7 +2441,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
v.mark(end);
myMap.leaveTemp(subjectType.getSize());
myFrameMap.leaveTemp(subjectType.getSize());
return StackValue.onStack(expressionType(expression));
}
@@ -4,7 +4,10 @@ import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.*;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
@@ -20,10 +23,10 @@ import static org.objectweb.asm.Opcodes.*;
*/
public class FunctionCodegen {
private final ClassContext owner;
private final ClassVisitor v;
private final ClassBuilder v;
private final GenerationState state;
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) {
public FunctionCodegen(ClassContext owner, ClassBuilder v, GenerationState state) {
this.owner = owner;
this.v = v;
this.state = state;
@@ -39,13 +42,13 @@ public class FunctionCodegen {
ClassContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor);
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
}
private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature,
ClassContext context,
FunctionDescriptor functionDescriptor)
FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
@@ -62,7 +65,7 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
if (isAbstract) flags |= ACC_ABSTRACT;
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(fun, flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
if(kind != OwnerKind.TRAIT_IMPL) {
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
for(int i = 0; i != paramDescrs.size(); ++i) {
@@ -78,9 +81,10 @@ public class FunctionCodegen {
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
Type[] argTypes = jvmSignature.getArgumentTypes();
int add = functionDescriptor.getReceiverParameter().exists() ? state.getTypeMapper().mapType(functionDescriptor.getReceiverParameter().getType()).getSize() : 0;
for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i);
frameMap.enter(parameter, argTypes[i].getSize());
frameMap.enter(parameter, argTypes[i+add].getSize());
}
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -135,7 +139,7 @@ public class FunctionCodegen {
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind);
}
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
if(kind != OwnerKind.TRAIT_IMPL) {
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
@@ -146,7 +150,7 @@ public class FunctionCodegen {
}
}
static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
static void generateDefaultIfNeeded(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
DeclarationDescriptor contextClass = owner.getContextClass();
if(kind != OwnerKind.TRAIT_IMPL) {
@@ -187,7 +191,7 @@ public class FunctionCodegen {
String descriptor = jvmSignature.getDescriptor().replace(")","I)");
if(!isStatic)
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";");
final MethodVisitor mv = v.visitMethod(flags| ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
final MethodVisitor mv = v.newMethod(null, flags | ACC_STATIC, jvmSignature.getName() + "$default", descriptor, null, null);
InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode();
@@ -287,14 +291,14 @@ public class FunctionCodegen {
}
}
private static void checkOverride(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
private static void checkOverride(ClassContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
Type type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
if(!type1.equals(type2)) {
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal());
int flags = ACC_PUBLIC; // TODO.
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(null, flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
mv.visitCode();
Type[] argTypes = jvmSignature.getArgumentTypes();
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -18,7 +17,7 @@ public class FunctionOrClosureCodegen {
public final GenerationState state;
protected final ExpressionCodegen exprContext;
protected final ClassContext context;
protected ClassVisitor cv = null;
protected ClassBuilder cv = null;
public String name = null;
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
@@ -46,7 +45,7 @@ public class FunctionOrClosureCodegen {
final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName();
StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false);
cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
cv.newField(null, Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer);
@@ -15,8 +15,6 @@ import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.lang.types.JetStandardLibrary;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.commons.Method;
import java.util.Collections;
import java.util.List;
@@ -61,26 +59,21 @@ public class GenerationState {
return intrinsics;
}
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass() {
return new ClassCodegen(this);
}
public ClassVisitor forClassImplementation(ClassDescriptor aClass) {
public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class");
}
public ClassVisitor forTraitImplementation(ClassDescriptor aClass) {
public ClassBuilder forTraitImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class");
}
public Pair<String, ClassVisitor> forAnonymousSubclass(JetExpression expression) {
public Pair<String, ClassBuilder> forAnonymousSubclass(JetExpression expression) {
String className = typeMapper.classNameForAnonymousClass(expression);
ClassVisitor visitor = factory.forAnonymousSubclass(className);
return Pair.create(className, visitor);
return Pair.create(className, factory.forAnonymousSubclass(className));
}
public NamespaceCodegen forNamespace(JetNamespace namespace) {
@@ -123,7 +116,7 @@ public class GenerationState {
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst();
@@ -11,7 +11,10 @@ import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.*;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import org.objectweb.asm.commons.Method;
@@ -26,7 +29,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object";
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state);
}
@@ -89,21 +92,23 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
}
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0),
jvmName(),
null,
superClass,
interfaces.toArray(new String[interfaces.size()])
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
? Opcodes.ACC_INTERFACE
: 0),
jvmName(),
null,
superClass,
interfaces.toArray(new String[interfaces.size()])
);
v.visitSource(myClass.getContainingFile().getName(), null);
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
v.visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
v.getVisitor().visitOuterClass(state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION).getInternalName(), null, null);
}
if(myClass instanceof JetClass) {
AnnotationVisitor annotationVisitor = v.visitAnnotation("Ljet/typeinfo/JetSignature;", true);
AnnotationVisitor annotationVisitor = v.newAnnotation(myClass, "Ljet/typeinfo/JetSignature;", true);
annotationVisitor.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
annotationVisitor.visitEnd();
}
@@ -162,7 +167,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForObjectInstance() {
if (isNonLiteralObject()) {
Type type = JetTypeMapper.jetImplementationType(descriptor);
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
@@ -182,7 +187,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetClassObject classObject = getClassObject();
if (classObject != null) {
Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject));
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null);
v.newField(classObject, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$classobj", type.getDescriptor(), null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
@@ -242,7 +247,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(myClass, flags, "<init>", method.getDescriptor(), null, null);
mv.visitCode();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
@@ -312,7 +317,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String delegateField = "$delegate_" + n;
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
String fieldDesc = fieldType.getDescriptor();
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
v.newField(specifier, Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
@@ -328,7 +333,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0";
v.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
v.newField(myClass, Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, fieldName, interfaceDesc, null, null);
iv.load(0, classType);
iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc);
@@ -393,7 +398,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal());
final MethodVisitor mv = v.visitMethod(flags, function.getName(), function.getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(myClass, flags, function.getName(), function.getDescriptor(), null, null);
mv.visitCode();
codegen.generateThisOrOuter(descriptor);
@@ -475,7 +480,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";";
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
v.newField(declaration, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@Override
@@ -533,7 +538,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getSignature().getDescriptor(), null, null);
final MethodVisitor mv = v.newMethod(constructor, flags, "<init>", method.getSignature().getDescriptor(), null, null);
mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
@@ -677,9 +682,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
}
}
}
@@ -703,9 +708,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JetType defaultType = descriptor.getDefaultType();
if(CodegenUtil.hasTypeInfoField(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
v.newField(myClass, Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -715,7 +720,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0);
mv.visitEnd();
mv = v.visitMethod(Opcodes.ACC_PROTECTED|Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
mv = v.newMethod(myClass, Opcodes.ACC_PROTECTED | Opcodes.ACC_FINAL, "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V", null, null);
mv.visitCode();
iv = new InstructionAdapter(mv);
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -734,7 +739,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void genGetStaticGetTypeInfoMethod() {
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -745,7 +750,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void staticTypeInfoField() {
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
v.newField(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
@@ -776,11 +781,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC,
"$$getSuperTypesTypeInfo",
sig,
null /* TODO */,
null);
final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"$$getSuperTypesTypeInfo",
sig,
null /* TODO */,
null);
mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv);
@@ -547,6 +547,9 @@ public class JetTypeMapper {
}
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
if(functionDescriptor == null)
return null;
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind);
@@ -9,10 +9,14 @@ import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.objectweb.asm.*;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*;
@@ -20,20 +24,20 @@ import static org.objectweb.asm.Opcodes.*;
* @author max
*/
public class NamespaceCodegen {
private final ClassVisitor v;
private final ClassBuilder v;
private final GenerationState state;
public NamespaceCodegen(ClassVisitor v, String fqName, GenerationState state, PsiFile sourceFile) {
public NamespaceCodegen(ClassBuilder v, String fqName, GenerationState state, PsiFile sourceFile) {
this.v = v;
this.state = state;
v.visit(V1_6,
ACC_PUBLIC,
getJVMClassName(fqName),
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
v.defineClass(V1_6,
ACC_PUBLIC,
getJVMClassName(fqName),
null,
//"jet/lang/Namespace",
"java/lang/Object",
new String[0]
);
// TODO figure something out for a namespace that spans multiple files
v.visitSource(sourceFile.getName(), null);
@@ -76,8 +80,8 @@ public class NamespaceCodegen {
}
private void generateStaticInitializers(JetNamespace namespace) {
MethodVisitor mv = v.visitMethod(ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null);
MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null);
mv.visitCode();
FrameMap frameMap = new FrameMap();
@@ -104,9 +108,9 @@ public class NamespaceCodegen {
String jvmClassName = getJVMClassName(namespace.getName());
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
String fieldName = "$typeInfoCache$" + e.getValue();
v.visitField(ACC_PRIVATE|ACC_STATIC|ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null);
v.newField(null, ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, fieldName, "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mmv = v.visitMethod(ACC_PUBLIC|ACC_STATIC|ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mmv = v.newMethod(null, ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, "$getCachedTypeInfo$" + e.getValue(), "()Ljet/typeinfo/TypeInfo;", null, null);
InstructionAdapter v = new InstructionAdapter(mmv);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP);
@@ -185,7 +189,7 @@ public class NamespaceCodegen {
}
public void done() {
v.visitEnd();
v.done();
}
public static String getJVMClassName(String fqName) {
@@ -2,12 +2,14 @@ package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
@@ -19,10 +21,10 @@ import org.objectweb.asm.commons.InstructionAdapter;
public class PropertyCodegen {
private final GenerationState state;
private final FunctionCodegen functionCodegen;
private final ClassVisitor v;
private final ClassBuilder v;
private final OwnerKind kind;
public PropertyCodegen(ClassContext context, ClassVisitor v, FunctionCodegen functionCodegen, GenerationState state) {
public PropertyCodegen(ClassContext context, ClassBuilder v, FunctionCodegen functionCodegen, GenerationState state) {
this.v = v;
this.functionCodegen = functionCodegen;
this.state = state;
@@ -41,9 +43,9 @@ public class PropertyCodegen {
generateSetter(p, propertyDescriptor);
}
else if (kind instanceof OwnerKind.DelegateKind) {
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) {
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
}
}
}
@@ -71,7 +73,7 @@ public class PropertyCodegen {
else {
modifiers = Opcodes.ACC_PRIVATE;
}
v.visitField(modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
v.newField(p, modifiers, p.getName(), state.getTypeMapper().mapType(propertyDescriptor.getOutType()).getDescriptor(), null, value);
}
}
@@ -114,10 +116,10 @@ public class PropertyCodegen {
private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultGetter(propertyDescriptor, flags);
generateDefaultGetter(propertyDescriptor, flags, p);
}
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags) {
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -129,7 +131,7 @@ public class PropertyCodegen {
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -156,10 +158,10 @@ public class PropertyCodegen {
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC);
generateDefaultSetter(propertyDescriptor, flags);
generateDefaultSetter(propertyDescriptor, flags, p);
}
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags) {
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -170,7 +172,7 @@ public class PropertyCodegen {
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv);
@@ -38,7 +38,7 @@ public abstract class StackValue {
throw new UnsupportedOperationException("cannot store to value " + this);
}
public void dupReceiver(InstructionAdapter v, int below) {
public void dupReceiver(InstructionAdapter v) {
}
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
@@ -84,8 +84,8 @@ public abstract class StackValue {
return new ArrayElement(type, unbox);
}
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) {
return new CollectionElement(type, getter, setter);
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
return new CollectionElement(type, getter, setter, frame);
}
public static StackValue field(Type type, String owner, String name, boolean isStatic) {
@@ -456,24 +456,21 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
if (below == 1) {
v.dup2X1();
}
else {
v.dup2(); // array and index
}
public void dupReceiver(InstructionAdapter v) {
v.dup2(); // array and index
}
}
private static class CollectionElement extends StackValue {
private final CallableMethod getter;
private final CallableMethod setter;
private final FrameMap frame;
public CollectionElement(Type type, CallableMethod getter, CallableMethod setter) {
public CollectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
super(type);
this.getter = getter;
this.setter = setter;
this.frame = frame;
}
@Override
@@ -494,13 +491,70 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
if (below == 1) {
v.dup2X1();
}
else {
public void dupReceiver(InstructionAdapter v) {
int size = calcSize();
if(size == 2) {
v.dup2(); // collection and index
}
else {
Method signature = getter.getSignature();
Type[] argumentTypes = signature.getArgumentTypes();
int firstIndex = frame.enterTemp();
int lastIndex = firstIndex;
frame.leaveTemp();
for(int i = argumentTypes.length-1; i >= 0; i--) {
int sz = argumentTypes[i].getSize();
frame.enterTemp(sz);
lastIndex += sz;
v.store(lastIndex-sz, argumentTypes[i]);
}
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
frame.enterTemp();
lastIndex++;
v.store(lastIndex-1, JetTypeMapper.TYPE_OBJECT);
}
firstIndex = lastIndex;
int curIndex = lastIndex;
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT);
curIndex--;
}
for(int i = 0; i != argumentTypes.length; i++) {
int sz = argumentTypes[i].getSize();
v.load(curIndex-sz, argumentTypes[i]);
curIndex -= sz;
}
curIndex = firstIndex;
if(getter.getInvokeOpcode() != Opcodes.INVOKESTATIC) {
v.load(curIndex-1, JetTypeMapper.TYPE_OBJECT);
curIndex--;
}
for(int i = 0; i != argumentTypes.length; i++) {
int sz = argumentTypes[i].getSize();
v.load(curIndex-sz, argumentTypes[i]);
curIndex -= sz;
}
frame.leaveTemp(size);
}
}
private int calcSize() {
assert getter != null;
int size = getter.getInvokeOpcode() == Opcodes.INVOKESTATIC ? 0 : 1;
Method signature = getter.getSignature();
Type[] argumentTypes = signature.getArgumentTypes();
for(int i = 0; i != argumentTypes.length; ++i)
size += argumentTypes[i].getSize();
return size;
}
}
@@ -523,14 +577,9 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
public void dupReceiver(InstructionAdapter v) {
if (!isStatic) {
if (below == 1) {
v.dupX1();
}
else {
v.dup();
}
v.dup();
}
}
@@ -557,7 +606,7 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
public void dupReceiver(InstructionAdapter v) {
}
@Override
@@ -607,14 +656,9 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
public void dupReceiver(InstructionAdapter v) {
if (!isStatic) {
if (below == 1) {
v.dupX1();
}
else {
v.dup();
}
v.dup();
}
}
}
@@ -716,13 +760,8 @@ public abstract class StackValue {
}
@Override
public void dupReceiver(InstructionAdapter v, int below) {
if (below == 1) {
v.dupX1();
}
else {
v.dup();
}
public void dupReceiver(InstructionAdapter v) {
v.dup();
}
@Override
@@ -7,15 +7,12 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
public class TraitImplBodyCodegen extends ClassBodyCodegen {
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
public TraitImplBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassBuilder v, GenerationState state) {
super(aClass, context, v, state);
}
@@ -48,12 +45,12 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration() {
v.visit(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
jvmName(),
null,
"java/lang/Object",
new String[0]
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
jvmName(),
null,
"java/lang/Object",
new String[0]
);
v.visitSource(myClass.getContainingFile().getName(), null);
}
@@ -32,7 +32,7 @@ public class Increment implements IntrinsicMethod {
}
}
StackValue value = codegen.genQualified(receiver, operand);
value.dupReceiver(v, 0);
value. dupReceiver(v);
value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta);
@@ -0,0 +1,311 @@
package org.jetbrains.jet.compiler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import jet.modules.IModuleBuilder;
import jet.modules.IModuleSetBuilder;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GeneratedClassLoader;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.plugin.JetMainDetector;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.jar.*;
/**
* The environment for compiling a bunch of source files or
*
* @author yole
*/
public class CompileEnvironment {
private JetCoreEnvironment myEnvironment;
private final Disposable myRootDisposable;
private PrintStream myErrorStream = System.out;
public CompileEnvironment() {
myRootDisposable = new Disposable() {
@Override
public void dispose() {
}
};
myEnvironment = new JetCoreEnvironment(myRootDisposable);
}
public void setMyErrorStream(PrintStream errorStream) {
myErrorStream = errorStream;
}
public void dispose() {
Disposer.dispose(myRootDisposable);
}
public boolean initializeKotlinRuntime() {
final File unpackedRuntimePath = getUnpackedRuntimePath();
if (unpackedRuntimePath != null) {
myEnvironment.addToClasspath(unpackedRuntimePath);
}
else {
final File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null && runtimeJarPath.exists()) {
myEnvironment.addToClasspath(runtimeJarPath);
}
else {
return false;
}
}
return true;
}
public static File getUnpackedRuntimePath() {
URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("file")) {
return new File(url.getPath()).getParentFile().getParentFile();
}
return null;
}
public static File getRuntimeJarPath() {
URL url = CompileEnvironment.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("jar")) {
String path = url.getPath();
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
}
return null;
}
public void setJavaRuntime(File rtJarPath) {
myEnvironment.addToClasspath(rtJarPath);
}
public static File findActiveRtJar() {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if (systemClassLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) systemClassLoader;
for (URL url: loader.getURLs()) {
if("file".equals(url.getProtocol())) {
if(url.getFile().endsWith("/lib/rt.jar")) {
return new File(url.getFile());
}
if(url.getFile().endsWith("/Classes/classes.jar")) {
return new File(url.getFile()).getAbsoluteFile();
}
}
}
}
return null;
}
public void compileModuleScript(String moduleFile) {
final IModuleSetBuilder moduleSetBuilder = loadModuleScript(moduleFile);
if (moduleSetBuilder == null) {
return;
}
final String directory = new File(moduleFile).getParent();
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory);
writeToJar(moduleFactory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
}
}
public IModuleSetBuilder loadModuleScript(String moduleFile) {
CompileSession scriptCompileSession = new CompileSession(myEnvironment);
scriptCompileSession.addSources(moduleFile);
URL url = CompileEnvironment.class.getClassLoader().getResource("ModuleBuilder.kt");
if (url != null) {
String path = url.getPath();
if (path.startsWith("file:")) {
path = path.substring(5);
}
final VirtualFile vFile = myEnvironment.getJarFileSystem().findFileByPath(path);
if (vFile == null) {
throw new CompileEnvironmentException("Couldn't load ModuleBuilder.kt from runtime jar: "+ url);
}
scriptCompileSession.addSources(vFile);
}
else {
// building from source
final String homeDirectory = getHomeDirectory();
final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt");
scriptCompileSession.addSources(myEnvironment.getLocalFileSystem().findFileByPath(file.getPath()));
}
if (!scriptCompileSession.analyze(myErrorStream)) {
return null;
}
final ClassFileFactory factory = scriptCompileSession.generate();
return runDefineModules(moduleFile, factory);
}
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) {
GeneratedClassLoader loader = new GeneratedClassLoader(factory);
try {
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
Class namespaceClass = loader.loadClass("namespace");
final Method[] methods = namespaceClass.getMethods();
boolean modulesDefined = false;
for (Method method : methods) {
if (method.getName().equals("defineModules")) {
method.invoke(null, moduleSetBuilder);
modulesDefined = true;
break;
}
}
if (!modulesDefined) {
throw new CompileEnvironmentException("Module script " + moduleFile + " must define a defineModules() method");
}
return moduleSetBuilder;
} catch (Exception e) {
throw new CompileEnvironmentException(e);
}
}
public ClassFileFactory compileModule(IModuleBuilder moduleBuilder, String directory) {
CompileSession moduleCompileSession = new CompileSession(myEnvironment);
for (String sourceFile : moduleBuilder.getSourceFiles()) {
moduleCompileSession.addSources(new File(directory, sourceFile).getPath());
}
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
myEnvironment.addToClasspath(new File(classpathRoot));
}
if (!moduleCompileSession.analyze(myErrorStream)) {
return null;
}
return moduleCompileSession.generate();
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(CompileEnvironment.class, "/org/jetbrains/jet/compiler/CompileEnvironment.class")).getParentFile().getParentFile().getParent();
}
public static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) {
try {
Manifest manifest = new Manifest();
final Attributes mainAttributes = manifest.getMainAttributes();
mainAttributes.putValue("Manifest-Version", "1.0");
mainAttributes.putValue("Created-By", "JetBrains Kotlin");
if (mainClass != null) {
mainAttributes.putValue("Main-Class", mainClass);
}
FileOutputStream fos = new FileOutputStream(jar);
JarOutputStream stream = new JarOutputStream(fos, manifest);
try {
for (String file : factory.files()) {
stream.putNextEntry(new JarEntry(file));
stream.write(factory.asBytes(file));
}
if (includeRuntime) {
writeRuntimeToJar(stream);
}
}
finally {
stream.close();
fos.close();
}
} catch (IOException e) {
throw new CompileEnvironmentException("Failed to generate jar file", e);
}
}
private static void writeRuntimeToJar(final JarOutputStream stream) throws IOException {
final File unpackedRuntimePath = getUnpackedRuntimePath();
if (unpackedRuntimePath != null) {
FileUtil.processFilesRecursively(unpackedRuntimePath, new Processor<File>() {
@Override
public boolean process(File file) {
if (file.isDirectory()) return true;
final String relativePath = FileUtil.getRelativePath(unpackedRuntimePath, file);
try {
stream.putNextEntry(new JarEntry(FileUtil.toSystemIndependentName(relativePath)));
FileInputStream fis = new FileInputStream(file);
try {
FileUtil.copy(fis, stream);
} finally {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}
});
}
else {
File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null) {
JarInputStream jis = new JarInputStream(new FileInputStream(runtimeJarPath));
try {
while (true) {
JarEntry e = jis.getNextJarEntry();
if (e == null) {
break;
}
if (FileUtil.getExtension(e.getName()).equals("class")) {
stream.putNextEntry(e);
FileUtil.copy(jis, stream);
}
}
} finally {
jis.close();
}
}
else {
throw new CompileEnvironmentException("Couldn't find runtime library");
}
}
}
public void compileBunchOfSources(String sourceFileOrDir, String jar, String outputDir) {
CompileSession session = new CompileSession(myEnvironment);
session.addSources(sourceFileOrDir);
String mainClass = null;
for (JetNamespace namespace : session.getSourceFileNamespaces()) {
if (JetMainDetector.hasMain(namespace.getDeclarations())) {
mainClass = namespace.getFQName() + ".namespace";
break;
}
}
if (!session.analyze(myErrorStream)) {
return;
}
ClassFileFactory factory = session.generate();
if (jar != null) {
writeToJar(factory, jar, mainClass, true);
}
else if (outputDir != null) {
writeToOutputDirectory(factory, outputDir);
}
else {
throw new CompileEnvironmentException("Output directory or jar file is not specified - no files will be saved to the disk");
}
}
private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) {
List<String> files = factory.files();
for (String file : files) {
File target = new File(outputDir, file);
try {
FileUtil.writeToFile(target, factory.asBytes(file));
} catch (IOException e) {
throw new CompileEnvironmentException(e);
}
}
}
}
@@ -0,0 +1,18 @@
package org.jetbrains.jet.compiler;
/**
* @author yole
*/
public class CompileEnvironmentException extends RuntimeException {
public CompileEnvironmentException(String message) {
super(message);
}
public CompileEnvironmentException(Throwable cause) {
super(cause);
}
public CompileEnvironmentException(String message, Throwable cause) {
super(message, cause);
}
}
@@ -1,4 +1,4 @@
package org.jetbrains.jet.cli;
package org.jetbrains.jet.compiler;
import com.google.common.base.Predicates;
import com.intellij.openapi.vfs.VirtualFile;
@@ -15,10 +15,13 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.plugin.JetFileType;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
/**
* The session which handles analyzing and compiling a single module.
*
* @author yole
*/
public class CompileSession {
@@ -73,10 +76,10 @@ public class CompileSession {
return mySourceFileNamespaces;
}
public boolean analyze() {
public boolean analyze(final PrintStream out) {
if (!myErrors.isEmpty()) {
for (String error : myErrors) {
System.out.println(error);
out.println(error);
}
return false;
}
@@ -85,7 +88,7 @@ public class CompileSession {
allNamespaces.addAll(myLibrarySourceFileNamespaces);
myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY);
ErrorCollector errorCollector = new ErrorCollector(myBindingContext);
errorCollector.report();
errorCollector.report(out);
return !errorCollector.hasErrors;
}
@@ -1,4 +1,4 @@
package org.jetbrains.jet.cli;
package org.jetbrains.jet.compiler;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.resolve.BindingContext;
import java.io.PrintStream;
import java.util.Collection;
/**
@@ -36,14 +37,14 @@ class ErrorCollector {
}
}
void report() {
void report(final PrintStream out) {
if(!maps.isEmpty()) {
for (PsiFile psiFile : maps.keySet()) {
System.out.println(psiFile.getVirtualFile().getPath());
out.println(psiFile.getVirtualFile().getPath());
Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile);
for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) {
String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange);
System.out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage());
out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage());
}
}
}
@@ -1,29 +1,11 @@
package org.jetbrains.jet.cli;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import jet.modules.IModuleBuilder;
import jet.modules.IModuleSetBuilder;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GeneratedClassLoader;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.plugin.JetMainDetector;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.compiler.CompileEnvironmentException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.jar.*;
/**
* @author yole
@@ -54,273 +36,35 @@ public class KotlinCompiler {
return;
}
Disposable root = new Disposable() {
@Override
public void dispose() {
}
};
JetCoreEnvironment environment = new JetCoreEnvironment(root);
CompileEnvironment environment = new CompileEnvironment();
File rtJar = initJdk();
if (rtJar == null) return;
environment.addToClasspath(rtJar);
final File unpackedRuntimePath = getUnpackedRuntimePath();
if (unpackedRuntimePath != null) {
environment.addToClasspath(unpackedRuntimePath);
}
else {
final File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null && runtimeJarPath.exists()) {
environment.addToClasspath(runtimeJarPath);
}
else {
try {
environment.setJavaRuntime(rtJar);
if (!environment.initializeKotlinRuntime()) {
System.out.println("No runtime library found");
return;
}
}
if (arguments.module != null) {
compileModuleScript(environment, arguments.module);
return;
}
CompileSession session = new CompileSession(environment);
session.addSources(arguments.src);
String mainClass = null;
for (JetNamespace namespace : session.getSourceFileNamespaces()) {
if (JetMainDetector.hasMain(namespace.getDeclarations())) {
mainClass = namespace.getFQName() + ".namespace";
break;
}
}
if (!session.analyze()) {
return;
}
ClassFileFactory factory = session.generate();
if (arguments.jar != null) {
writeToJar(factory, arguments.jar, mainClass, true);
}
else if (arguments.outputDir != null) {
writeToOutputDirectory(factory, arguments.outputDir);
}
else {
System.out.println("Output directory or jar file is not specified - no files will be saved to the disk");
}
}
private static void compileModuleScript(JetCoreEnvironment environment, String moduleFile) {
CompileSession scriptCompileSession = new CompileSession(environment);
scriptCompileSession.addSources(moduleFile);
URL url = KotlinCompiler.class.getClassLoader().getResource("ModuleBuilder.kt");
if (url != null) {
String path = url.getPath();
if (path.startsWith("file:")) {
path = path.substring(5);
}
final VirtualFile vFile = environment.getJarFileSystem().findFileByPath(path);
if (vFile == null) {
System.out.println("Couldn't load ModuleBuilder.kt from runtime jar: "+ url);
if (arguments.module != null) {
environment.compileModuleScript(arguments.module);
return;
}
scriptCompileSession.addSources(vFile);
}
else {
// building from source
final String homeDirectory = getHomeDirectory();
final File file = new File(homeDirectory, "stdlib/ktSrc/ModuleBuilder.kt");
scriptCompileSession.addSources(environment.getLocalFileSystem().findFileByPath(file.getPath()));
}
if (!scriptCompileSession.analyze()) {
return;
}
final ClassFileFactory factory = scriptCompileSession.generate();
final IModuleSetBuilder moduleSetBuilder = runDefineModules(moduleFile, factory);
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
compileModule(environment, moduleBuilder, new File(moduleFile).getParent());
}
}
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) {
GeneratedClassLoader loader = new GeneratedClassLoader(factory);
try {
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
Class namespaceClass = loader.loadClass("namespace");
final Method[] methods = namespaceClass.getMethods();
boolean modulesDefined = false;
for (Method method : methods) {
if (method.getName().equals("defineModules")) {
method.invoke(null, moduleSetBuilder);
modulesDefined = true;
break;
}
}
if (!modulesDefined) {
System.out.println("Module script " + moduleFile + " must define a defineModules() method");
return null;
}
return moduleSetBuilder;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static void compileModule(JetCoreEnvironment environment, IModuleBuilder moduleBuilder, String directory) {
CompileSession moduleCompileSession = new CompileSession(environment);
for (String sourceFile : moduleBuilder.getSourceFiles()) {
moduleCompileSession.addSources(new File(directory, sourceFile).getPath());
}
for (String classpathRoot : moduleBuilder.getClasspathRoots()) {
environment.addToClasspath(new File(classpathRoot));
}
if (!moduleCompileSession.analyze()) {
return;
}
ClassFileFactory factory = moduleCompileSession.generate();
writeToJar(factory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
}
private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(KotlinCompiler.class, "/org/jetbrains/jet/cli/KotlinCompiler.class")).getParentFile().getParentFile().getParent();
}
private static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) {
try {
Manifest manifest = new Manifest();
final Attributes mainAttributes = manifest.getMainAttributes();
mainAttributes.putValue("Manifest-Version", "1.0");
mainAttributes.putValue("Created-By", "JetBrains Kotlin");
if (mainClass != null) {
mainAttributes.putValue("Main-Class", mainClass);
}
FileOutputStream fos = new FileOutputStream(jar);
JarOutputStream stream = new JarOutputStream(fos, manifest);
try {
for (String file : factory.files()) {
stream.putNextEntry(new JarEntry(file));
stream.write(factory.asBytes(file));
}
if (includeRuntime) {
writeRuntimeToJar(stream);
}
}
finally {
stream.close();
fos.close();
}
} catch (IOException e) {
System.out.println("Failed to generate jar file: " + e.getMessage());
}
}
private static File getUnpackedRuntimePath() {
URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("file")) {
return new File(url.getPath()).getParentFile().getParentFile();
}
return null;
}
private static File getRuntimeJarPath() {
URL url = KotlinCompiler.class.getClassLoader().getResource("jet/JetObject.class");
if (url != null && url.getProtocol().equals("jar")) {
String path = url.getPath();
return new File(path.substring(path.indexOf(":") + 1, path.indexOf("!/")));
}
return null;
}
private static void writeRuntimeToJar(final JarOutputStream stream) throws IOException {
final File unpackedRuntimePath = getUnpackedRuntimePath();
if (unpackedRuntimePath != null) {
FileUtil.processFilesRecursively(unpackedRuntimePath, new Processor<File>() {
@Override
public boolean process(File file) {
if (file.isDirectory()) return true;
final String relativePath = FileUtil.getRelativePath(unpackedRuntimePath, file);
try {
stream.putNextEntry(new JarEntry(FileUtil.toSystemIndependentName(relativePath)));
FileInputStream fis = new FileInputStream(file);
try {
FileUtil.copy(fis, stream);
} finally {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return true;
}
});
}
else {
File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null) {
JarInputStream jis = new JarInputStream(new FileInputStream(runtimeJarPath));
try {
while (true) {
JarEntry e = jis.getNextJarEntry();
if (e == null) {
break;
}
if (FileUtil.getExtension(e.getName()).equals("class")) {
stream.putNextEntry(e);
FileUtil.copy(jis, stream);
}
}
} finally {
jis.close();
}
}
else {
System.out.println("Couldn't find runtime library");
}
}
}
private static void writeToOutputDirectory(ClassFileFactory factory, final String outputDir) {
List<String> files = factory.files();
for (String file : files) {
File target = new File(outputDir, file);
try {
FileUtil.writeToFile(target, factory.asBytes(file));
System.out.println("Generated classfile: " + target);
} catch (IOException e) {
System.out.println(e.getMessage());
environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir);
}
} catch (CompileEnvironmentException e) {
System.out.println(e.getMessage());
}
}
private static File initJdk() {
String javaHome = System.getenv("JAVA_HOME");
File rtJar = null;
File rtJar;
if (javaHome == null) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if(systemClassLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) systemClassLoader;
for(URL url: loader.getURLs()) {
if("file".equals(url.getProtocol())) {
if(url.getFile().endsWith("/lib/rt.jar")) {
rtJar = new File(url.getFile());
break;
}
if(url.getFile().endsWith("/Classes/classes.jar")) {
rtJar = new File(url.getFile()).getAbsoluteFile();
break;
}
}
}
}
rtJar = CompileEnvironment.findActiveRtJar();
if(rtJar == null) {
System.out.println("JAVA_HOME environment variable needs to be defined");
@@ -13,8 +13,6 @@ public class JavaDefaultImports {
public static final ImportingStrategy JAVA_DEFAULT_IMPORTS = new ImportingStrategy() {
@Override
public void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope) {
// scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("").getMemberScope());
// scope.importScope(javaSemanticServices.getDescriptorResolver().resolveNamespace("java.lang").getMemberScope());
JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, trace);
rootScope.importScope(new JavaPackageScope("", null, javaSemanticServices));
rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
@@ -83,4 +83,13 @@ public class FunctionDescriptorUtil {
return parameterScope;
}
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType) {
assert JetStandardClasses.isFunctionType(functionType);
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
ReceiverDescriptor.NO_RECEIVER,
Collections.<TypeParameterDescriptor>emptyList(),
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
JetStandardClasses.getReturnType(functionType),
Modality.FINAL, Visibility.LOCAL);
}
}
@@ -2,8 +2,6 @@ package org.jetbrains.jet.lang.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collections;
@@ -15,9 +13,8 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
JetType outType = variableDescriptor.getOutType();
assert outType != null;
assert JetStandardClasses.isFunctionType(outType);
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
result.initialize(JetStandardClasses.getReceiverType(outType), ReceiverDescriptor.NO_RECEIVER, Collections.<TypeParameterDescriptor>emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL, Visibility.LOCAL);
FunctionDescriptorUtil.initializeFromFunctionType(result, outType);
return result;
}
@@ -25,7 +22,6 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
// super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
this.variableDescriptor = variableDescriptor;
}
@@ -207,6 +207,7 @@ public interface Errors {
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Method 'iterator()' is ambiguous for this expression: {0}");
ParameterizedDiagnosticFactory1<JetType> COMPARE_TO_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "compareTo() must return Int, but returns {0}");
ParameterizedDiagnosticFactory1<JetType> CALLEE_NOT_A_FUNCTION = ParameterizedDiagnosticFactory1.create(ERROR, "Expecting a function type, but found {0}");
SimpleDiagnosticFactory RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = SimpleDiagnosticFactory.create(ERROR, "Returns are not allowed for functions with expression body. Use block body in '{...}'");
SimpleDiagnosticFactory NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = SimpleDiagnosticFactory.create(ERROR, "A 'return' expression required in a function with a block body ('{...}')");
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Maps;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
@@ -23,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author abreslav
@@ -82,14 +84,17 @@ public class AnalyzingUtils {
TopDownAnalyzer.process(semanticServices, bindingTraceContext, scope, new NamespaceLike.Adapter(owner) {
private Map<String, NamespaceDescriptorImpl> declaredNamespaces = Maps.newHashMap();
@Override
public NamespaceDescriptorImpl getNamespace(String name) {
return null;
return declaredNamespaces.get(name);
}
@Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
scope.addNamespace(namespaceDescriptor);
declaredNamespaces.put(namespaceDescriptor.getName(), (NamespaceDescriptorImpl) namespaceDescriptor);
}
@Override
@@ -36,8 +36,8 @@ public interface BindingContext {
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT");
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_NEXT = Slices.createSimpleSlice("LOOP_RANGE_NEXT");
WritableSlice<JetExpression, FunctionDescriptor> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET");
WritableSlice<JetExpression, FunctionDescriptor> INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET");
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET");
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET");
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST");
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE");
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
@@ -78,7 +79,7 @@ public class CallResolver {
}
@Nullable
public FunctionDescriptor resolveCallWithGivenName(
public ResolvedCall<FunctionDescriptor> resolveCallWithGivenName(
@NotNull BindingTrace trace,
@NotNull JetScope scope,
@NotNull final Call call,
@@ -86,7 +87,7 @@ public class CallResolver {
@NotNull String name,
@NotNull JetType expectedType) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo);
return resolveCallToDescriptor(trace, scope, call, expectedType, tasks, functionReference);
return doResolveCall(trace, scope, call, expectedType, tasks, functionReference);
}
@Nullable
@@ -173,8 +174,30 @@ public class CallResolver {
}
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY));
}
else if (calleeExpression != null) {
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
ExpressionTypingServices typingServices = new ExpressionTypingServices(semanticServices, trace);
JetType calleeType = typingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE);// We are actually expecting a function, but there seems to be no easy way of expressing this
if (!JetStandardClasses.isFunctionType(calleeType)) {
checkTypesWithNoCallee(trace, scope, call);
if (!ErrorUtils.isErrorType(calleeType)) {
trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
}
return null;
}
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "for expression " + calleeExpression.getText());
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
Collections.singleton(resolvedCall), call, dataFlowInfo));
functionReference = new JetReferenceExpression(calleeExpression.getNode()) {
};
}
else {
throw new UnsupportedOperationException("Type argument inference not implemented for " + call);
checkTypesWithNoCallee(trace, scope, call);
return null;
}
}
@@ -232,7 +255,15 @@ public class CallResolver {
@Override
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
trace.report(NO_VALUE_FOR_PARAMETER.on(reference, valueParameter));
PsiElement reportOn;
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
if (valueArgumentList != null) {
reportOn = valueArgumentList;
}
else {
reportOn = reference;
}
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
}
@Override
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.*;
@@ -559,11 +560,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
ExpressionReceiver receiver = getExpressionReceiver(facade, baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
if (receiver == null) return null;
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
CallMaker.makeCall(receiver, expression),
expression.getOperationSign(),
name,
receiver);
name);
if (functionDescriptor == null) return null;
JetType returnType = functionDescriptor.getReturnType();
@@ -705,10 +705,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
String name = "contains";
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE));
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
operationSign,
name, receiver);
name);
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
ensureBooleanResult(operationSign, name, containsType, context);
}
@@ -752,14 +752,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope));
if (receiver != null) {
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
ResolvedCall<FunctionDescriptor> resolvedCall = context.resolveCallWithGivenName(
CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()),
expression,
"get",
receiver);
if (functionDescriptor != null) {
context.trace.record(INDEXED_LVALUE_GET, expression, functionDescriptor);
return DataFlowUtils.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
"get"
);
if (resolvedCall != null) {
context.trace.record(INDEXED_LVALUE_GET, expression, resolvedCall);
return DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType);
}
}
return null;
@@ -768,11 +768,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Nullable
protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenName(
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
CallMaker.makeCall(receiver, binaryExpression),
binaryExpression.getOperationReference(),
name,
receiver);
name
);
if (functionDescriptor != null) {
return functionDescriptor.getReturnType();
}
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
@@ -172,10 +173,16 @@ import java.util.Map;
////////// Call resolution utilities
@Nullable
public FunctionDescriptor resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name, @NotNull ReceiverDescriptor receiver) {
public ResolvedCall<FunctionDescriptor> resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) {
return getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType);
}
@Nullable
public FunctionDescriptor resolveCallWithGivenNameToDescriptor(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) {
ResolvedCall<FunctionDescriptor> resolvedCall = resolveCallWithGivenName(call, functionReference, name);
return resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
}
@Nullable
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
return getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType);
@@ -9,17 +9,17 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lexer.JetTokens;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET;
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver;
/**
@@ -109,7 +109,8 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
@Override
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
// If there's += (or similar op) defined as such, we just call it.
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
@@ -119,13 +120,13 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
if (assignmentOperationType == null) {
String counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), operationSign, context);
}
JetType typeForBinaryCall = getTypeForBinaryCall(scope, counterpartName, context, expression);
if (typeForBinaryCall != null) {
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
if (left instanceof JetArrayAccessExpression) {
resolveArrayAccessToLValue((JetArrayAccessExpression) left, expression.getRight(), expression.getOperationReference(), context, true);
}
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
}
@@ -138,14 +139,14 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
@Override
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
boolean getterNeeded = false;
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
JetExpression right = expression.getRight();
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context, getterNeeded);
return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context);
}
JetType leftType = facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope));
JetType leftType = left == null ? ErrorUtils.createErrorType("No expression")
: facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope));
if (right != null) {
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
}
@@ -164,30 +165,32 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
return checkExpectedType(expression, context);
}
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context, boolean getterNeeded) {
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
if (receiver == null) return null;
Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide);
FunctionDescriptor setFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
ResolvedCall<FunctionDescriptor> setFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
call,
arrayAccessExpression,
"set", receiver);
if (setFunction == null) return null;
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunction);
"set");
if (setFunctionCall == null) return null;
FunctionDescriptor setFunctionDescriptor = setFunctionCall.getResultingDescriptor();
if (getterNeeded) {
FunctionDescriptor getFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
arrayAccessExpression,
"get", receiver);
if (getFunction == null) return null;
context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunction);
}
else {
context.trace.record(REFERENCE_TARGET, operationSign, setFunction);
}
return DataFlowUtils.checkType(setFunction.getReturnType(), arrayAccessExpression, context);
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionCall);
// if (getterNeeded) {
// ResolvedCall<FunctionDescriptor> getFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
// CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
// arrayAccessExpression,
// "get");
// if (getFunctionCall == null) return null;
// context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionCall);
// }
// else {
// context.trace.record(REFERENCE_TARGET, operationSign, setFunctionDescriptor);
// }
return DataFlowUtils.checkType(setFunctionDescriptor.getReturnType(), arrayAccessExpression, context);
}
@Override
@@ -16,6 +16,6 @@ class C : T {
super.foo() // OK
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
super.buzz() // OK, resolved to a member
super.<!NO_VALUE_FOR_PARAMETER!>buzz1<!>() // Resolved to a member, but error: no parameter passed where required
super.buzz1<!NO_VALUE_FOR_PARAMETER!>()<!> // Resolved to a member, but error: no parameter passed where required
}
}
@@ -0,0 +1,50 @@
namespace foo
fun Any.foo() : fun() : Unit {
return {}
}
fun Any.foo1() : fun(i : Int) : Unit {
return {}
}
fun foo2() : fun(i : fun()) : Unit {
return {}
}
fun fooT1<T>(t : T) : fun() : T {
return {t}
}
fun fooT2<T>() : fun(t : T) : T {
return {it}
}
fun main(args : Array<String>) {
args.foo()()
args.foo1()<!NO_VALUE_FOR_PARAMETER!>()<!>
<!UNRESOLVED_REFERENCE!>a<!>.foo1()()
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
args.foo1()(1)
args.foo1()(<!TYPE_MISMATCH!>"1"<!>)
<!UNRESOLVED_REFERENCE!>a<!>.foo1()("1")
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
foo2()({})
foo2()<!TOO_MANY_ARGUMENTS!>{}<!>
(foo2()){}
(foo2())<!TYPE_MISMATCH!>{<!CANNOT_INFER_PARAMETER_TYPE!>x<!> => }<!>
foo2()(<!TYPE_MISMATCH!>{<!CANNOT_INFER_PARAMETER_TYPE!>x<!> => }<!>)
val a = fooT1(1)()
a : Int
val b = fooT2<Int>()(1)
b : Int
fooT2()(1) // : Any?
<!CALLEE_NOT_A_FUNCTION!>1<!>()
<!CALLEE_NOT_A_FUNCTION!>1<!>{}
<!CALLEE_NOT_A_FUNCTION!>1<!>(){}
}
@@ -14,10 +14,10 @@ fun test() {
foo(1, "", <!TOO_MANY_ARGUMENTS!>""<!>)
bar(z = "")
<!NO_VALUE_FOR_PARAMETER!>bar<!>()
<!NO_VALUE_FOR_PARAMETER!>bar<!>("")
bar<!NO_VALUE_FOR_PARAMETER!>()<!>
bar<!NO_VALUE_FOR_PARAMETER!>("")<!>
bar(1, 1, "")
bar(1, 1, "")
bar(1, <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>z<!> = "")
<!NO_VALUE_FOR_PARAMETER!>bar<!>(1, <!UNRESOLVED_REFERENCE, MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>zz<!> = "", <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!><!UNRESOLVED_REFERENCE!>zz<!>.foo<!>)
bar<!NO_VALUE_FOR_PARAMETER!>(1, <!UNRESOLVED_REFERENCE, MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>zz<!> = "", <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!><!UNRESOLVED_REFERENCE!>zz<!>.foo<!>)<!>
}
@@ -0,0 +1,6 @@
fun box () : String {
val s = java.util.ArrayList<String>()
s.add("foo")
s[0] += "bar"
return if(s[0] == "foobar") "OK" else "fail"
}
@@ -0,0 +1,4 @@
namespace Smoke
fun main(args: Array<String>) {
}
@@ -0,0 +1,8 @@
import kotlin.modules.ModuleSetBuilder
fun ModuleSetBuilder.defineModules() {
module("smoke") {
source files "Smoke.kt"
jar name System.getProperty("java.io.tmpdir") + "/smoke.jar"
}
}
@@ -96,4 +96,74 @@ public class ArrayGenTest extends CodegenTestCase {
Method foo = generateFunction();
foo.invoke(null);
}
public void testCollectionPlusAssign () throws Exception {
blackBoxFile("regressions/kt33.jet");
}
public void testArrayPlusAssign () throws Exception {
loadText("fun box() : Int { val s = IntArray(1); s [0] = 5; s[0] += 7; return s[0] }");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Integer)foo.invoke(null) == 12);
}
public void testCollectionAssignGetMultiIndex () throws Exception {
loadText("import java.util.ArrayList\n" +
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[2,-2] }\n" +
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("57"));
}
public void testArrayGetAssignMultiIndex () throws Exception {
loadText(
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; s[2, -2] += \"7\"; return s[-3,3] }\n" +
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("57"));
}
public void testCollectionGetMultiIndex () throws Exception {
loadText("import java.util.ArrayList\n" +
"fun box() : String { val s = ArrayList<String>(1); s.add(\"\"); s [1, -1] = \"5\"; return s[2, -2] }\n" +
"fun ArrayList<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun ArrayList<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem }\n");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("5"));
}
public void testArrayGetMultiIndex () throws Exception {
loadText(
"fun box() : String? { val s = Array<String>(1,{ \"\" }); s [1, -1] = \"5\"; return s[-2, 2] }\n" +
"fun Array<String>.get(index1: Int, index2 : Int) = this[index1+index2]\n" +
"fun Array<String>.set(index1: Int, index2 : Int, elem: String) { this[index1+index2] = elem\n }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue(foo.invoke(null).equals("5"));
}
public void testMap () throws Exception {
loadText(
"fun box() : Int? { val s = java.util.HashMap<String,Int?>(); s[\"239\"] = 239; return s[\"239\"] }\n" +
"fun java.util.HashMap<String,Int?>.set(index: String, elem: Int?) { this.put(index, elem) }");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue((Integer)foo.invoke(null) == 239);
}
public void testLongDouble () throws Exception {
loadText(
"fun box() : Int { var l = IntArray(1); l[0.lng] = 4; l[0.lng] += 6; return l[0.lng];}\n" +
"fun IntArray.set(index: Long, elem: Int) { this[index.int] = elem }\n" +
"fun IntArray.get(index: Long) = this[index.int]");
System.out.println(generateToText());
Method foo = generateFunction("box");
assertTrue((Integer)foo.invoke(null) == 10);
}
}
@@ -366,7 +366,7 @@ public class NamespaceGenTest extends CodegenTestCase {
}
public void testArrayAugAssignLong() throws Exception {
loadText("fun foo(c: LongArray) { c[0] *= 2 }");
loadText("fun foo(c: LongArray) { c[0] *= 2.lng }");
System.out.println(generateToText());
final Method main = generateFunction();
long[] data = new long[] { 5 };
@@ -0,0 +1,25 @@
package org.jetbrains.jet.compiler;
import jet.modules.IModuleBuilder;
import jet.modules.IModuleSetBuilder;
import junit.framework.TestCase;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.parsing.JetParsingTest;
/**
* @author yole
*/
public class CompileEnvironmentTest extends TestCase {
public void testSmoke() {
CompileEnvironment environment = new CompileEnvironment();
environment.setJavaRuntime(CompileEnvironment.findActiveRtJar());
environment.initializeKotlinRuntime();
final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/";
final IModuleSetBuilder setBuilder = environment.loadModuleScript(testDataDir + "Smoke.kts");
assertEquals(1, setBuilder.getModules().size());
final IModuleBuilder moduleBuilder = setBuilder.getModules().get(0);
final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir);
assertNotNull(factory);
assertNotNull(factory.asBytes("Smoke/namespace.class"));
}
}
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
import org.jetbrains.jet.lang.psi.JetContainerNode;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
@@ -40,8 +41,8 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
@Override
protected PsiElement doResolve() {
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
if (getFunction != null && setFunction != null) {
return null; // Call doMultiResolve
}
@@ -51,10 +52,10 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
@Override
protected ResolveResult[] doMultiResolve() {
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction);
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction);
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction.getResultingDescriptor());
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction.getResultingDescriptor());
return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)};
// return super.doMultiResolve();
}
+15 -1
View File
@@ -29,9 +29,16 @@ class ClasspathBuilder(val parent: ModuleBuilder) {
}
}
class JarBuilder(val parent: ModuleBuilder) {
fun name(jarName: String) {
parent.setJarName(jarName)
}
}
class ModuleBuilder(val name: String): IModuleBuilder {
val sourceFiles: ArrayList<String?> = ArrayList<String?>()
val classpathRoots: ArrayList<String?> = ArrayList<String?>()
var _jarName: String? = null
val source: SourcesBuilder
get() = SourcesBuilder(this)
@@ -39,6 +46,9 @@ class ModuleBuilder(val name: String): IModuleBuilder {
val classpath: ClasspathBuilder
get() = ClasspathBuilder(this)
val jar: JarBuilder
get() = JarBuilder(this)
fun addSourceFiles(pattern: String) {
sourceFiles.add(pattern)
}
@@ -47,9 +57,13 @@ class ModuleBuilder(val name: String): IModuleBuilder {
classpathRoots.add(name)
}
fun setJarName(name: String) {
_jarName = name
}
override fun getSourceFiles(): List<String?>? = sourceFiles
override fun getClasspathRoots(): List<String?>? = classpathRoots
override fun getModuleName(): String? = name
}
override fun getJarName(): String? = _jarName
}
+39
View File
@@ -0,0 +1,39 @@
namespace std
namespace io {
import java.io.*
fun print(message : Any?) { System.out?.print(message) }
fun print(message : Int) { System.out?.print(message) }
fun print(message : Long) { System.out?.print(message) }
fun print(message : Byte) { System.out?.print(message) }
fun print(message : Short) { System.out?.print(message) }
fun print(message : Char) { System.out?.print(message) }
fun print(message : Boolean) { System.out?.print(message) }
fun print(message : Float) { System.out?.print(message) }
fun print(message : Double) { System.out?.print(message) }
fun println(message : Any?) {
System.out?.println(message)
}
fun println(message : Int) { System.out?.println(message) }
fun println(message : Long) { System.out?.println(message) }
fun println(message : Byte) { System.out?.println(message) }
fun println(message : Short) { System.out?.println(message) }
fun println(message : Char) { System.out?.println(message) }
fun println(message : Boolean) { System.out?.println(message) }
fun println(message : Float) { System.out?.println(message) }
fun println(message : Double) { System.out?.println(message) }
private var systemIn : InputStream? = null // Unfortunately, System.in may change
private var stdin : BufferedReader? = null // This may introduce leaks of system.in objects...
fun readLine() : String? {
if (stdin == null || systemIn != System.`in`) {
stdin = java.io.BufferedReader(java.io.InputStreamReader(System.`in`))
systemIn = System.`in`
}
return stdin?.readLine()
}
}
@@ -9,4 +9,5 @@ public interface IModuleBuilder {
String getModuleName();
List<String> getSourceFiles();
List<String> getClasspathRoots();
String getJarName();
}