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 examples/.idea/workspace.xml
confluence/target confluence/target
confluence/target confluence/target
out
.idea/dictionaries/yozh.xml
.idea/codeStyleSettings.xml
.idea/workspace.xml
@@ -1,10 +1,10 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.InstructionAdapter; import org.objectweb.asm.commons.InstructionAdapter;
@@ -23,12 +23,12 @@ public abstract class ClassBodyCodegen {
protected final JetClassOrObject myClass; protected final JetClassOrObject myClass;
protected final OwnerKind kind; protected final OwnerKind kind;
protected final ClassDescriptor descriptor; protected final ClassDescriptor descriptor;
protected final ClassVisitor v; protected final ClassBuilder v;
protected final ClassContext context; protected final ClassContext context;
protected final List<CodeChunk> staticInitializerChunks = new ArrayList<CodeChunk>(); 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; this.state = state;
descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
myClass = aClass; myClass = aClass;
@@ -46,7 +46,7 @@ public abstract class ClassBodyCodegen {
generateStaticInitializer(); generateStaticInitializer();
v.visitEnd(); v.done();
} }
protected abstract void generateDeclaration(); protected abstract void generateDeclaration();
@@ -62,7 +62,7 @@ public abstract class ClassBodyCodegen {
generateDeclaration(propertyCodegen, declaration, functionCodegen); generateDeclaration(propertyCodegen, declaration, functionCodegen);
} }
generatePrimaryConstructorProperties(propertyCodegen); generatePrimaryConstructorProperties(propertyCodegen, myClass);
} }
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
@@ -82,20 +82,20 @@ public abstract class ClassBodyCodegen {
functionCodegen.gen(declaration); functionCodegen.gen(declaration);
} }
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) { private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, PsiElement origin) {
OwnerKind kind = context.getContextKind(); OwnerKind kind = context.getContextKind();
for (JetParameter p : getPrimaryConstructorParameters()) { for (JetParameter p : getPrimaryConstructorParameters()) {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, origin);
} }
//noinspection ConstantConditions //noinspection ConstantConditions
if (!(kind instanceof OwnerKind.DelegateKind) && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { 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() { private void generateStaticInitializer() {
if (staticInitializerChunks.size() > 0) { if (staticInitializerChunks.size() > 0) {
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, final MethodVisitor mv = v.newMethod(null, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); 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.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.objectweb.asm.ClassVisitor;
/** /**
* @author max * @author max
@@ -33,7 +32,7 @@ public class ClassCodegen {
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) { private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass); 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(); new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) { if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
@@ -17,7 +17,7 @@ public class ClassFileFactory {
private final Project project; private final Project project;
private final boolean isText; private final boolean isText;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>(); 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; private boolean isDone = false;
public final GenerationState state; public final GenerationState state;
@@ -27,7 +27,7 @@ public class ClassFileFactory {
this.state = state; this.state = state;
} }
ClassVisitor newVisitor(String filePath) { ClassBuilder newVisitor(String filePath) {
ClassVisitor visitor; ClassVisitor visitor;
if (isText) { if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter())); visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
@@ -36,11 +36,12 @@ public class ClassFileFactory {
visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
} }
generators.put(filePath, visitor); final ClassBuilder answer = new ClassBuilder(visitor);
return visitor; generators.put(filePath, answer);
return answer;
} }
ClassVisitor forAnonymousSubclass(String className) { ClassBuilder forAnonymousSubclass(String className) {
return newVisitor(className + ".class"); return newVisitor(className + ".class");
} }
@@ -49,8 +50,8 @@ public class ClassFileFactory {
String fqName = namespace.getFQName(); String fqName = namespace.getFQName();
NamespaceCodegen codegen = ns2codegen.get(fqName); NamespaceCodegen codegen = ns2codegen.get(fqName);
if (codegen == null) { if (codegen == null) {
final ClassVisitor classVisitor = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class"); final ClassBuilder builder = newVisitor(NamespaceCodegen.getJVMClassName(fqName) + ".class");
codegen = new NamespaceCodegen(classVisitor, fqName, state, namespace.getContainingFile()); codegen = new NamespaceCodegen(builder, fqName, state, namespace.getContainingFile());
ns2codegen.put(fqName, codegen); ns2codegen.put(fqName, codegen);
} }
@@ -71,7 +72,7 @@ public class ClassFileFactory {
done(); done();
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file); TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file).getVisitor();
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer)); visitor.print(new PrintWriter(writer));
@@ -84,7 +85,7 @@ public class ClassFileFactory {
done(); done();
ClassWriter visitor = (ClassWriter) generators.get(file); ClassWriter visitor = (ClassWriter) generators.get(file).getVisitor();
return visitor.toByteArray(); return visitor.toByteArray();
} }
@@ -5,13 +5,18 @@
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
import com.intellij.openapi.util.Pair; 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.JetFunctionLiteral;
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression; import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType; 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.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
@@ -44,7 +49,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
} }
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) { 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); 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(), '='); appendType(signatureWriter, funDescriptor.getReturnType(), '=');
signatureWriter.visitEnd(); signatureWriter.visitEnd();
cv.visit(V1_6, cv.defineClass(V1_6,
ACC_PUBLIC, ACC_PUBLIC,
name, name,
null, null,
funClass, funClass,
new String[0] new String[0]
); );
cv.visitSource(fun.getContainingFile().getName(), null); cv.visitSource(fun.getContainingFile().getName(), null);
generateBridge(name, funDescriptor, cv); generateBridge(name, funDescriptor, fun, cv);
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral()); captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
final Type enclosingType = context.enclosingClassType(state.getTypeMapper()); final Type enclosingType = context.enclosingClassType(state.getTypeMapper());
if (enclosingType == null) captureThis = false; if (enclosingType == null) captureThis = false;
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType()); final Method constructor = generateConstructor(funClass, captureThis, fun, funDescriptor.getReturnType());
if (captureThis) { if (captureThis) {
cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null); cv.newField(fun, 0, "this$0", enclosingType.getDescriptor(), null, null);
} }
if(isConst()) { if(isConst()) {
generateConstInstance(); generateConstInstance(fun);
} }
cv.visitEnd(); cv.done();
final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis); final GeneratedAnonymousClassDescriptor answer = new GeneratedAnonymousClassDescriptor(name, constructor, captureThis);
for (DeclarationDescriptor descriptor : closure.keySet()) { for (DeclarationDescriptor descriptor : closure.keySet()) {
@@ -98,41 +103,23 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
return answer; return answer;
} }
private void generateConstInstance() { private void generateConstInstance(JetFunctionLiteralExpression fun) {
cv.visitField(ACC_PRIVATE| ACC_STATIC, "$instance", "Ljava/lang/ref/SoftReference;", null, null); 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.visitCode();
mv.visitFieldInsn(GETSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;"); mv.visitFieldInsn(GETSTATIC, name, "$instance", classDescr);
mv.visitInsn(DUP); 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(); Label ret = new Label();
mv.visitJumpInsn(IFNULL, makeNew); mv.visitJumpInsn(IFNONNULL, ret);
mv.visitTypeInsn(CHECKCAST, name);
mv.visitJumpInsn(GOTO, ret);
mv.visitLabel(makeNew);
mv.visitInsn(POP); mv.visitInsn(POP);
mv.visitTypeInsn(NEW, "java/lang/ref/SoftReference");
mv.visitInsn(DUP);
mv.visitTypeInsn(NEW, name); mv.visitTypeInsn(NEW, name);
mv.visitInsn(DUP);
mv.visitVarInsn(ASTORE, 0);
mv.visitInsn(DUP); mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V"); mv.visitMethodInsn(INVOKESPECIAL, name, "<init>", "()V");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/ref/SoftReference", "<init>", "(Ljava/lang/Object;)V"); mv.visitFieldInsn(PUTSTATIC, name, "$instance", classDescr);
mv.visitFieldInsn(PUTSTATIC, name, "$instance", "Ljava/lang/ref/SoftReference;");
mv.visitVarInsn(ALOAD, 0);
mv.visitLabel(ret); mv.visitLabel(ret);
mv.visitInsn(ARETURN); mv.visitInsn(ARETURN);
@@ -140,21 +127,21 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd(); 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); final ClassContext closureContext = context.intoClosure(name, this);
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor); fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
return closureContext.isThisWasUsed(); 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 bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor);
if(bridge.getDescriptor().equals(delegate.getDescriptor())) if(bridge.getDescriptor().equals(delegate.getDescriptor()))
return; 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(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -185,7 +172,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
mv.visitEnd(); 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(); int argCount = closure.size();
if (captureThis) { if (captureThis) {
@@ -208,7 +195,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
} }
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes); 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(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); 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.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.calls.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor; import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
@@ -53,7 +52,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private int myLastLineNumber = -1; private int myLastLineNumber = -1;
private final InstructionAdapter v; private final InstructionAdapter v;
private final FrameMap myMap; private final FrameMap myFrameMap;
private final JetTypeMapper typeMapper; private final JetTypeMapper typeMapper;
private final GenerationState state; private final GenerationState state;
@@ -69,7 +68,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type returnType, Type returnType,
ClassContext context, ClassContext context,
GenerationState state) { GenerationState state) {
this.myMap = myMap; this.myFrameMap = myMap;
this.typeMapper = state.getTypeMapper(); this.typeMapper = state.getTypeMapper();
this.returnType = returnType; this.returnType = returnType;
this.state = state; this.state = state;
@@ -265,7 +264,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType(); JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType); Type asmParamType = typeMapper.mapType(paramType);
int iteratorVar = myMap.enterTemp(); int iteratorVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType); gen(expression.getLoopRange(), loopRangeType);
invokeFunctionNoParams(iteratorDescriptor, asmIterType, v); invokeFunctionNoParams(iteratorDescriptor, asmIterType, v);
v.store(iteratorVar, asmIterType); v.store(iteratorVar, asmIterType);
@@ -290,7 +289,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
v.ifeq(end); v.ifeq(end);
myMap.enter(parameterDescriptor, asmParamType.getSize()); myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
v.load(iteratorVar, asmIterType); v.load(iteratorVar, asmIterType);
invokeFunctionNoParams(nextDescriptor, asmParamType, v); invokeFunctionNoParams(nextDescriptor, asmParamType, v);
@@ -305,10 +304,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.goTo(begin); v.goTo(begin);
v.mark(end); v.mark(end);
int paramIndex = myMap.leave(parameterDescriptor); int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex); v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myMap.leaveTemp(); myFrameMap.leaveTemp();
myBreakTargets.pop(); myBreakTargets.pop();
myContinueTargets.pop(); myContinueTargets.pop();
} }
@@ -339,7 +338,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
JetType paramType = parameterDescriptor.getOutType(); JetType paramType = parameterDescriptor.getOutType();
Type asmParamType = typeMapper.mapType(paramType); Type asmParamType = typeMapper.mapType(paramType);
myMap.enter(parameterDescriptor, asmParamType.getSize()); myFrameMap.enter(parameterDescriptor, asmParamType.getSize());
generatePrologue(); generatePrologue();
Label condition = new Label(); Label condition = new Label();
@@ -359,7 +358,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end); v.mark(end);
cleanupTemp(); cleanupTemp();
final int paramIndex = myMap.leave(parameterDescriptor); final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex); v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop(); myBreakTargets.pop();
@@ -387,11 +386,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void generatePrologue() { protected void generatePrologue() {
myLengthVar = myMap.enterTemp(); myLengthVar = myFrameMap.enterTemp();
gen(expression.getLoopRange(), loopRangeType); gen(expression.getLoopRange(), loopRangeType);
v.arraylength(); v.arraylength();
v.store(myLengthVar, Type.INT_TYPE); v.store(myLengthVar, Type.INT_TYPE);
myIndexVar = myMap.enterTemp(); myIndexVar = myFrameMap.enterTemp();
v.iconst(0); v.iconst(0);
v.store(myIndexVar, Type.INT_TYPE); v.store(myIndexVar, Type.INT_TYPE);
} }
@@ -415,7 +414,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
protected void cleanupTemp() { protected void cleanupTemp() {
myMap.leaveTemp(2); myFrameMap.leaveTemp(2);
} }
} }
@@ -428,7 +427,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void generatePrologue() { protected void generatePrologue() {
myEndVar = myMap.enterTemp(); myEndVar = myFrameMap.enterTemp();
if(isIntRangeExpr(expression.getLoopRange())) { if(isIntRangeExpr(expression.getLoopRange())) {
JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange(); JetBinaryExpression rangeExpression = (JetBinaryExpression) expression.getLoopRange();
//noinspection ConstantConditions //noinspection ConstantConditions
@@ -462,7 +461,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
protected void cleanupTemp() { 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 sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); 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); VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null; assert variableDescriptor != null;
int index = myMap.leave(variableDescriptor); int index = myFrameMap.leave(variableDescriptor);
final Type sharedVarType = getSharedVarType(variableDescriptor); final Type sharedVarType = getSharedVarType(variableDescriptor);
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType()); 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) { public int lookupLocal(DeclarationDescriptor descriptor) {
return myMap.getIndex(descriptor); return myFrameMap.getIndex(descriptor);
} }
public void invokeFunctionNoParams(FunctionDescriptor functionDescriptor, Type type, InstructionAdapter v) { 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; if (isSubclass((ClassDescriptor) curContextType, calleeContainingClass)) break;
final StackValue outer; final StackValue outer;
if (!thisDone && myMap instanceof ConstructorFrameMap) { if (!thisDone && myFrameMap instanceof ConstructorFrameMap) {
outer = StackValue.local(((ConstructorFrameMap) myMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT); outer = StackValue.local(((ConstructorFrameMap) myFrameMap).getOuterThisIndex(), JetTypeMapper.TYPE_OBJECT);
} }
else { else {
thisToStack(); thisToStack();
@@ -1189,12 +1188,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else if(resolvedValueArgument instanceof VarargValueArgument) { else if(resolvedValueArgument instanceof VarargValueArgument) {
VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument; VarargValueArgument valueArgument = (VarargValueArgument) resolvedValueArgument;
JetType outType = valueParameterDescriptor.getOutType(); JetType outType = valueParameterDescriptor.getOutType();
Type type = typeMapper.mapType(outType); Type type = typeMapper.mapType(outType);
assert type.getSort() == Type.ARRAY; assert type.getSort() == Type.ARRAY;
Type elementType = type.getElementType(); Type elementType = type.getElementType();
int size = valueArgument.getArgumentExpressions().size(); int size = valueArgument.getArgumentExpressions().size();
v.iconst(valueArgument.getArgumentExpressions().size()); v.iconst(valueArgument.getArgumentExpressions().size());
v.newarray(elementType); v.newarray(elementType);
for(int i = 0; i != size; ++i) { for(int i = 0; i != size; ++i) {
@@ -1203,7 +1202,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
gen(valueArgument.getArgumentExpressions().get(i), elementType); gen(valueArgument.getArgumentExpressions().get(i), elementType);
StackValue.arrayElement(elementType, false).store(v); StackValue.arrayElement(elementType, false).store(v);
} }
// throw new UnsupportedOperationException("Varargs are not supported yet"); // throw new UnsupportedOperationException("Varargs are not supported yet");
} }
else { else {
@@ -1632,12 +1631,20 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference()); DeclarationDescriptor op = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getOperationReference());
final Callable callable = resolveToCallable(op); final Callable callable = resolveToCallable(op);
final JetExpression lhs = expression.getLeft(); 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); Type lhsType = expressionType(lhs);
//noinspection ConstantConditions //noinspection ConstantConditions
if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) { if (bindingContext.get(BindingContext.VARIABLE_REASSIGNMENT, expression)) {
if (callable instanceof IntrinsicMethod) { if (callable instanceof IntrinsicMethod) {
StackValue value = gen(lhs); // receiver StackValue value = gen(lhs); // receiver
value.dupReceiver(v, 0); // receiver receiver value.dupReceiver(v); // receiver receiver
value.put(lhsType, v); // receiver lhs value.put(lhsType, v); // receiver lhs
final IntrinsicMethod intrinsic = (IntrinsicMethod) callable; final IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
//noinspection NullableProblems //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) { private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) {
StackValue value = gen(expression.getLeft()); StackValue value = gen(expression.getLeft());
if (keepReturnValue) { if (keepReturnValue) {
value.dupReceiver(v, 0); value.dupReceiver(v);
} }
value.put(lhsType, v); value.put(lhsType, v);
genToJVMStack(expression.getRight()); genToJVMStack(expression.getRight());
@@ -1748,7 +1755,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
StackValue value = genQualified(receiver, operand); StackValue value = genQualified(receiver, operand);
value.dupReceiver(v, 0); value.dupReceiver(v);
value.put(asmType, v); value.put(asmType, v);
if (asmType == Type.LONG_TYPE) { if (asmType == Type.LONG_TYPE) {
//noinspection UnnecessaryBoxing //noinspection UnnecessaryBoxing
@@ -1915,7 +1922,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
if(args.size() == 2) { if(args.size() == 2) {
int sizeIndex = myMap.enterTemp(2); int sizeIndex = myFrameMap.enterTemp(2);
int indexIndex = sizeIndex+1; int indexIndex = sizeIndex+1;
v.dup(); v.dup();
@@ -1947,7 +1954,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.visitLabel(end); v.visitLabel(end);
v.pop(); 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); JetType type = bindingContext.get(BindingContext.EXPRESSION_TYPE, array);
final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type); final Type arrayType = type == null ? Type.VOID_TYPE : typeMapper.mapType(type);
gen(array, arrayType); gen(array, arrayType);
generateArrayIndex(expression); final List<JetExpression> indices = expression.getIndexExpressions();
if (arrayType.getSort() == Type.ARRAY) { 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())) { if(state.getStandardLibrary().getArray().equals(type.getConstructor().getDeclarationDescriptor())) {
JetType elementType = type.getArguments().get(0).getType(); JetType elementType = type.getArguments().get(0).getType();
Type notBoxed = typeMapper.mapType(elementType); Type notBoxed = typeMapper.mapType(elementType);
@@ -1970,23 +1981,39 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
} }
else { else {
final PsiElement declaration = BindingContextUtils.resolveToDeclarationPsiElement(bindingContext, expression); CallableMethod accessor = typeMapper.mapToCallableMethod(operationDescriptor, OwnerKind.IMPLEMENTATION);
assert declaration != null : "No declaration found for " + expression.getText();
final CallableMethod accessor; boolean isGetter = accessor.getSignature().getName().equals("get");
if (declaration instanceof PsiMethod) {
accessor = typeMapper.mapToCallableMethod((PsiMethod) declaration); ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
} FunctionDescriptor setterDescriptor = resolvedSetCall == null ? null : resolvedSetCall.getResultingDescriptor();
else if (declaration instanceof JetNamedFunction) { CallableMethod setter = resolvedSetCall == null ? null : typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION);
accessor = typeMapper.mapToCallableMethod((JetNamedFunction) declaration, null);
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 { 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( for (JetExpression jetExpression : expression.getIndexExpressions()) {
isGetter ? accessor.getSignature().getReturnType() : accessor.getSignature().getArgumentTypes()[1], gen(jetExpression, argumentTypes[index]);
isGetter ? accessor : null, index++;
isGetter ? null : accessor); }
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 @Override
public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) { public StackValue visitThrowExpression(JetThrowExpression expression, StackValue receiver) {
gen(expression.getThrownExpression(), JetTypeMapper.TYPE_OBJECT); 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()); VariableDescriptor descriptor = bindingContext.get(BindingContext.VALUE_PARAMETER, clause.getCatchParameter());
assert descriptor != null; assert descriptor != null;
Type descriptorType = typeMapper.mapType(descriptor.getOutType()); Type descriptorType = typeMapper.mapType(descriptor.getOutType());
myMap.enter(descriptor, 1); myFrameMap.enter(descriptor, 1);
int index = lookupLocal(descriptor); int index = lookupLocal(descriptor);
v.store(index, descriptorType); v.store(index, descriptorType);
gen(clause.getCatchBody(), Type.VOID_TYPE); gen(clause.getCatchBody(), Type.VOID_TYPE);
v.goTo(end); // TODO don't generate goto if there's no code following try/catch 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()); v.visitTryCatchBlock(tryStart, tryEnd, clauseStart, descriptorType.getInternalName());
} }
if (finallyBlock != null) { if (finallyBlock != null) {
Label finallyStart = new Label(); Label finallyStart = new Label();
v.mark(finallyStart); v.mark(finallyStart);
int index = myMap.enterTemp(); int index = myFrameMap.enterTemp();
v.store(index, THROWABLE_TYPE); v.store(index, THROWABLE_TYPE);
gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE); gen(finallyBlock.getFinalExpression(), Type.VOID_TYPE);
@@ -2101,7 +2121,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.load(index, THROWABLE_TYPE); v.load(index, THROWABLE_TYPE);
v.athrow(); v.athrow();
myMap.leaveTemp(); myFrameMap.leaveTemp();
v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null); v.visitTryCatchBlock(tryStart, tryEnd, finallyStart, null);
} }
@@ -2156,7 +2176,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
if (pattern instanceof JetTypePattern) { if (pattern instanceof JetTypePattern) {
JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference(); JetTypeReference typeReference = ((JetTypePattern) pattern).getTypeReference();
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference); JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
generateInstanceOf(expressionToMatch, jetType, false); generateInstanceOf(expressionToMatch, jetType, false);
StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE); StackValue value = StackValue.onStack(Type.BOOLEAN_TYPE);
return negated ? StackValue.not(value) : value; return negated ? StackValue.not(value) : value;
@@ -2166,7 +2186,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else if (pattern instanceof JetExpressionPattern) { else if (pattern instanceof JetExpressionPattern) {
final Type subjectType = expressionToMatch.type; final Type subjectType = expressionToMatch.type;
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(subjectType, v); expressionToMatch.put(subjectType, v);
JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression(); JetExpression condExpression = ((JetExpressionPattern) pattern).getExpression();
Type condType = isNumberPrimitive(subjectType) ? expressionType(condExpression) : OBJECT_TYPE; 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); final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
assert variableDescriptor != null; assert variableDescriptor != null;
final Type varType = typeMapper.mapType(variableDescriptor.getOutType()); final Type varType = typeMapper.mapType(variableDescriptor.getOutType());
myMap.enter(variableDescriptor, varType.getSize()); myFrameMap.enter(variableDescriptor, varType.getSize());
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(varType, v); expressionToMatch.put(varType, v);
final int varIndex = myMap.getIndex(variableDescriptor); final int varIndex = myFrameMap.getIndex(variableDescriptor);
v.store(varIndex, varType); v.store(varIndex, varType);
return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null); return generateWhenCondition(varType, varIndex, ((JetBindingPattern) pattern).getCondition(), null);
} }
@@ -2199,7 +2219,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label lblFail = new Label(); Label lblFail = new Label();
Label lblDone = new Label(); Label lblDone = new Label();
expressionToMatch.dupReceiver(v, 0); expressionToMatch.dupReceiver(v);
expressionToMatch.put(OBJECT_TYPE, v); expressionToMatch.put(OBJECT_TYPE, v);
v.dup(); v.dup();
final String tupleClassName = "jet/Tuple" + entries.size(); 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) { public StackValue visitWhenExpression(JetWhenExpression expression, StackValue receiver) {
JetExpression expr = expression.getSubjectExpression(); JetExpression expr = expression.getSubjectExpression();
final Type subjectType = expressionType(expr); final Type subjectType = expressionType(expr);
final int subjectLocal = myMap.enterTemp(subjectType.getSize()); final int subjectLocal = myFrameMap.enterTemp(subjectType.getSize());
gen(expr, subjectType); gen(expr, subjectType);
v.store(subjectLocal, subjectType); v.store(subjectLocal, subjectType);
@@ -2393,7 +2413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(nextCondition); v.mark(nextCondition);
} }
nextCondition = new Label(); nextCondition = new Label();
FrameMap.Mark mark = myMap.mark(); FrameMap.Mark mark = myFrameMap.mark();
Label thisEntry = new Label(); Label thisEntry = new Label();
if (!whenEntry.isElse()) { if (!whenEntry.isElse()) {
final JetWhenCondition[] conditions = whenEntry.getConditions(); final JetWhenCondition[] conditions = whenEntry.getConditions();
@@ -2421,7 +2441,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
v.mark(end); v.mark(end);
myMap.leaveTemp(subjectType.getSize()); myFrameMap.leaveTemp(subjectType.getSize());
return StackValue.onStack(expressionType(expression)); 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.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -20,10 +23,10 @@ import static org.objectweb.asm.Opcodes.*;
*/ */
public class FunctionCodegen { public class FunctionCodegen {
private final ClassContext owner; private final ClassContext owner;
private final ClassVisitor v; private final ClassBuilder v;
private final GenerationState state; private final GenerationState state;
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) { public FunctionCodegen(ClassContext owner, ClassBuilder v, GenerationState state) {
this.owner = owner; this.owner = owner;
this.v = v; this.v = v;
this.state = state; this.state = state;
@@ -39,13 +42,13 @@ public class FunctionCodegen {
ClassContext funContext = owner.intoFunction(functionDescriptor); ClassContext funContext = owner.intoFunction(functionDescriptor);
final JetExpression bodyExpression = f.getBodyExpression(); final JetExpression bodyExpression = f.getBodyExpression();
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor); generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor, f);
} }
private void generatedMethod(JetExpression bodyExpressions, private void generatedMethod(JetExpression bodyExpressions,
Method jvmSignature, Method jvmSignature,
ClassContext context, ClassContext context,
FunctionDescriptor functionDescriptor) FunctionDescriptor functionDescriptor, JetDeclarationWithBody fun)
{ {
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters(); List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
@@ -62,7 +65,7 @@ public class FunctionCodegen {
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration())); boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
if (isAbstract) flags |= ACC_ABSTRACT; 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) { if(kind != OwnerKind.TRAIT_IMPL) {
int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0; int start = functionDescriptor.getReceiverParameter().exists() ? 1 : 0;
for(int i = 0; i != paramDescrs.size(); ++i) { 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); ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
Type[] argTypes = jvmSignature.getArgumentTypes(); 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++) { for (int i = 0; i < paramDescrs.size(); i++) {
ValueParameterDescriptor parameter = paramDescrs.get(i); ValueParameterDescriptor parameter = paramDescrs.get(i);
frameMap.enter(parameter, argTypes[i].getSize()); frameMap.enter(parameter, argTypes[i+add].getSize());
} }
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -135,7 +139,7 @@ public class FunctionCodegen {
generateDefaultIfNeeded(context, state, v, jvmSignature, functionDescriptor, kind); 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(); Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
for (FunctionDescriptor overriddenFunction : overriddenFunctions) { 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(); DeclarationDescriptor contextClass = owner.getContextClass();
if(kind != OwnerKind.TRAIT_IMPL) { if(kind != OwnerKind.TRAIT_IMPL) {
@@ -187,7 +191,7 @@ public class FunctionCodegen {
String descriptor = jvmSignature.getDescriptor().replace(")","I)"); String descriptor = jvmSignature.getDescriptor().replace(")","I)");
if(!isStatic) if(!isStatic)
descriptor = descriptor.replace("(","(L" + ownerInternalName + ";"); 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); InstructionAdapter iv = new InstructionAdapter(mv);
mv.visitCode(); 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 type1 = state.getTypeMapper().mapType(overriddenFunction.getOriginal().getReturnType());
Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType()); Type type2 = state.getTypeMapper().mapType(functionDescriptor.getReturnType());
if(!type1.equals(type2)) { if(!type1.equals(type2)) {
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()); Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal());
int flags = ACC_PUBLIC; // TODO. 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(); mv.visitCode();
Type[] argTypes = jvmSignature.getArgumentTypes(); 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.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -18,7 +17,7 @@ public class FunctionOrClosureCodegen {
public final GenerationState state; public final GenerationState state;
protected final ExpressionCodegen exprContext; protected final ExpressionCodegen exprContext;
protected final ClassContext context; protected final ClassContext context;
protected ClassVisitor cv = null; protected ClassBuilder cv = null;
public String name = null; public String name = null;
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>(); protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
@@ -46,7 +45,7 @@ public class FunctionOrClosureCodegen {
final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName(); final String fieldName = "$" + (closure.size() + 1); // + "$" + vd.getName();
StackValue innerValue = sharedVarType != null ? StackValue.fieldForSharedVar(localType, name, fieldName) : StackValue.field(type, name, fieldName, false); 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); answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
closure.put(d, answer); 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.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.lang.types.JetStandardLibrary; 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.Collections;
import java.util.List; import java.util.List;
@@ -61,26 +59,21 @@ public class GenerationState {
return intrinsics; return intrinsics;
} }
public ClassVisitor forClassInterface(ClassDescriptor aClass) {
return factory.newVisitor(JetTypeMapper.jvmNameForInterface(aClass) + ".class");
}
public ClassCodegen forClass() { public ClassCodegen forClass() {
return new ClassCodegen(this); return new ClassCodegen(this);
} }
public ClassVisitor forClassImplementation(ClassDescriptor aClass) { public ClassBuilder forClassImplementation(ClassDescriptor aClass) {
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class"); 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"); 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); String className = typeMapper.classNameForAnonymousClass(expression);
ClassVisitor visitor = factory.forAnonymousSubclass(className); return Pair.create(className, factory.forAnonymousSubclass(className));
return Pair.create(className, visitor);
} }
public NamespaceCodegen forNamespace(JetNamespace namespace) { public NamespaceCodegen forNamespace(JetNamespace namespace) {
@@ -123,7 +116,7 @@ public class GenerationState {
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) { public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration(); JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(objectDeclaration); Pair<String, ClassBuilder> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
closure.cv = nameAndVisitor.getSecond(); closure.cv = nameAndVisitor.getSecond();
closure.name = nameAndVisitor.getFirst(); 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.JetType;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lexer.JetTokens; 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.InstructionAdapter;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -26,7 +29,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private JetDelegationSpecifier superCall; private JetDelegationSpecifier superCall;
private String superClass = "java/lang/Object"; 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); super(aClass, context, v, state);
} }
@@ -89,21 +92,23 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
v.visit(Opcodes.V1_6, v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface ? Opcodes.ACC_INTERFACE : 0), Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
jvmName(), ? Opcodes.ACC_INTERFACE
null, : 0),
superClass, jvmName(),
interfaces.toArray(new String[interfaces.size()]) null,
superClass,
interfaces.toArray(new String[interfaces.size()])
); );
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) { 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) { 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.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
annotationVisitor.visitEnd(); annotationVisitor.visitEnd();
} }
@@ -162,7 +167,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateFieldForObjectInstance() { private void generateFieldForObjectInstance() {
if (isNonLiteralObject()) { if (isNonLiteralObject()) {
Type type = JetTypeMapper.jetImplementationType(descriptor); 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() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -182,7 +187,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetClassObject classObject = getClassObject(); final JetClassObject classObject = getClassObject();
if (classObject != null) { if (classObject != null) {
Type type = Type.getObjectType(state.getTypeMapper().jvmName(classObject)); 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() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -242,7 +247,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
int flags = Opcodes.ACC_PUBLIC; // TODO 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(); mv.visitCode();
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
@@ -312,7 +317,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String delegateField = "$delegate_" + n; String delegateField = "$delegate_" + n;
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor); Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
String fieldDesc = fieldType.getDescriptor(); 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); iv.putfield(classname, delegateField, fieldDesc);
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor); 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); final Type type = JetTypeMapper.jetImplementationType(outerDescriptor);
String interfaceDesc = type.getDescriptor(); String interfaceDesc = type.getDescriptor();
final String fieldName = "this$0"; 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(0, classType);
iv.load(frameMap.getOuterThisIndex(), type); iv.load(frameMap.getOuterThisIndex(), type);
iv.putfield(classname, fieldName, interfaceDesc); iv.putfield(classname, fieldName, interfaceDesc);
@@ -393,7 +398,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method function = state.getTypeMapper().mapSignature(fun.getName(), fun); Method function = state.getTypeMapper().mapSignature(fun.getName(), fun);
Method functionOriginal = state.getTypeMapper().mapSignature(fun.getName(), fun.getOriginal()); 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(); mv.visitCode();
codegen.generateThisOrOuter(descriptor); codegen.generateThisOrOuter(descriptor);
@@ -475,7 +480,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) { else if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName(); String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION) + ";"; 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()) { if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
@@ -533,7 +538,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
int flags = Opcodes.ACC_PUBLIC; // TODO 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(); mv.visitCode();
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind); ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
@@ -677,9 +682,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (p.getValOrVarNode() != null) { if (p.getValOrVarNode() != null) {
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p); PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
if (propertyDescriptor != null) { if (propertyDescriptor != null) {
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { 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(); JetType defaultType = descriptor.getDefaultType();
if(CodegenUtil.hasTypeInfoField(defaultType)) { if(CodegenUtil.hasTypeInfoField(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) { 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(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -715,7 +720,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitMaxs(0, 0); mv.visitMaxs(0, 0);
mv.visitEnd(); 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(); mv.visitCode();
iv = new InstructionAdapter(mv); iv = new InstructionAdapter(mv);
owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -734,7 +739,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void genGetStaticGetTypeInfoMethod() { 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(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION); String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
@@ -745,7 +750,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void staticTypeInfoField() { 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() { staticInitializerChunks.add(new CodeChunk() {
@Override @Override
public void generate(InstructionAdapter v) { public void generate(InstructionAdapter v) {
@@ -776,11 +781,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType()); String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC, final MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"$$getSuperTypesTypeInfo", "$$getSuperTypesTypeInfo",
sig, sig,
null /* TODO */, null /* TODO */,
null); null);
mv.visitCode(); mv.visitCode();
InstructionAdapter v = new InstructionAdapter(mv); InstructionAdapter v = new InstructionAdapter(mv);
@@ -547,6 +547,9 @@ public class JetTypeMapper {
} }
public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) { public CallableMethod mapToCallableMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
if(functionDescriptor == null)
return null;
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration(); final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
final List<Type> valueParameterTypes = new ArrayList<Type>(); final List<Type> valueParameterTypes = new ArrayList<Type>();
Method descriptor = mapSignature(functionDescriptor.getOriginal(), valueParameterTypes, kind); 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.JetType;
import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils; 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 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.*; import static org.objectweb.asm.Opcodes.*;
@@ -20,20 +24,20 @@ import static org.objectweb.asm.Opcodes.*;
* @author max * @author max
*/ */
public class NamespaceCodegen { public class NamespaceCodegen {
private final ClassVisitor v; private final ClassBuilder v;
private final GenerationState state; 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.v = v;
this.state = state; this.state = state;
v.visit(V1_6, v.defineClass(V1_6,
ACC_PUBLIC, ACC_PUBLIC,
getJVMClassName(fqName), getJVMClassName(fqName),
null, null,
//"jet/lang/Namespace", //"jet/lang/Namespace",
"java/lang/Object", "java/lang/Object",
new String[0] new String[0]
); );
// TODO figure something out for a namespace that spans multiple files // TODO figure something out for a namespace that spans multiple files
v.visitSource(sourceFile.getName(), null); v.visitSource(sourceFile.getName(), null);
@@ -76,8 +80,8 @@ public class NamespaceCodegen {
} }
private void generateStaticInitializers(JetNamespace namespace) { private void generateStaticInitializers(JetNamespace namespace) {
MethodVisitor mv = v.visitMethod(ACC_PUBLIC | ACC_STATIC, MethodVisitor mv = v.newMethod(namespace, ACC_PUBLIC | ACC_STATIC,
"<clinit>", "()V", null, null); "<clinit>", "()V", null, null);
mv.visitCode(); mv.visitCode();
FrameMap frameMap = new FrameMap(); FrameMap frameMap = new FrameMap();
@@ -104,9 +108,9 @@ public class NamespaceCodegen {
String jvmClassName = getJVMClassName(namespace.getName()); String jvmClassName = getJVMClassName(namespace.getName());
for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) { for(Map.Entry<JetType,Integer> e : (context.typeInfoConstants != null ? context.typeInfoConstants : Collections.<JetType,Integer>emptyMap()).entrySet()) {
String fieldName = "$typeInfoCache$" + e.getValue(); 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); InstructionAdapter v = new InstructionAdapter(mmv);
v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;"); v.visitFieldInsn(GETSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
v.visitInsn(DUP); v.visitInsn(DUP);
@@ -185,7 +189,7 @@ public class NamespaceCodegen {
} }
public void done() { public void done() {
v.visitEnd(); v.done();
} }
public static String getJVMClassName(String fqName) { 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.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement; 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.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@@ -19,10 +21,10 @@ import org.objectweb.asm.commons.InstructionAdapter;
public class PropertyCodegen { public class PropertyCodegen {
private final GenerationState state; private final GenerationState state;
private final FunctionCodegen functionCodegen; private final FunctionCodegen functionCodegen;
private final ClassVisitor v; private final ClassBuilder v;
private final OwnerKind kind; 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.v = v;
this.functionCodegen = functionCodegen; this.functionCodegen = functionCodegen;
this.state = state; this.state = state;
@@ -41,9 +43,9 @@ public class PropertyCodegen {
generateSetter(p, propertyDescriptor); generateSetter(p, propertyDescriptor);
} }
else if (kind instanceof OwnerKind.DelegateKind) { else if (kind instanceof OwnerKind.DelegateKind) {
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC); generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
if (propertyDescriptor.isVar()) { if (propertyDescriptor.isVar()) {
generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC); generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p);
} }
} }
} }
@@ -71,7 +73,7 @@ public class PropertyCodegen {
else { else {
modifiers = Opcodes.ACC_PRIVATE; 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) { private void generateDefaultGetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); 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) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
@@ -129,7 +131,7 @@ public class PropertyCodegen {
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(); final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
String getterName = getterName(propertyDescriptor.getName()); 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) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -156,10 +158,10 @@ public class PropertyCodegen {
private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) { private void generateDefaultSetter(JetProperty p, JetDeclaration declaration) {
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p);
int flags = JetTypeMapper.getAccessModifiers(declaration, Opcodes.ACC_PUBLIC); 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) { if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC; flags |= Opcodes.ACC_STATIC;
} }
@@ -170,7 +172,7 @@ public class PropertyCodegen {
flags |= Opcodes.ACC_ABSTRACT; flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(); 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) { if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode(); mv.visitCode();
InstructionAdapter iv = new InstructionAdapter(mv); InstructionAdapter iv = new InstructionAdapter(mv);
@@ -38,7 +38,7 @@ public abstract class StackValue {
throw new UnsupportedOperationException("cannot store to value " + this); 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) { public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
@@ -84,8 +84,8 @@ public abstract class StackValue {
return new ArrayElement(type, unbox); return new ArrayElement(type, unbox);
} }
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) { public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter, FrameMap frame) {
return new CollectionElement(type, getter, setter); return new CollectionElement(type, getter, setter, frame);
} }
public static StackValue field(Type type, String owner, String name, boolean isStatic) { public static StackValue field(Type type, String owner, String name, boolean isStatic) {
@@ -456,24 +456,21 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { v.dup2(); // array and index
v.dup2X1();
}
else {
v.dup2(); // array and index
}
} }
} }
private static class CollectionElement extends StackValue { private static class CollectionElement extends StackValue {
private final CallableMethod getter; private final CallableMethod getter;
private final CallableMethod setter; 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); super(type);
this.getter = getter; this.getter = getter;
this.setter = setter; this.setter = setter;
this.frame = frame;
} }
@Override @Override
@@ -494,13 +491,70 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { int size = calcSize();
v.dup2X1();
} if(size == 2) {
else {
v.dup2(); // collection and index 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 @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (!isStatic) { if (!isStatic) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
} }
@@ -557,7 +606,7 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
} }
@Override @Override
@@ -607,14 +656,9 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (!isStatic) { if (!isStatic) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
} }
} }
@@ -716,13 +760,8 @@ public abstract class StackValue {
} }
@Override @Override
public void dupReceiver(InstructionAdapter v, int below) { public void dupReceiver(InstructionAdapter v) {
if (below == 1) { v.dup();
v.dupX1();
}
else {
v.dup();
}
} }
@Override @Override
@@ -7,15 +7,12 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TraitImplBodyCodegen extends ClassBodyCodegen { 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); super(aClass, context, v, state);
} }
@@ -48,12 +45,12 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override @Override
protected void generateDeclaration() { protected void generateDeclaration() {
v.visit(Opcodes.V1_6, v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
jvmName(), jvmName(),
null, null,
"java/lang/Object", "java/lang/Object",
new String[0] new String[0]
); );
v.visitSource(myClass.getContainingFile().getName(), null); v.visitSource(myClass.getContainingFile().getName(), null);
} }
@@ -32,7 +32,7 @@ public class Increment implements IntrinsicMethod {
} }
} }
StackValue value = codegen.genQualified(receiver, operand); StackValue value = codegen.genQualified(receiver, operand);
value.dupReceiver(v, 0); value. dupReceiver(v);
value.put(expectedType, v); value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) { if (expectedType == Type.LONG_TYPE) {
v.lconst(myDelta); 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.google.common.base.Predicates;
import com.intellij.openapi.vfs.VirtualFile; 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.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.plugin.JetFileType;
import java.io.PrintStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* The session which handles analyzing and compiling a single module.
*
* @author yole * @author yole
*/ */
public class CompileSession { public class CompileSession {
@@ -73,10 +76,10 @@ public class CompileSession {
return mySourceFileNamespaces; return mySourceFileNamespaces;
} }
public boolean analyze() { public boolean analyze(final PrintStream out) {
if (!myErrors.isEmpty()) { if (!myErrors.isEmpty()) {
for (String error : myErrors) { for (String error : myErrors) {
System.out.println(error); out.println(error);
} }
return false; return false;
} }
@@ -85,7 +88,7 @@ public class CompileSession {
allNamespaces.addAll(myLibrarySourceFileNamespaces); allNamespaces.addAll(myLibrarySourceFileNamespaces);
myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY); myBindingContext = instance.analyzeNamespaces(myEnvironment.getProject(), allNamespaces, Predicates.<PsiFile>alwaysTrue(), JetControlFlowDataTraceFactory.EMPTY);
ErrorCollector errorCollector = new ErrorCollector(myBindingContext); ErrorCollector errorCollector = new ErrorCollector(myBindingContext);
errorCollector.report(); errorCollector.report(out);
return !errorCollector.hasErrors; 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.LinkedHashMultimap;
import com.google.common.collect.Multimap; 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.diagnostics.Severity;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import java.io.PrintStream;
import java.util.Collection; import java.util.Collection;
/** /**
@@ -36,14 +37,14 @@ class ErrorCollector {
} }
} }
void report() { void report(final PrintStream out) {
if(!maps.isEmpty()) { if(!maps.isEmpty()) {
for (PsiFile psiFile : maps.keySet()) { for (PsiFile psiFile : maps.keySet()) {
System.out.println(psiFile.getVirtualFile().getPath()); out.println(psiFile.getVirtualFile().getPath());
Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile); Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile);
for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) { for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) {
String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange); 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; 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.Args;
import com.sampullara.cli.Argument; import com.sampullara.cli.Argument;
import jet.modules.IModuleBuilder; import org.jetbrains.jet.compiler.CompileEnvironment;
import jet.modules.IModuleSetBuilder; import org.jetbrains.jet.compiler.CompileEnvironmentException;
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.File; 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 * @author yole
@@ -54,273 +36,35 @@ public class KotlinCompiler {
return; return;
} }
Disposable root = new Disposable() { CompileEnvironment environment = new CompileEnvironment();
@Override
public void dispose() {
}
};
JetCoreEnvironment environment = new JetCoreEnvironment(root);
File rtJar = initJdk(); File rtJar = initJdk();
if (rtJar == null) return; if (rtJar == null) return;
environment.addToClasspath(rtJar); try {
final File unpackedRuntimePath = getUnpackedRuntimePath(); environment.setJavaRuntime(rtJar);
if (unpackedRuntimePath != null) { if (!environment.initializeKotlinRuntime()) {
environment.addToClasspath(unpackedRuntimePath);
}
else {
final File runtimeJarPath = getRuntimeJarPath();
if (runtimeJarPath != null && runtimeJarPath.exists()) {
environment.addToClasspath(runtimeJarPath);
}
else {
System.out.println("No runtime library found"); System.out.println("No runtime library found");
return; return;
} }
}
if (arguments.module != null) { if (arguments.module != null) {
compileModuleScript(environment, arguments.module); environment.compileModuleScript(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);
return; 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 { else {
System.out.println("Couldn't find runtime library"); environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir);
}
}
}
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());
} }
} catch (CompileEnvironmentException e) {
System.out.println(e.getMessage());
} }
} }
private static File initJdk() { private static File initJdk() {
String javaHome = System.getenv("JAVA_HOME"); String javaHome = System.getenv("JAVA_HOME");
File rtJar = null; File rtJar;
if (javaHome == null) { if (javaHome == null) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); rtJar = CompileEnvironment.findActiveRtJar();
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;
}
}
}
}
if(rtJar == null) { if(rtJar == null) {
System.out.println("JAVA_HOME environment variable needs to be defined"); 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() { public static final ImportingStrategy JAVA_DEFAULT_IMPORTS = new ImportingStrategy() {
@Override @Override
public void addImports(Project project, JetSemanticServices semanticServices, BindingTrace trace, WritableScope rootScope) { 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); JavaSemanticServices javaSemanticServices = new JavaSemanticServices(project, semanticServices, trace);
rootScope.importScope(new JavaPackageScope("", null, javaSemanticServices)); rootScope.importScope(new JavaPackageScope("", null, javaSemanticServices));
rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices)); rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
@@ -83,4 +83,13 @@ public class FunctionDescriptorUtil {
return parameterScope; 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.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 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 org.jetbrains.jet.lang.types.JetType;
import java.util.Collections; import java.util.Collections;
@@ -15,9 +13,8 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) { public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
JetType outType = variableDescriptor.getOutType(); JetType outType = variableDescriptor.getOutType();
assert outType != null; assert outType != null;
assert JetStandardClasses.isFunctionType(outType);
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor); 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; return result;
} }
@@ -25,7 +22,6 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) { private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName()); super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
// super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
this.variableDescriptor = variableDescriptor; this.variableDescriptor = variableDescriptor;
} }
@@ -207,6 +207,7 @@ public interface Errors {
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Method 'iterator()' is ambiguous for this expression: {0}"); 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> 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 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 ('{...}')"); 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.Predicate;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.Maps;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElementVisitor;
@@ -23,6 +24,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* @author abreslav * @author abreslav
@@ -82,14 +84,17 @@ public class AnalyzingUtils {
TopDownAnalyzer.process(semanticServices, bindingTraceContext, scope, new NamespaceLike.Adapter(owner) { TopDownAnalyzer.process(semanticServices, bindingTraceContext, scope, new NamespaceLike.Adapter(owner) {
private Map<String, NamespaceDescriptorImpl> declaredNamespaces = Maps.newHashMap();
@Override @Override
public NamespaceDescriptorImpl getNamespace(String name) { public NamespaceDescriptorImpl getNamespace(String name) {
return null; return declaredNamespaces.get(name);
} }
@Override @Override
public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) { public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
scope.addNamespace(namespaceDescriptor); scope.addNamespace(namespaceDescriptor);
declaredNamespaces.put(namespaceDescriptor.getName(), (NamespaceDescriptorImpl) namespaceDescriptor);
} }
@Override @Override
@@ -36,8 +36,8 @@ public interface BindingContext {
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT"); 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> LOOP_RANGE_NEXT = Slices.createSimpleSlice("LOOP_RANGE_NEXT");
WritableSlice<JetExpression, FunctionDescriptor> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET"); WritableSlice<JetExpression, ResolvedCall<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_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET");
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST"); WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST");
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE"); 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.annotations.Nullable;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*; 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.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl; import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
@@ -78,7 +79,7 @@ public class CallResolver {
} }
@Nullable @Nullable
public FunctionDescriptor resolveCallWithGivenName( public ResolvedCall<FunctionDescriptor> resolveCallWithGivenName(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull JetScope scope, @NotNull JetScope scope,
@NotNull final Call call, @NotNull final Call call,
@@ -86,7 +87,7 @@ public class CallResolver {
@NotNull String name, @NotNull String name,
@NotNull JetType expectedType) { @NotNull JetType expectedType) {
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo); 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 @Nullable
@@ -173,8 +174,30 @@ public class CallResolver {
} }
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY)); 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 { 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 @Override
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) { 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 @Override
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*; import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.CallMaker; 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.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.*; 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)); ExpressionReceiver receiver = getExpressionReceiver(facade, baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
if (receiver == null) return null; if (receiver == null) return null;
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName( FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
CallMaker.makeCall(receiver, expression), CallMaker.makeCall(receiver, expression),
expression.getOperationSign(), expression.getOperationSign(),
name, name);
receiver);
if (functionDescriptor == null) return null; if (functionDescriptor == null) return null;
JetType returnType = functionDescriptor.getReturnType(); 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) { public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
String name = "contains"; String name = "contains";
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE)); 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)), CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
operationSign, operationSign,
name, receiver); name);
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
ensureBooleanResult(operationSign, name, containsType, context); ensureBooleanResult(operationSign, name, containsType, context);
} }
@@ -752,14 +752,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope)); ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope));
if (receiver != null) { if (receiver != null) {
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName( ResolvedCall<FunctionDescriptor> resolvedCall = context.resolveCallWithGivenName(
CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()), CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()),
expression, expression,
"get", "get"
receiver); );
if (functionDescriptor != null) { if (resolvedCall != null) {
context.trace.record(INDEXED_LVALUE_GET, expression, functionDescriptor); context.trace.record(INDEXED_LVALUE_GET, expression, resolvedCall);
return DataFlowUtils.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); return DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType);
} }
} }
return null; return null;
@@ -768,11 +768,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
@Nullable @Nullable
protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) { protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope)); 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), CallMaker.makeCall(receiver, binaryExpression),
binaryExpression.getOperationReference(), binaryExpression.getOperationReference(),
name, name
receiver); );
if (functionDescriptor != null) { if (functionDescriptor != null) {
return functionDescriptor.getReturnType(); 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.TypeResolver;
import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.CallMaker;
import org.jetbrains.jet.lang.resolve.calls.CallResolver; 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.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
@@ -172,10 +173,16 @@ import java.util.Map;
////////// Call resolution utilities ////////// Call resolution utilities
@Nullable @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); 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 @Nullable
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
return getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType); 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.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.calls.CallMaker; 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.WritableScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; 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.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import static org.jetbrains.jet.lang.diagnostics.Errors.*; 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.INDEXED_LVALUE_SET;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver; import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver;
/** /**
@@ -109,7 +109,8 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
@Override @Override
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) { protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
// If there's += (or similar op) defined as such, we just call it. // 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); String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
@@ -119,13 +120,13 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
if (assignmentOperationType == null) { if (assignmentOperationType == null) {
String counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType)); 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); JetType typeForBinaryCall = getTypeForBinaryCall(scope, counterpartName, context, expression);
if (typeForBinaryCall != null) { 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); context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context); ExpressionTypingUtils.checkWrappingInRef(expression.getLeft(), context);
} }
@@ -138,14 +139,14 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
@Override @Override
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) { protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
boolean getterNeeded = false;
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft()); JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
JetExpression right = expression.getRight(); JetExpression right = expression.getRight();
if (left instanceof JetArrayAccessExpression) { if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left; 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) { if (right != null) {
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope)); JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
} }
@@ -164,30 +165,32 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
return checkExpectedType(expression, context); 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)); ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
if (receiver == null) return null; if (receiver == null) return null;
Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide); 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, call,
arrayAccessExpression, arrayAccessExpression,
"set", receiver); "set");
if (setFunction == null) return null; if (setFunctionCall == null) return null;
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunction); FunctionDescriptor setFunctionDescriptor = setFunctionCall.getResultingDescriptor();
if (getterNeeded) { context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionCall);
FunctionDescriptor getFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
CallMaker.makeArrayGetCall(receiver, arrayAccessExpression), // if (getterNeeded) {
arrayAccessExpression, // ResolvedCall<FunctionDescriptor> getFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
"get", receiver); // CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
if (getFunction == null) return null; // arrayAccessExpression,
context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunction); // "get");
} // if (getFunctionCall == null) return null;
else { // context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionCall);
context.trace.record(REFERENCE_TARGET, operationSign, setFunction); // }
} // else {
return DataFlowUtils.checkType(setFunction.getReturnType(), arrayAccessExpression, context); // context.trace.record(REFERENCE_TARGET, operationSign, setFunctionDescriptor);
// }
return DataFlowUtils.checkType(setFunctionDescriptor.getReturnType(), arrayAccessExpression, context);
} }
@Override @Override
@@ -16,6 +16,6 @@ class C : T {
super.foo() // OK super.foo() // OK
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error <!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
super.buzz() // OK, resolved to a member 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!>""<!>) foo(1, "", <!TOO_MANY_ARGUMENTS!>""<!>)
bar(z = "") bar(z = "")
<!NO_VALUE_FOR_PARAMETER!>bar<!>() bar<!NO_VALUE_FOR_PARAMETER!>()<!>
<!NO_VALUE_FOR_PARAMETER!>bar<!>("") bar<!NO_VALUE_FOR_PARAMETER!>("")<!>
bar(1, 1, "") bar(1, 1, "")
bar(1, 1, "") bar(1, 1, "")
bar(1, <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>z<!> = "") 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(); Method foo = generateFunction();
foo.invoke(null); 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 { 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()); System.out.println(generateToText());
final Method main = generateFunction(); final Method main = generateFunction();
long[] data = new long[] { 5 }; 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.JetContainerNode;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; 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.lexer.JetTokens;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
@@ -40,8 +41,8 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
@Override @Override
protected PsiElement doResolve() { protected PsiElement doResolve() {
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile()); BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
if (getFunction != null && setFunction != null) { if (getFunction != null && setFunction != null) {
return null; // Call doMultiResolve return null; // Call doMultiResolve
} }
@@ -51,10 +52,10 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
@Override @Override
protected ResolveResult[] doMultiResolve() { protected ResolveResult[] doMultiResolve() {
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile()); BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression); ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction); PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction.getResultingDescriptor());
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression); ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction); PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction.getResultingDescriptor());
return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)}; return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)};
// return super.doMultiResolve(); // 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 { class ModuleBuilder(val name: String): IModuleBuilder {
val sourceFiles: ArrayList<String?> = ArrayList<String?>() val sourceFiles: ArrayList<String?> = ArrayList<String?>()
val classpathRoots: ArrayList<String?> = ArrayList<String?>() val classpathRoots: ArrayList<String?> = ArrayList<String?>()
var _jarName: String? = null
val source: SourcesBuilder val source: SourcesBuilder
get() = SourcesBuilder(this) get() = SourcesBuilder(this)
@@ -39,6 +46,9 @@ class ModuleBuilder(val name: String): IModuleBuilder {
val classpath: ClasspathBuilder val classpath: ClasspathBuilder
get() = ClasspathBuilder(this) get() = ClasspathBuilder(this)
val jar: JarBuilder
get() = JarBuilder(this)
fun addSourceFiles(pattern: String) { fun addSourceFiles(pattern: String) {
sourceFiles.add(pattern) sourceFiles.add(pattern)
} }
@@ -47,9 +57,13 @@ class ModuleBuilder(val name: String): IModuleBuilder {
classpathRoots.add(name) classpathRoots.add(name)
} }
fun setJarName(name: String) {
_jarName = name
}
override fun getSourceFiles(): List<String?>? = sourceFiles override fun getSourceFiles(): List<String?>? = sourceFiles
override fun getClasspathRoots(): List<String?>? = classpathRoots override fun getClasspathRoots(): List<String?>? = classpathRoots
override fun getModuleName(): String? = name 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(); String getModuleName();
List<String> getSourceFiles(); List<String> getSourceFiles();
List<String> getClasspathRoots(); List<String> getClasspathRoots();
String getJarName();
} }