Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -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();
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-4
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
+5
-4
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-5
@@ -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
|
||||||
|
|||||||
+14
-14
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -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);
|
||||||
|
|||||||
+31
-28
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user