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