Merge remote branch 'origin/master'
Conflicts: idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java
This commit is contained in:
Generated
+8
@@ -26,6 +26,14 @@
|
||||
<maximumStackSize value="2" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/build.xml">
|
||||
<additionalClassPath />
|
||||
<antReference projectDefault="true" />
|
||||
<customJdkName value="" />
|
||||
<maximumHeapSize value="128" />
|
||||
<maximumStackSize value="2" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
||||
Generated
+1
@@ -4,6 +4,7 @@
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Jet.iml" filepath="$PROJECT_DIR$/Jet.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/backend/backend.iml" filepath="$PROJECT_DIR$/compiler/backend/backend.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/cli/cli.iml" filepath="$PROJECT_DIR$/compiler/cli/cli.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/frontend/frontend.iml" filepath="$PROJECT_DIR$/compiler/frontend/frontend.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/frontend.java/frontend.java.iml" filepath="$PROJECT_DIR$/compiler/frontend.java/frontend.java.iml" />
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<project name="Kotlin" default="dist">
|
||||
<property name="output" value="${basedir}/dist"/>
|
||||
<property name="build.number" value="snapshot"/>
|
||||
|
||||
<path id="classpath">
|
||||
<fileset dir="${basedir}/ideaSDK" includes="*.jar"/>
|
||||
<fileset dir="${basedir}/lib" includes="*.jar"/>
|
||||
<pathelement path="${output}/classes/runtime"/>
|
||||
</path>
|
||||
|
||||
<path id="sourcepath">
|
||||
<dirset dir="${basedir}/compiler">
|
||||
<include name="frontend/src"/>
|
||||
<include name="frontend.java/src"/>
|
||||
<include name="backend/src"/>
|
||||
<include name="cli/src"/>
|
||||
</dirset>
|
||||
</path>
|
||||
|
||||
<target name="compileRT">
|
||||
<mkdir dir="${output}/classes/runtime"/>
|
||||
<javac destdir="${output}/classes/runtime">
|
||||
<src path="${basedir}/stdlib/src"/>
|
||||
<classpath refid="classpath"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="jarRT" depends="compileRT">
|
||||
<jar destfile="${output}/kotlin-runtime.jar">
|
||||
<fileset dir="${output}/classes/runtime"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="compile" depends="compileRT">
|
||||
<mkdir dir="${output}/classes/compiler"/>
|
||||
<javac destdir="${output}/classes/compiler">
|
||||
<src refid="sourcepath"/>
|
||||
<classpath refid="classpath"/>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="jar">
|
||||
<jar destfile="${output}/kotlin-compiler.jar">
|
||||
<fileset dir="${output}/classes/compiler"/>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="dist" depends="jarRT,jar">
|
||||
<zip destfile="${output}/kotlin-${build.number}.zip">
|
||||
<zipfileset prefix="kotlin-${build.number}/bin" filemode="755">
|
||||
<include name="${basedir}/compile/cli/bin/*"/>
|
||||
</zipfileset>
|
||||
<zipfileset prefix="kotlin-${build.number}/examples" includes="examples/src/**"/>
|
||||
<zipfileset prefix="kotlin-${build.number}/lib">
|
||||
<include name="ideaSDK/*.jar"/>
|
||||
<include name="lib/*.jar"/>
|
||||
<include name="${output}/*.jar"/>
|
||||
</zipfileset>
|
||||
<zipfileset prefix="kotlin-${build.number}/examples" includes="examples/src/**"/>
|
||||
</zip>
|
||||
</target>
|
||||
</project>
|
||||
|
||||
@@ -40,10 +40,10 @@ public abstract class ClassBodyCodegen {
|
||||
public void generate() {
|
||||
generateDeclaration();
|
||||
|
||||
generateSyntheticParts();
|
||||
|
||||
generateClassBody();
|
||||
|
||||
generateSyntheticParts();
|
||||
|
||||
generateStaticInitializer();
|
||||
|
||||
v.visitEnd();
|
||||
|
||||
@@ -4,8 +4,6 @@ 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;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -25,7 +23,7 @@ public class ClassCodegen {
|
||||
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
final ClassContext contextForInners = parentContext.intoClass(null, descriptor, OwnerKind.IMPLEMENTATION);
|
||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||
generate(contextForInners, (JetClass) declaration);
|
||||
@@ -36,11 +34,11 @@ 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);
|
||||
new ImplementationBodyCodegen(aClass, parentContext.intoClass(descriptor, kind), v, state).generate();
|
||||
new ImplementationBodyCodegen(aClass, parentContext.intoClass(null, descriptor, kind), v, state).generate();
|
||||
|
||||
if(aClass instanceof JetClass && ((JetClass)aClass).isTrait()) {
|
||||
v = state.forTraitImplementation(descriptor);
|
||||
new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
|
||||
new TraitImplBodyCodegen(aClass, parentContext.intoClass(null, descriptor, OwnerKind.TRAIT_IMPL), v, state).generate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
@@ -14,18 +11,22 @@ import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/*
|
||||
* @author max
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ClassContext {
|
||||
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null);
|
||||
private final DeclarationDescriptor contextType;
|
||||
private final OwnerKind contextKind;
|
||||
private final StackValue thisExpression;
|
||||
private final ClassContext parentContext;
|
||||
private final ClosureCodegen closure;
|
||||
public final FunctionOrClosureCodegen closure;
|
||||
private boolean thisWasUsed = false;
|
||||
|
||||
HashMap<JetType,Integer> typeInfoConstants;
|
||||
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) {
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, FunctionOrClosureCodegen closureCodegen) {
|
||||
this.contextType = contextType;
|
||||
this.contextKind = contextKind;
|
||||
this.thisExpression = thisExpression;
|
||||
@@ -60,11 +61,11 @@ public class ClassContext {
|
||||
return new ClassContext(descriptor, OwnerKind.NAMESPACE, null, this, null);
|
||||
}
|
||||
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
|
||||
public ClassContext intoClass(FunctionOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
||||
final StackValue thisValue;
|
||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
return new ClassContext(descriptor, kind, thisValue, this, null);
|
||||
return new ClassContext(descriptor, kind, thisValue, this, closure);
|
||||
}
|
||||
|
||||
public ClassContext intoFunction(FunctionDescriptor descriptor) {
|
||||
@@ -140,13 +141,21 @@ public class ClassContext {
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d, InstructionAdapter v) {
|
||||
final ClosureCodegen top = closure;
|
||||
final FunctionOrClosureCodegen top = closure;
|
||||
if (top != null) {
|
||||
final StackValue answer = top.lookupInContext(d);
|
||||
if (answer != null) return answer;
|
||||
|
||||
final StackValue thisContext = getThisExpression();
|
||||
thisContext.put(thisContext.type, v);
|
||||
if(thisContext instanceof StackValue.Local) {
|
||||
}
|
||||
else if(thisContext instanceof StackValue.InstanceField) {
|
||||
StackValue.InstanceField instanceField = (StackValue.InstanceField) thisContext;
|
||||
v.getfield(instanceField.owner, instanceField.name, instanceField.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
return parentContext != null ? parentContext.lookupInContext(d, v) : null;
|
||||
|
||||
@@ -26,19 +26,10 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClosureCodegen {
|
||||
public final GenerationState state;
|
||||
private final ExpressionCodegen exprContext;
|
||||
private final ClassContext context;
|
||||
private ClassVisitor cv = null;
|
||||
public String name = null;
|
||||
|
||||
private Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||
public class ClosureCodegen extends FunctionOrClosureCodegen {
|
||||
|
||||
public ClosureCodegen(GenerationState state, ExpressionCodegen exprContext, ClassContext context) {
|
||||
this.state = state;
|
||||
this.exprContext = exprContext;
|
||||
this.context = context;
|
||||
super(exprContext, context, state);
|
||||
}
|
||||
|
||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||
@@ -57,31 +48,6 @@ public class ClosureCodegen {
|
||||
return state.getTypeMapper().mapSignature("invoke", fd);
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d) {
|
||||
if (d instanceof VariableDescriptor) {
|
||||
VariableDescriptor vd = (VariableDescriptor) d;
|
||||
|
||||
EnclosedValueDescriptor answer = closure.get(vd);
|
||||
if (answer != null) return answer.getInnerValue();
|
||||
|
||||
final int idx = exprContext.lookupLocal(vd);
|
||||
if (idx < 0) return null;
|
||||
|
||||
final Type type = state.getTypeMapper().mapType(vd.getOutType());
|
||||
|
||||
StackValue outerValue = StackValue.local(idx, type);
|
||||
final String fieldName = "$" + (closure.size() + 1);
|
||||
StackValue innerValue = StackValue.field(type, name, fieldName, false);
|
||||
cv.visitField(Opcodes.ACC_PUBLIC, fieldName, type.getDescriptor(), null, null);
|
||||
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
|
||||
closure.put(d, answer);
|
||||
|
||||
return innerValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor gen(JetFunctionLiteralExpression fun) {
|
||||
final Pair<String, ClassVisitor> nameAndVisitor = state.forAnonymousSubclass(fun);
|
||||
|
||||
@@ -120,7 +86,7 @@ public class ClosureCodegen {
|
||||
final Method constructor = generateConstructor(funClass, captureThis, funDescriptor.getReturnType());
|
||||
|
||||
if (captureThis) {
|
||||
cv.visitField(Opcodes.ACC_PRIVATE, "this$0", enclosingType.getDescriptor(), null, null);
|
||||
cv.visitField(0, "this$0", enclosingType.getDescriptor(), null, null);
|
||||
}
|
||||
|
||||
cv.visitEnd();
|
||||
@@ -192,7 +158,9 @@ public class ClosureCodegen {
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||
argTypes[i++] = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
|
||||
final Type sharedVarType = exprContext.getSharedVarType(descriptor);
|
||||
final Type type = sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
|
||||
argTypes[i++] = type;
|
||||
}
|
||||
|
||||
final Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
|
||||
|
||||
@@ -551,7 +551,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
final Method cons = closure.getConstructor();
|
||||
|
||||
if (closure.isCaptureThis()) {
|
||||
thisToStack();
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
for (int i = 0; i < closure.getArgs().size(); i++) {
|
||||
@@ -566,16 +566,43 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
@Override
|
||||
public StackValue visitObjectLiteralExpression(JetObjectLiteralExpression expression, StackValue receiver) {
|
||||
GeneratedAnonymousClassDescriptor descriptor = state.generateObjectLiteral(expression, this, context);
|
||||
Type type = Type.getObjectType(descriptor.getClassname());
|
||||
FunctionOrClosureCodegen closureCodegen = new FunctionOrClosureCodegen(this, context, state);
|
||||
GeneratedAnonymousClassDescriptor closure = state.generateObjectLiteral(expression, closureCodegen);
|
||||
Type type = Type.getObjectType(closure.getClassname());
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
String jvmDescriptor = descriptor.getConstructor().getDescriptor().replace("(","(" + typeMapper.jetImplementationType((ClassDescriptor) contextType()));
|
||||
v.invokespecial(descriptor.getClassname(), "<init>", jvmDescriptor);
|
||||
return StackValue.onStack(type);
|
||||
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(closure.getConstructor().getArgumentTypes()));
|
||||
|
||||
if (consArgTypes.size() > 0) {
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) {
|
||||
final Type sharedVarType = getSharedVarType(descriptor);
|
||||
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
|
||||
final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor);
|
||||
valueDescriptor.getOuterValue().put(sharedVarType, v);
|
||||
}
|
||||
|
||||
Method cons = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
||||
v.invokespecial(closure.getClassname(), "<init>", cons.getDescriptor());
|
||||
return StackValue.onStack(Type.getObjectType(closure.getClassname()));
|
||||
}
|
||||
|
||||
Type getSharedVarType(DeclarationDescriptor variableDescriptor) {
|
||||
if(!(variableDescriptor instanceof VariableDescriptor))
|
||||
return null;
|
||||
|
||||
Boolean aBoolean = bindingContext.get(BindingContext.MUST_BE_WRAPPED_IN_A_REF, (VariableDescriptor) variableDescriptor);
|
||||
if (aBoolean != null && aBoolean) {
|
||||
JetType outType = ((VariableDescriptor) variableDescriptor).getOutType();
|
||||
return StackValue.sharedTypeForType(typeMapper.mapType(outType));
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private StackValue generateBlock(List<JetElement> statements) {
|
||||
Label blockStart = new Label();
|
||||
v.mark(blockStart);
|
||||
@@ -584,7 +611,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (statement instanceof JetProperty) {
|
||||
final VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, statement);
|
||||
assert variableDescriptor != null;
|
||||
final Type type = typeMapper.mapType(variableDescriptor.getOutType());
|
||||
|
||||
final Type sharedVarType = getSharedVarType(variableDescriptor);
|
||||
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
|
||||
myMap.enter(variableDescriptor, type.getSize());
|
||||
}
|
||||
}
|
||||
@@ -608,10 +637,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetProperty var = (JetProperty) statement;
|
||||
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, var);
|
||||
assert variableDescriptor != null;
|
||||
Type outType = typeMapper.mapType(variableDescriptor.getOutType());
|
||||
|
||||
int index = myMap.leave(variableDescriptor);
|
||||
v.visitLocalVariable(var.getName(), outType.getDescriptor(), null, blockStart, blockEnd, index);
|
||||
|
||||
final Type sharedVarType = getSharedVarType(variableDescriptor);
|
||||
final Type type = sharedVarType != null ? sharedVarType : typeMapper.mapType(variableDescriptor.getOutType());
|
||||
if(sharedVarType != null) {
|
||||
v.aconst(null);
|
||||
v.store(index, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
v.visitLocalVariable(var.getName(), type.getDescriptor(), null, blockStart, blockEnd, index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,8 +735,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
else {
|
||||
int index = lookupLocal(descriptor);
|
||||
if (index >= 0) {
|
||||
Type sharedVarType = getSharedVarType(descriptor);
|
||||
final JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
||||
return StackValue.local(index, typeMapper.mapType(outType));
|
||||
if(sharedVarType != null) {
|
||||
return StackValue.shared(index, typeMapper.mapType(outType));
|
||||
}
|
||||
else {
|
||||
return StackValue.local(index, typeMapper.mapType(outType));
|
||||
}
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
@@ -785,6 +827,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
if (value == null) {
|
||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||
}
|
||||
|
||||
if(value instanceof StackValue.FieldForSharedVar) {
|
||||
StackValue.FieldForSharedVar fieldForSharedVar = (StackValue.FieldForSharedVar) value;
|
||||
Type sharedType = StackValue.sharedTypeForType(value.type);
|
||||
v.visitFieldInsn(Opcodes.GETFIELD, fieldForSharedVar.owner, fieldForSharedVar.name, sharedType.getDescriptor());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1617,12 +1665,27 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
|
||||
assert index >= 0;
|
||||
|
||||
final Type sharedVarType = getSharedVarType(variableDescriptor);
|
||||
assert variableDescriptor != null;
|
||||
Type varType = typeMapper.mapType(variableDescriptor.getOutType());
|
||||
if(sharedVarType != null) {
|
||||
v.anew(sharedVarType);
|
||||
v.dup();
|
||||
v.invokespecial(sharedVarType.getInternalName(), "<init>", "()V");
|
||||
v.store(index, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer != null) {
|
||||
assert variableDescriptor != null;
|
||||
Type type = typeMapper.mapType(variableDescriptor.getOutType());
|
||||
gen(initializer, type);
|
||||
v.store(index, type);
|
||||
if(sharedVarType == null) {
|
||||
gen(initializer, varType);
|
||||
v.store(index, varType);
|
||||
}
|
||||
else {
|
||||
v.load(index, JetTypeMapper.TYPE_OBJECT);
|
||||
gen(initializer, varType);
|
||||
v.putfield(sharedVarType.getInternalName(), "ref", sharedVarType == JetTypeMapper.TYPE_SHARED_VAR ? "Ljava/lang/Object;" : varType.getDescriptor());
|
||||
}
|
||||
}
|
||||
return StackValue.none();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.codegen;
|
||||
import gnu.trove.TObjectIntHashMap;
|
||||
import gnu.trove.TObjectIntIterator;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -98,6 +98,23 @@ public class FunctionCodegen {
|
||||
iv.areturn(jvmSignature.getReturnType());
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||
|
||||
Type sharedVarType = codegen.getSharedVarType(parameter);
|
||||
Type localVarType = state.getTypeMapper().mapType(parameter.getOutType());
|
||||
if(sharedVarType != null) {
|
||||
int index = frameMap.getIndex(parameter);
|
||||
mv.visitTypeInsn(Opcodes.NEW, sharedVarType.getInternalName());
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, sharedVarType.getInternalName(), "<init>", "()V");
|
||||
mv.visitVarInsn(localVarType.getOpcode(Opcodes.ILOAD), index);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, sharedVarType.getInternalName(), "ref", StackValue.refType(localVarType).getDescriptor());
|
||||
mv.visitVarInsn(sharedVarType.getOpcode(Opcodes.ISTORE), index);
|
||||
}
|
||||
}
|
||||
|
||||
codegen.returnExpression(bodyExpressions);
|
||||
}
|
||||
mv.visitMaxs(0, 0);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
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;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class FunctionOrClosureCodegen {
|
||||
public final GenerationState state;
|
||||
protected final ExpressionCodegen exprContext;
|
||||
protected final ClassContext context;
|
||||
protected ClassVisitor cv = null;
|
||||
public String name = null;
|
||||
protected Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = new LinkedHashMap<DeclarationDescriptor, EnclosedValueDescriptor>();
|
||||
|
||||
public FunctionOrClosureCodegen(ExpressionCodegen exprContext, ClassContext context, GenerationState state) {
|
||||
this.exprContext = exprContext;
|
||||
this.context = context;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public StackValue lookupInContext(DeclarationDescriptor d) {
|
||||
if (d instanceof VariableDescriptor) {
|
||||
VariableDescriptor vd = (VariableDescriptor) d;
|
||||
|
||||
EnclosedValueDescriptor answer = closure.get(vd);
|
||||
if (answer != null) return answer.getInnerValue();
|
||||
|
||||
final int idx = exprContext.lookupLocal(vd);
|
||||
if (idx < 0) return null;
|
||||
|
||||
final Type sharedVarType = exprContext.getSharedVarType(vd);
|
||||
Type localType = state.getTypeMapper().mapType(vd.getOutType());
|
||||
final Type type = sharedVarType != null ? sharedVarType : localType;
|
||||
|
||||
StackValue outerValue = StackValue.local(idx, type);
|
||||
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);
|
||||
|
||||
answer = new EnclosedValueDescriptor(d, innerValue, outerValue);
|
||||
closure.put(d, answer);
|
||||
|
||||
return innerValue;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -120,13 +121,19 @@ public class GenerationState {
|
||||
}
|
||||
}
|
||||
|
||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, ExpressionCodegen context, ClassContext classContext) {
|
||||
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(literal.getObjectDeclaration());
|
||||
public GeneratedAnonymousClassDescriptor generateObjectLiteral(JetObjectLiteralExpression literal, FunctionOrClosureCodegen closure) {
|
||||
JetObjectDeclaration objectDeclaration = literal.getObjectDeclaration();
|
||||
Pair<String, ClassVisitor> nameAndVisitor = forAnonymousSubclass(objectDeclaration);
|
||||
|
||||
final ClassContext objectContext = classContext.intoClass(getBindingContext().get(BindingContext.CLASS, literal.getObjectDeclaration()), OwnerKind.IMPLEMENTATION);
|
||||
closure.cv = nameAndVisitor.getSecond();
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
final ClassContext objectContext = closure.context.intoClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||
|
||||
new ImplementationBodyCodegen(literal.getObjectDeclaration(), objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, new Method("<init>", "()V"), false);
|
||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate();
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = closure.state.getBindingContext().get(BindingContext.CONSTRUCTOR, objectDeclaration);
|
||||
CallableMethod callableMethod = closure.state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
return new GeneratedAnonymousClassDescriptor(nameAndVisitor.first, callableMethod.getSignature(), false);
|
||||
}
|
||||
|
||||
public static void prepareAnonymousClasses(JetElement aClass, final JetTypeMapper typeMapper) {
|
||||
|
||||
@@ -225,6 +225,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
|
||||
method = callableMethod.getSignature();
|
||||
}
|
||||
|
||||
int firstClosureIndex = -1;
|
||||
if(context.closure != null) {
|
||||
final List<Type> consArgTypes = new LinkedList<Type>(Arrays.asList(method.getArgumentTypes()));
|
||||
|
||||
firstClosureIndex = consArgTypes.size()+1;
|
||||
|
||||
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
|
||||
for (DeclarationDescriptor descriptor : closure.keySet()) {
|
||||
final Type sharedVarType = context.closure.exprContext.getSharedVarType(descriptor);
|
||||
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
|
||||
}
|
||||
|
||||
method = new Method("<init>", Type.VOID_TYPE, consArgTypes.toArray(new Type[consArgTypes.size()]));
|
||||
}
|
||||
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
@@ -300,7 +316,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.putfield(classname, delegateField, fieldDesc);
|
||||
|
||||
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
final ClassContext delegateContext = context.intoClass(superClassDescriptor,
|
||||
final ClassContext delegateContext = context.intoClass(null, superClassDescriptor,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
|
||||
generateDelegates(superClass, delegateContext, overridden);
|
||||
@@ -322,6 +338,17 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
||||
}
|
||||
|
||||
if(context.closure != null) {
|
||||
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
|
||||
int k = 0;
|
||||
for (DeclarationDescriptor varDescr : closure.keySet()) {
|
||||
final Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType));
|
||||
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$" + (k+1), sharedVarType.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
generateInitializers(codegen, iv);
|
||||
|
||||
generateTraitMethods(codegen);
|
||||
|
||||
@@ -59,6 +59,15 @@ public class JetTypeMapper {
|
||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
|
||||
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
|
||||
public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/refs/SharedVar$Object");
|
||||
public static final Type TYPE_SHARED_INT = Type.getObjectType("jet/refs/SharedVar$Int");
|
||||
public static final Type TYPE_SHARED_DOUBLE = Type.getObjectType("jet/refs/SharedVar$Double");
|
||||
public static final Type TYPE_SHARED_FLOAT = Type.getObjectType("jet/refs/SharedVar$Float");
|
||||
public static final Type TYPE_SHARED_BYTE = Type.getObjectType("jet/refs/SharedVar$Byte");
|
||||
public static final Type TYPE_SHARED_SHORT = Type.getObjectType("jet/refs/SharedVar$Short");
|
||||
public static final Type TYPE_SHARED_CHAR = Type.getObjectType("jet/refs/SharedVar$Char");
|
||||
public static final Type TYPE_SHARED_LONG = Type.getObjectType("jet/refs/SharedVar$Long");
|
||||
public static final Type TYPE_SHARED_BOOLEAN = Type.getObjectType("jet/refs/SharedVar$Boolean");
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.objectweb.asm.commons.Method;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public abstract class StackValue {
|
||||
public final Type type;
|
||||
@@ -59,6 +60,10 @@ public abstract class StackValue {
|
||||
return new Local(index, type);
|
||||
}
|
||||
|
||||
public static StackValue shared(int index, Type type) {
|
||||
return new Shared(index, type);
|
||||
}
|
||||
|
||||
public static StackValue onStack(Type type) {
|
||||
return type == Type.VOID_TYPE ? none() : new OnStack(type);
|
||||
}
|
||||
@@ -225,7 +230,11 @@ public abstract class StackValue {
|
||||
public static StackValue none() {
|
||||
return None.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public static StackValue fieldForSharedVar(Type type, String name, String fieldName) {
|
||||
return new FieldForSharedVar(type, name, fieldName);
|
||||
}
|
||||
|
||||
private static class None extends StackValue {
|
||||
public static None INSTANCE = new None();
|
||||
private None() {
|
||||
@@ -496,9 +505,9 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
|
||||
private static class Field extends StackValue {
|
||||
private final String owner;
|
||||
private final String name;
|
||||
static class Field extends StackValue {
|
||||
final String owner;
|
||||
final String name;
|
||||
private final boolean isStatic;
|
||||
|
||||
public Field(Type type, String owner, String name, boolean isStatic) {
|
||||
@@ -531,9 +540,9 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
private static class InstanceField extends StackValue {
|
||||
private final String owner;
|
||||
private final String name;
|
||||
static class InstanceField extends StackValue {
|
||||
final String owner;
|
||||
final String name;
|
||||
|
||||
public InstanceField(Type type, String owner, String name) {
|
||||
super(type);
|
||||
@@ -625,4 +634,106 @@ public abstract class StackValue {
|
||||
generator.gen(expression, type);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Shared extends StackValue {
|
||||
private final int index;
|
||||
|
||||
public Shared(int index, Type type) {
|
||||
super(type);
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
v.load(index, JetTypeMapper.TYPE_OBJECT);
|
||||
Type refType = refType(this.type);
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
|
||||
StackValue.onStack(refType).coerce(this.type, v);
|
||||
StackValue.onStack(this.type).coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(InstructionAdapter v) {
|
||||
v.load(index, JetTypeMapper.TYPE_OBJECT);
|
||||
v.swap();
|
||||
Type refType = refType(this.type);
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
v.visitFieldInsn(Opcodes.PUTFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
public static Type sharedTypeForType(Type type) {
|
||||
switch(type.getSort()) {
|
||||
case Type.OBJECT:
|
||||
case Type.ARRAY:
|
||||
return JetTypeMapper.TYPE_SHARED_VAR;
|
||||
|
||||
case Type.BYTE:
|
||||
return JetTypeMapper.TYPE_SHARED_BYTE;
|
||||
|
||||
case Type.SHORT:
|
||||
return JetTypeMapper.TYPE_SHARED_SHORT;
|
||||
|
||||
case Type.CHAR:
|
||||
return JetTypeMapper.TYPE_SHARED_CHAR;
|
||||
|
||||
case Type.INT:
|
||||
return JetTypeMapper.TYPE_SHARED_INT;
|
||||
|
||||
case Type.BOOLEAN:
|
||||
return JetTypeMapper.TYPE_SHARED_BOOLEAN;
|
||||
|
||||
case Type.FLOAT:
|
||||
return JetTypeMapper.TYPE_SHARED_FLOAT;
|
||||
|
||||
case Type.DOUBLE:
|
||||
return JetTypeMapper.TYPE_SHARED_DOUBLE;
|
||||
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static Type refType(Type type) {
|
||||
if(type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY)
|
||||
return JetTypeMapper.TYPE_OBJECT;
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static class FieldForSharedVar extends StackValue {
|
||||
final String owner;
|
||||
final String name;
|
||||
|
||||
public FieldForSharedVar(Type type, String owner, String name) {
|
||||
super(type);
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dupReceiver(InstructionAdapter v, int below) {
|
||||
if (below == 1) {
|
||||
v.dupX1();
|
||||
}
|
||||
else {
|
||||
v.dup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
Type sharedType = sharedTypeForType(this.type);
|
||||
Type refType = refType(this.type);
|
||||
v.visitFieldInsn(Opcodes.GETFIELD, sharedType.getInternalName(), "ref", refType.getDescriptor());
|
||||
StackValue.onStack(refType).coerce(this.type, v);
|
||||
StackValue.onStack(this.type).coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(InstructionAdapter v) {
|
||||
v.visitFieldInsn(Opcodes.PUTFIELD, sharedTypeForType(type).getInternalName(), "ref", refType(type).getDescriptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
#!/bin/bash --posix
|
||||
#
|
||||
##############################################################################
|
||||
# Copyright 2002-2011, LAMP/EPFL
|
||||
# Copyright 2011, JetBrains
|
||||
#
|
||||
# This is free software; see the distribution for copying conditions.
|
||||
# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
##############################################################################
|
||||
|
||||
cygwin=false;
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
esac
|
||||
|
||||
# Finding the root folder for this Kotlin distribution
|
||||
SOURCE=$0;
|
||||
SCRIPT=`basename "$SOURCE"`;
|
||||
while [ -h "$SOURCE" ]; do
|
||||
SCRIPT=`basename "$SOURCE"`;
|
||||
LOOKUP=`ls -ld "$SOURCE"`;
|
||||
TARGET=`expr "$LOOKUP" : '.*-> \(.*\)$'`;
|
||||
if expr "${TARGET:-.}/" : '/.*/$' > /dev/null; then
|
||||
SOURCE=${TARGET:-.};
|
||||
else
|
||||
SOURCE=`dirname "$SOURCE"`/${TARGET:-.};
|
||||
fi;
|
||||
done;
|
||||
|
||||
# see #2092
|
||||
KOTLIN_HOME=`dirname "$SOURCE"`
|
||||
KOTLIN_HOME=`cd "$KOTLIN_HOME"; pwd -P`
|
||||
KOTLIN_HOME=`cd "$KOTLIN_HOME"/..; pwd`
|
||||
|
||||
# Remove spaces from KOTLIN_HOME on windows
|
||||
if $cygwin; then
|
||||
KOTLIN_HOME=`cygpath --windows --short-name "$KOTLIN_HOME"`
|
||||
KOTLIN_HOME=`cygpath --unix "$KOTLIN_HOME"`
|
||||
fi
|
||||
|
||||
# Constructing the extension classpath
|
||||
TOOL_CLASSPATH=""
|
||||
if [ -z "$TOOL_CLASSPATH" ] ; then
|
||||
for ext in "$KOTLIN_HOME"/lib/* ; do
|
||||
if [ -z "$TOOL_CLASSPATH" ] ; then
|
||||
TOOL_CLASSPATH="$ext"
|
||||
else
|
||||
TOOL_CLASSPATH="$TOOL_CLASSPATH:$ext"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
[ -n "$JAVA_OPTS" ] || JAVA_OPTS="-Xmx256M -Xms32M"
|
||||
|
||||
# break out -D and -J options and add them to JAVA_OPTS as well
|
||||
# so they reach the underlying JVM in time to do some good. The
|
||||
# -D options will be available as system properties.
|
||||
declare -a java_args
|
||||
declare -a kotlin_args
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-D*)
|
||||
# pass to kotlin as well: otherwise we lose it sometimes when we
|
||||
# need it, e.g. communicating with a server compiler.
|
||||
java_args=("${java_args[@]}" "$1")
|
||||
kotlin_args=("${kotlin_args[@]}" "$1")
|
||||
shift
|
||||
;;
|
||||
-J*)
|
||||
# as with -D, pass to scala even though it will almost
|
||||
# never be used.
|
||||
java_args=("${java_args[@]}" "${1:2}")
|
||||
kotlin_args=("${kotlin_args[@]}" "$1")
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
kotlin_args=("${kotlin_args[@]}" "$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# reset "$@" to the remaining args
|
||||
set -- "${kotlin_args[@]}"
|
||||
|
||||
if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
|
||||
"${JAVACMD:=java}" \
|
||||
$JAVA_OPTS \
|
||||
"${java_args[@]}" \
|
||||
${CPSELECT}${TOOL_CLASSPATH} \
|
||||
org.jetbrains.jet.cli.KotlinCompiler "$@"
|
||||
@@ -0,0 +1,51 @@
|
||||
rem based on scalac.bat from the Scala distribution
|
||||
rem ##########################################################################
|
||||
rem # Copyright 2002-2011, LAMP/EPFL
|
||||
rem # Copyright 2011, JetBrains
|
||||
rem #
|
||||
rem # This is free software; see the distribution for copying conditions.
|
||||
rem # There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
||||
rem # PARTICULAR PURPOSE.
|
||||
rem ##########################################################################
|
||||
@echo off
|
||||
|
||||
@setlocal
|
||||
call :set_home
|
||||
|
||||
if not "%JAVA_HOME%"=="" (
|
||||
if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe"
|
||||
)
|
||||
|
||||
if "%_JAVACMD%"=="" set _JAVACMD=java
|
||||
|
||||
rem We use the value of the JAVA_OPTS environment variable if defined
|
||||
set _JAVA_OPTS=-Xmx256M -Xms32M
|
||||
|
||||
set _TOOL_CLASSPATH=
|
||||
if "%_TOOL_CLASSPATH%"=="" (
|
||||
for %%f in ("%_KOTLIN_HOME%\lib\*") do call :add_cpath "%%f"
|
||||
for /d %%f in ("%_KOTLIN_HOME%\lib\*") do call :add_cpath "%%f"
|
||||
)
|
||||
|
||||
"%_JAVACMD%" %_JAVA_OPTS% cp "%_TOOL_CLASSPATH%" org.jetbrains.jet.cli.KotlinCompiler %*
|
||||
goto end
|
||||
|
||||
rem ##########################################################################
|
||||
rem # subroutines
|
||||
|
||||
:add_cpath
|
||||
if "%_TOOL_CLASSPATH%"=="" (
|
||||
set _TOOL_CLASSPATH=%~1
|
||||
) else (
|
||||
set _TOOL_CLASSPATH=%_TOOL_CLASSPATH%;%~1
|
||||
)
|
||||
goto :eof
|
||||
|
||||
:set_home
|
||||
set _BIN_DIR=
|
||||
for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi
|
||||
set _KOTLIN_HOME=%_BIN_DIR%..
|
||||
goto :eof
|
||||
|
||||
:end
|
||||
@endlocal
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="IDEA 10.x" jdkType="IDEA JDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.jetbrains.jet.cli;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.core.JavaCoreEnvironment;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import org.jetbrains.jet.codegen.ClassFileFactory;
|
||||
import org.jetbrains.jet.codegen.GenerationState;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
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.plugin.JetFileType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class KotlinCompiler {
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
if (args.length < 1) {
|
||||
System.out.println("Usage: KotlinCompiler <filename>");
|
||||
return;
|
||||
}
|
||||
String javaHome = System.getenv("JAVA_HOME");
|
||||
if (javaHome == null) {
|
||||
System.out.println("JAVA_HOME environment variable needs to be defined");
|
||||
return;
|
||||
}
|
||||
File rtJar = findRtJar(javaHome);
|
||||
if (rtJar == null || !rtJar.exists()) {
|
||||
System.out.print("No rt.jar found under JAVA_HOME");
|
||||
return;
|
||||
}
|
||||
|
||||
Disposable root = new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
};
|
||||
JavaCoreEnvironment environment = new JavaCoreEnvironment(root);
|
||||
environment.addToClasspath(rtJar);
|
||||
|
||||
environment.registerFileType(JetFileType.INSTANCE, "kt");
|
||||
environment.registerParserDefinition(new JetParserDefinition());
|
||||
VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(args [0]);
|
||||
|
||||
Project project = environment.getProject();
|
||||
GenerationState generationState = new GenerationState(project, false);
|
||||
List<JetNamespace> namespaces = Lists.newArrayList();
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
|
||||
if (psiFile instanceof JetFile) {
|
||||
namespaces.add(((JetFile) psiFile).getRootNamespace());
|
||||
}
|
||||
|
||||
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY);
|
||||
|
||||
boolean errors = false;
|
||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
|
||||
switch (diagnostic.getSeverity()) {
|
||||
case ERROR:
|
||||
errors = true;
|
||||
report(diagnostic);
|
||||
break;
|
||||
case INFO:
|
||||
report(diagnostic);
|
||||
break;
|
||||
case WARNING:
|
||||
report(diagnostic);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!errors) {
|
||||
generationState.compileCorrectNamespaces(bindingContext, namespaces);
|
||||
|
||||
final ClassFileFactory factory = generationState.getFactory();
|
||||
List<String> files = factory.files();
|
||||
for (String file : files) {
|
||||
File target = new File(vFile.getParent().getPath(), file);
|
||||
try {
|
||||
FileUtil.writeToFile(target, factory.asBytes(file));
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void report(Diagnostic diagnostic) {
|
||||
System.out.println(diagnostic.getMessage());
|
||||
}
|
||||
|
||||
private static File findRtJar(String javaHome) {
|
||||
File rtJar = new File(javaHome, "jre/lib/rt.jar");
|
||||
if (rtJar.exists()) {
|
||||
return rtJar;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -5,13 +5,20 @@ package org.jetbrains.jet.plugin;
|
||||
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class JetFileType extends LanguageFileType {
|
||||
public static final JetFileType INSTANCE = new JetFileType();
|
||||
private final Icon myIcon = IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png");
|
||||
private final NotNullLazyValue<Icon> myIcon = new NotNullLazyValue<Icon>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Icon compute() {
|
||||
return IconLoader.getIcon("/org/jetbrains/jet/plugin/icons/kotlin16x16.png");
|
||||
}
|
||||
};
|
||||
|
||||
private JetFileType() {
|
||||
super(JetLanguage.INSTANCE);
|
||||
@@ -33,7 +40,7 @@ public class JetFileType extends LanguageFileType {
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return myIcon;
|
||||
return myIcon.getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
fun box() : String {
|
||||
val cl = 39
|
||||
return if (sum(200, { cl }) == 239) "OK" else "FAIL"
|
||||
return if (sum(200, { val m = { val r = { cl }; r() }; m() }) == 239) "OK" else "FAIL"
|
||||
}
|
||||
|
||||
fun sum(arg:Int, f : fun () : Int) : Int {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import java.util.*
|
||||
|
||||
fun concat(l: List<String>): String? {
|
||||
val sb = StringBuilder()
|
||||
for(s in l) {
|
||||
val x = if(l.size() > 1) { "T" } else { "F" };
|
||||
sb.append(x)
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
class C() {
|
||||
val child = object {
|
||||
fun toString(): String = "child"
|
||||
class C(x: Int, val y : Int) {
|
||||
fun initChild(x: Int) : java.lang.Object {
|
||||
return object : java.lang.Object() {
|
||||
override fun toString(): String? {
|
||||
x = x + y
|
||||
return "child" + x
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val child = initChild(x)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val c = C()
|
||||
return if (c.child.toString() == "child") "OK" else "fail"
|
||||
val c = C(10,3)
|
||||
return if (c.child.toString() == "child13" && c.child.toString() == "child16" && c.child.toString() == "child19") "OK" else "fail"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
fun s0() : Boolean {
|
||||
val y = "222"
|
||||
val foo = {
|
||||
val bar = { y }
|
||||
bar ()
|
||||
}
|
||||
return foo() == "222"
|
||||
}
|
||||
|
||||
fun s1() : Boolean {
|
||||
var x = "222"
|
||||
val foo = {
|
||||
val bar = {
|
||||
x = "aaa"
|
||||
}
|
||||
bar ()
|
||||
}
|
||||
foo()
|
||||
return x == "aaa"
|
||||
}
|
||||
|
||||
fun t1() : Boolean {
|
||||
var x = "111"
|
||||
|
||||
val y = x + "22"
|
||||
val foo = {
|
||||
x = x + "45" + y
|
||||
x = x.substring(3)
|
||||
x += "aaa"
|
||||
()
|
||||
}
|
||||
foo()
|
||||
|
||||
x += "bbb"
|
||||
System.out?.println(x)
|
||||
return x == "4511122aaabbb"
|
||||
}
|
||||
|
||||
fun t2() : Boolean {
|
||||
var x = 111
|
||||
val y = x + 22
|
||||
val foo = {
|
||||
x = x + 5 + y
|
||||
x += 5
|
||||
x++
|
||||
()
|
||||
}
|
||||
foo()
|
||||
x -= 55
|
||||
System.out?.println(x)
|
||||
return x == 200
|
||||
}
|
||||
|
||||
fun t3() : Boolean {
|
||||
var x = true
|
||||
val foo = {
|
||||
x = false
|
||||
()
|
||||
}
|
||||
foo()
|
||||
return !x
|
||||
}
|
||||
|
||||
fun t4() : Boolean {
|
||||
var x = 100.flt
|
||||
val y = x + 22
|
||||
val foo = {
|
||||
x = x + 200.flt + y
|
||||
x += 18
|
||||
()
|
||||
}
|
||||
foo()
|
||||
System.out?.println(x)
|
||||
return x == 440.flt
|
||||
}
|
||||
|
||||
fun t5() : Boolean {
|
||||
var x = 100.dbl
|
||||
val y = x + 22
|
||||
val foo = {
|
||||
x = x + 200.dbl + y
|
||||
x -= 22
|
||||
()
|
||||
}
|
||||
foo()
|
||||
System.out?.println(x)
|
||||
return x == 400.dbl
|
||||
}
|
||||
|
||||
fun t6() : Boolean {
|
||||
var x = 20.byt
|
||||
val y = x + 22
|
||||
val foo = {
|
||||
x = (x + 20.byt + y).byt
|
||||
x += 2
|
||||
x--
|
||||
()
|
||||
}
|
||||
foo()
|
||||
System.out?.println(x)
|
||||
return x == 83.byt
|
||||
}
|
||||
|
||||
fun t7() : Boolean {
|
||||
var x : Char = 'a'
|
||||
val foo = {
|
||||
x = 'b'
|
||||
()
|
||||
}
|
||||
foo()
|
||||
System.out?.println(x)
|
||||
return x == 'b'
|
||||
}
|
||||
|
||||
fun t8() : Boolean {
|
||||
var x = 20.sht
|
||||
val foo = {
|
||||
val bar = {
|
||||
x = 30.sht
|
||||
()
|
||||
}
|
||||
bar()
|
||||
()
|
||||
}
|
||||
foo()
|
||||
return x == 30.sht
|
||||
}
|
||||
|
||||
fun t9(x: Int) : Boolean {
|
||||
while(x < 100) {
|
||||
x++
|
||||
}
|
||||
return x == 100
|
||||
}
|
||||
|
||||
fun t10() : Boolean {
|
||||
var y = 1
|
||||
val foo = {
|
||||
val bar = {
|
||||
y = y + 1
|
||||
}
|
||||
bar()
|
||||
}
|
||||
foo()
|
||||
return y == 2
|
||||
}
|
||||
|
||||
fun t11(x: Int) : Int {
|
||||
val foo = {
|
||||
x = x + 1
|
||||
val bar = {
|
||||
x = x + 1
|
||||
x += 3
|
||||
}
|
||||
bar()
|
||||
}
|
||||
while(x < 100) {
|
||||
foo()
|
||||
}
|
||||
return x
|
||||
}
|
||||
*/
|
||||
fun t12(x: Int) : Int {
|
||||
var y = x
|
||||
val runnable = object : Runnable {
|
||||
override fun run () {
|
||||
y = y + 1
|
||||
}
|
||||
}
|
||||
while(y < 100) {
|
||||
runnable.run()
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
/*
|
||||
if (!s0()) return "fail"
|
||||
if (!s1()) return "fail"
|
||||
if (!t1()) return "fail"
|
||||
if (!t2()) return "fail"
|
||||
if (!t3()) return "fail"
|
||||
if (!t4()) return "fail"
|
||||
if (!t5()) return "fail"
|
||||
if (!t6()) return "fail"
|
||||
if (!t7()) return "fail"
|
||||
if (!t8()) return "fail"
|
||||
if (!t9(0)) return "fail"
|
||||
if (!t10()) return "fail"
|
||||
if (t11(1) != 104) return "fail"
|
||||
*/
|
||||
if (t12(0) != 100) return "fail"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -190,4 +190,10 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
blackBoxFile("regressions/kt343.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testKt344 () throws Exception {
|
||||
loadFile("regressions/kt344.jet");
|
||||
System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class ClosuresGenTest extends CodegenTestCase {
|
||||
|
||||
public void testEnclosingLocalVariable() throws Exception {
|
||||
blackBoxFile("classes/enclosingLocalVariable.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testDoubleEnclosedLocalVariable() throws Exception {
|
||||
|
||||
@@ -86,6 +86,16 @@ public class ControlStructuresTest extends CodegenTestCase {
|
||||
assertEquals("IntelliJ IDEA", main.invoke(null, args));
|
||||
}
|
||||
|
||||
public void testIfBlock() throws Exception {
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
final Method main = generateFunction();
|
||||
List<String> args = Arrays.asList("IntelliJ", " ", "IDEA");
|
||||
assertEquals("TTT", main.invoke(null, args));
|
||||
args = Arrays.asList("JetBrains");
|
||||
assertEquals("F", main.invoke(null, args));
|
||||
}
|
||||
|
||||
public void testForInArray() throws Exception {
|
||||
loadFile();
|
||||
System.out.println(generateToText());
|
||||
|
||||
@@ -10,6 +10,7 @@ public class ObjectGenTest extends CodegenTestCase {
|
||||
|
||||
public void testObjectLiteral() throws Exception {
|
||||
blackBoxFile("objects/objectLiteral.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testMethodOnObject() throws Exception {
|
||||
|
||||
@@ -19,7 +19,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
||||
final Class aClass = loadImplementationClass(generateClassesInFile(), "PrivateVal");
|
||||
final Field[] fields = aClass.getDeclaredFields();
|
||||
assertEquals(2, fields.length); // $typeInfo, prop
|
||||
final Field field = fields[1];
|
||||
final Field field = fields[0];
|
||||
assertEquals("prop", field.getName());
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,7 @@ import org.jetbrains.jet.lang.resolve.calls.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.io.File;
|
||||
@@ -111,7 +109,7 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||
@NotNull
|
||||
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, JetType... parameterType) {
|
||||
List<JetType> parameterTypeList = Arrays.asList(parameterType);
|
||||
// ExpressionTypingServices typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
|
||||
// JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
|
||||
|
||||
CallResolver callResolver = new CallResolver(JetSemanticServices.createSemanticServices(getProject()), DataFlowInfo.getEmpty());
|
||||
OverloadResolutionResults<FunctionDescriptor> functions = callResolver.resolveExactSignature(
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package jet.refs;
|
||||
|
||||
public final class SharedVar {
|
||||
public static final class Object<T> {
|
||||
public T ref;
|
||||
}
|
||||
|
||||
public static final class Byte {
|
||||
public byte ref;
|
||||
}
|
||||
|
||||
public static final class Short {
|
||||
public short ref;
|
||||
}
|
||||
|
||||
public static final class Int {
|
||||
public int ref;
|
||||
}
|
||||
|
||||
public static final class Long {
|
||||
public long ref;
|
||||
}
|
||||
|
||||
public static final class Float {
|
||||
public float ref;
|
||||
}
|
||||
|
||||
public static final class Double {
|
||||
public double ref;
|
||||
}
|
||||
|
||||
public static final class Char {
|
||||
public char ref;
|
||||
}
|
||||
|
||||
public static final class Boolean {
|
||||
public boolean ref;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user