Merge remote branch 'origin'
This commit is contained in:
Generated
+8
-8
@@ -2,14 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="AntConfiguration">
|
||||
<defaultAnt bundledAnt="true" />
|
||||
<buildFile url="file://$PROJECT_DIR$/idea/buildLexer.xml">
|
||||
<additionalClassPath />
|
||||
<antReference projectDefault="true" />
|
||||
<customJdkName value="" />
|
||||
<maximumHeapSize value="128" />
|
||||
<maximumStackSize value="2" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/grammar/buildGrammarLexer.xml">
|
||||
<additionalClassPath />
|
||||
<antReference projectDefault="true" />
|
||||
@@ -26,6 +18,14 @@
|
||||
<maximumStackSize value="2" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
<buildFile url="file://$PROJECT_DIR$/compiler/frontend/buildLexer.xml">
|
||||
<additionalClassPath />
|
||||
<antReference projectDefault="true" />
|
||||
<customJdkName value="" />
|
||||
<maximumHeapSize value="128" />
|
||||
<maximumStackSize value="2" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="annotations">
|
||||
<CLASSES>
|
||||
<root url="jar://$IDEA_HOME$/lib/annotations.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+3
@@ -3,7 +3,10 @@
|
||||
<component name="ProjectModuleManager">
|
||||
<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$/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" />
|
||||
<module fileurl="file://$PROJECT_DIR$/grammar/grammar.iml" filepath="$PROJECT_DIR$/grammar/grammar.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/idea/idea.iml" filepath="$PROJECT_DIR$/idea/idea.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/stdlib/stdlib.iml" filepath="$PROJECT_DIR$/stdlib/stdlib.iml" />
|
||||
|
||||
Generated
+11
-10
@@ -51,16 +51,6 @@
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="java">
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="8" />
|
||||
<option name="TAB_SIZE" value="4" />
|
||||
<option name="USE_TAB_CHARACTER" value="false" />
|
||||
<option name="SMART_TABS" value="false" />
|
||||
<option name="LABEL_INDENT_SIZE" value="0" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<ADDITIONAL_INDENT_OPTIONS fileType="js">
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="8" />
|
||||
@@ -151,6 +141,17 @@
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
|
||||
<option name="USE_RELATIVE_INDENTS" value="false" />
|
||||
</ADDITIONAL_INDENT_OPTIONS>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||
<option name="TERNARY_OPERATION_WRAP" value="5" />
|
||||
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
|
||||
<option name="IF_BRACE_FORCE" value="1" />
|
||||
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
|
||||
<indentOptions />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JavaScript">
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
|
||||
Generated
+6
@@ -23,10 +23,16 @@
|
||||
</option>
|
||||
<envs />
|
||||
<patterns />
|
||||
<RunnerSettings RunnerId="Debug">
|
||||
<option name="DEBUG_PORT" value="53032" />
|
||||
<option name="TRANSPORT" value="0" />
|
||||
<option name="LOCAL" value="true" />
|
||||
</RunnerSettings>
|
||||
<RunnerSettings RunnerId="Profile ">
|
||||
<option name="myExternalizedOptions" value=" snapshots-dir= additional-options2=onexit\=snapshot " />
|
||||
</RunnerSettings>
|
||||
<RunnerSettings RunnerId="Run" />
|
||||
<ConfigurationWrapper RunnerId="Debug" />
|
||||
<ConfigurationWrapper RunnerId="Run" />
|
||||
<method />
|
||||
</configuration>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?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="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="library" name="asm" level="project" />
|
||||
<orderEntry type="module" module-name="stdlib" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
+7
-2
@@ -71,13 +71,17 @@ public abstract class ClassBodyCodegen {
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
try {
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
genNamedFunction((JetNamedFunction) declaration, functionCodegen);
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Error generating method " + myClass.getName() + "." + declaration.getName() + " in " + context, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void genNamedFunction(JetNamedFunction declaration, FunctionCodegen functionCodegen) {
|
||||
functionCodegen.gen(declaration);
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen) {
|
||||
OwnerKind kind = context.getContextKind();
|
||||
for (JetParameter p : getPrimaryConstructorParameters()) {
|
||||
@@ -89,7 +93,8 @@ public abstract class ClassBodyCodegen {
|
||||
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
}
|
||||
|
||||
if (!(kind instanceof OwnerKind.DelegateKind) && kind != OwnerKind.INTERFACE && state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
//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);
|
||||
}
|
||||
}
|
||||
+10
-27
@@ -9,6 +9,7 @@ import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ClassCodegen {
|
||||
private final GenerationState state;
|
||||
@@ -20,18 +21,10 @@ public class ClassCodegen {
|
||||
public void generate(ClassContext parentContext, JetClassOrObject aClass) {
|
||||
GenerationState.prepareAnonymousClasses((JetElement) aClass, state.getTypeMapper());
|
||||
|
||||
if (aClass instanceof JetObjectDeclaration) {
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
else {
|
||||
generateInterface(parentContext, aClass);
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
if (!ImplementationBodyCodegen.isEnum(aClass)) {
|
||||
generateImplementation(parentContext, aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
||||
}
|
||||
}
|
||||
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
|
||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||
@@ -40,26 +33,16 @@ public class ClassCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateInterface(ClassContext parentContext, JetClassOrObject aClass) {
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
final ClassVisitor visitor = state.forClassInterface(descriptor);
|
||||
new InterfaceBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.INTERFACE), visitor, state).generate();
|
||||
}
|
||||
|
||||
private void generateImplementation(ClassContext parentContext, JetClassOrObject aClass, OwnerKind kind) {
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
|
||||
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION
|
||||
? state.forClassImplementation(descriptor)
|
||||
: state.forClassDelegatingImplementation(descriptor);
|
||||
ClassVisitor v = state.forClassImplementation(descriptor);
|
||||
new ImplementationBodyCodegen(aClass, parentContext.intoClass(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void newTypeInfo(InstructionAdapter v, boolean isNullable, Type asmType) {
|
||||
v.anew(JetTypeMapper.TYPE_TYPEINFO);
|
||||
v.dup();
|
||||
v.aconst(asmType);
|
||||
v.aconst(isNullable);
|
||||
v.invokespecial("jet/typeinfo/TypeInfo", "<init>", "(Ljava/lang/Class;Z)V");
|
||||
}
|
||||
}
|
||||
+34
-14
@@ -7,10 +7,13 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ClassContext {
|
||||
public static final ClassContext STATIC = new ClassContext(null, OwnerKind.NAMESPACE, null, null, null);
|
||||
private final DeclarationDescriptor contextType;
|
||||
@@ -19,6 +22,8 @@ public class ClassContext {
|
||||
private final ClassContext parentContext;
|
||||
private final ClosureCodegen closure;
|
||||
private boolean thisWasUsed = false;
|
||||
|
||||
HashMap<JetType,Integer> typeInfoConstants;
|
||||
|
||||
public ClassContext(DeclarationDescriptor contextType, OwnerKind contextKind, StackValue thisExpression, ClassContext parentContext, ClosureCodegen closureCodegen) {
|
||||
this.contextType = contextType;
|
||||
@@ -32,12 +37,19 @@ public class ClassContext {
|
||||
return contextType;
|
||||
}
|
||||
|
||||
public String getNamespaceClassName() {
|
||||
if(parentContext != STATIC)
|
||||
return parentContext.getNamespaceClassName();
|
||||
|
||||
return NamespaceCodegen.getJVMClassName(contextType.getName());
|
||||
}
|
||||
|
||||
public OwnerKind getContextKind() {
|
||||
return contextKind;
|
||||
}
|
||||
|
||||
public StackValue getThisExpression() {
|
||||
if (parentContext == null) return null;
|
||||
if (parentContext == null) return StackValue.none();
|
||||
|
||||
thisWasUsed = true;
|
||||
if (thisExpression != null) return thisExpression;
|
||||
@@ -50,14 +62,7 @@ public class ClassContext {
|
||||
|
||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind) {
|
||||
final StackValue thisValue;
|
||||
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||
thisValue = StackValue.instanceField(JetTypeMapper.jetInterfaceType(descriptor),
|
||||
JetTypeMapper.jetDelegatingImplementationType(descriptor).getInternalName(),
|
||||
"$this");
|
||||
}
|
||||
else {
|
||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
thisValue = StackValue.local(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
return new ClassContext(descriptor, kind, thisValue, this, null);
|
||||
}
|
||||
@@ -68,7 +73,7 @@ public class ClassContext {
|
||||
thisIdx++;
|
||||
}
|
||||
|
||||
final boolean hasReceiver = descriptor.getReceiverType() != null;
|
||||
final boolean hasReceiver = descriptor.getReceiver().exists();
|
||||
if (hasReceiver) {
|
||||
thisIdx++;
|
||||
}
|
||||
@@ -98,12 +103,12 @@ public class ClassContext {
|
||||
return frameMap;
|
||||
}
|
||||
|
||||
private JetType receiverType() {
|
||||
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverType() : null;
|
||||
private ReceiverDescriptor receiver() {
|
||||
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
|
||||
}
|
||||
|
||||
private boolean hasReceiver() {
|
||||
return receiverType() != null;
|
||||
return receiver().exists();
|
||||
}
|
||||
|
||||
public ClassContext getParentContext() {
|
||||
@@ -150,7 +155,7 @@ public class ClassContext {
|
||||
public Type enclosingClassType(JetTypeMapper mapper) {
|
||||
DeclarationDescriptor descriptor = getContextDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.INTERFACE));
|
||||
return Type.getObjectType(mapper.jvmName((ClassDescriptor) descriptor, OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
|
||||
if (descriptor instanceof NamespaceDescriptor) {
|
||||
@@ -164,4 +169,19 @@ public class ClassContext {
|
||||
final ClassContext parent = getParentContext();
|
||||
return parent != null ? parent.enclosingClassType(mapper) : null;
|
||||
}
|
||||
|
||||
public int getTypeInfoConstantIndex(JetType type) {
|
||||
if(parentContext != STATIC)
|
||||
return parentContext.getTypeInfoConstantIndex(type);
|
||||
|
||||
if(typeInfoConstants == null)
|
||||
typeInfoConstants = new HashMap<JetType, Integer>();
|
||||
|
||||
Integer index = typeInfoConstants.get(type);
|
||||
if(index == null) {
|
||||
index = typeInfoConstants.size();
|
||||
typeInfoConstants.put(type, index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
+7
-6
@@ -11,6 +11,7 @@ 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.ClassVisitor;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
@@ -41,7 +42,7 @@ public class ClosureCodegen {
|
||||
}
|
||||
|
||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||
boolean isExtensionFunction = fd.getReceiverType() != null;
|
||||
boolean isExtensionFunction = fd.getReceiver().exists();
|
||||
int paramCount = fd.getValueParameters().size();
|
||||
if (isExtensionFunction) {
|
||||
paramCount++;
|
||||
@@ -150,11 +151,11 @@ public class ClosureCodegen {
|
||||
|
||||
iv.load(0, Type.getObjectType(className));
|
||||
|
||||
final JetType receiverType = funDescriptor.getReceiverType();
|
||||
final ReceiverDescriptor receiver = funDescriptor.getReceiver();
|
||||
int count = 1;
|
||||
if (receiverType != null) {
|
||||
if (receiver.exists()) {
|
||||
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiverType), iv);
|
||||
StackValue.onStack(JetTypeMapper.TYPE_OBJECT).upcast(state.getTypeMapper().mapType(receiver.getType()), iv);
|
||||
count++;
|
||||
}
|
||||
|
||||
@@ -228,7 +229,7 @@ public class ClosureCodegen {
|
||||
|
||||
public static String getInternalClassName(FunctionDescriptor descriptor) {
|
||||
final int paramCount = descriptor.getValueParameters().size();
|
||||
if (descriptor.getReceiverType() != null) {
|
||||
if (descriptor.getReceiver().exists()) {
|
||||
return "jet/ExtensionFunction" + paramCount;
|
||||
}
|
||||
else {
|
||||
@@ -249,7 +250,7 @@ public class ClosureCodegen {
|
||||
Method descriptor = erasedInvokeSignature(fd);
|
||||
String owner = getInternalClassName(fd);
|
||||
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
||||
if (fd.getReceiverType() != null) {
|
||||
if (fd.getReceiver().exists()) {
|
||||
result.setNeedsReceiver(null);
|
||||
}
|
||||
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class CodegenUtil {
|
||||
private CodegenUtil() {
|
||||
}
|
||||
|
||||
public static boolean isInterface(DeclarationDescriptor descriptor) {
|
||||
return descriptor instanceof ClassDescriptor && ((ClassDescriptor)descriptor).getKind() == ClassKind.TRAIT;
|
||||
}
|
||||
|
||||
public static boolean isInterface(JetType type) {
|
||||
return isInterface(type.getConstructor().getDeclarationDescriptor());
|
||||
}
|
||||
|
||||
public static boolean isClassObject(DeclarationDescriptor descriptor) {
|
||||
if(descriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor;
|
||||
if(classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||
if(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) classDescriptor.getContainingDeclaration();
|
||||
if(classDescriptor.getDefaultType().equals(containingDeclaration.getClassObjectType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasThis0(ClassDescriptor classDescriptor) {
|
||||
return getOuterClassDescriptor(classDescriptor) != null && !isClassObject(classDescriptor);
|
||||
}
|
||||
|
||||
public static ClassDescriptor getOuterClassDescriptor(DeclarationDescriptor descriptor) {
|
||||
DeclarationDescriptor outerDescriptor = descriptor.getContainingDeclaration();
|
||||
while(outerDescriptor != null) {
|
||||
if(outerDescriptor instanceof ClassDescriptor)
|
||||
break;
|
||||
|
||||
outerDescriptor = outerDescriptor.getContainingDeclaration();
|
||||
}
|
||||
return (ClassDescriptor) outerDescriptor;
|
||||
}
|
||||
|
||||
public static boolean hasOuterTypeInfo(ClassDescriptor descriptor) {
|
||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(descriptor);
|
||||
if(outerClassDescriptor == null)
|
||||
return false;
|
||||
|
||||
if(outerClassDescriptor.getTypeConstructor().getParameters().size() > 0)
|
||||
return true;
|
||||
|
||||
return hasOuterTypeInfo(outerClassDescriptor);
|
||||
}
|
||||
|
||||
public static boolean hasTypeInfoField(JetType type) {
|
||||
if(type.getConstructor().getParameters().size() > 0)
|
||||
return true;
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(hasTypeInfoField(jetType))
|
||||
return true;
|
||||
}
|
||||
|
||||
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
|
||||
if(outerClassDescriptor == null)
|
||||
return false;
|
||||
|
||||
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
|
||||
}
|
||||
|
||||
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
|
||||
if(!exceptOwn) {
|
||||
if(!isInterface(type))
|
||||
if(hasTypeInfoField(type))
|
||||
return true;
|
||||
}
|
||||
|
||||
for (JetType jetType : type.getConstructor().getSupertypes()) {
|
||||
if(hasDerivedTypeInfoField(jetType, false))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Type arrayElementType(Type type) {
|
||||
return Type.getType(type.getDescriptor().substring(1));
|
||||
}
|
||||
}
|
||||
+2
-13
@@ -14,22 +14,16 @@ import java.util.List;
|
||||
*/
|
||||
public class ConstructorFrameMap extends FrameMap {
|
||||
private int myOuterThisIndex = -1;
|
||||
private int myDelegateThisIndex = -1;
|
||||
private int myFirstTypeParameter = -1;
|
||||
private int myTypeParameterCount = 0;
|
||||
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, OwnerKind kind) {
|
||||
public ConstructorFrameMap(CallableMethod callableMethod, @Nullable ConstructorDescriptor descriptor, ClassDescriptor classDescriptor, OwnerKind kind) {
|
||||
enterTemp(); // this
|
||||
ClassDescriptor classDescriptor = null;
|
||||
if (descriptor != null) {
|
||||
classDescriptor = descriptor.getContainingDeclaration();
|
||||
if (classDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
||||
myOuterThisIndex = enterTemp(); // outer class instance
|
||||
}
|
||||
}
|
||||
if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||
myDelegateThisIndex = enterTemp(); // $this
|
||||
}
|
||||
|
||||
List<Type> explicitArgTypes = callableMethod.getValueParameterTypes();
|
||||
|
||||
@@ -41,7 +35,6 @@ public class ConstructorFrameMap extends FrameMap {
|
||||
enter(parameter, explicitArgTypes.get(i).getSize());
|
||||
}
|
||||
|
||||
|
||||
if (classDescriptor != null) {
|
||||
myTypeParameterCount = classDescriptor.getTypeConstructor().getParameters().size();
|
||||
if (kind == OwnerKind.IMPLEMENTATION) {
|
||||
@@ -59,10 +52,6 @@ public class ConstructorFrameMap extends FrameMap {
|
||||
return myOuterThisIndex;
|
||||
}
|
||||
|
||||
public int getDelegateThisIndex() {
|
||||
return myDelegateThisIndex;
|
||||
}
|
||||
|
||||
public int getFirstTypeParameter() {
|
||||
return myFirstTypeParameter;
|
||||
}
|
||||
+838
-425
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
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.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author yole
|
||||
*/
|
||||
public class FunctionCodegen {
|
||||
private final ClassContext owner;
|
||||
private final ClassVisitor v;
|
||||
private final GenerationState state;
|
||||
|
||||
public FunctionCodegen(ClassContext owner, ClassVisitor v, GenerationState state) {
|
||||
this.owner = owner;
|
||||
this.v = v;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public void gen(JetNamedFunction f) {
|
||||
Method method = state.getTypeMapper().mapToCallableMethod(f, owner.getContextKind()).getSignature();
|
||||
final FunctionDescriptor functionDescriptor = state.getBindingContext().get(BindingContext.FUNCTION, f);
|
||||
generateMethod(f, method, functionDescriptor);
|
||||
}
|
||||
|
||||
public void generateMethod(JetDeclarationWithBody f, Method jvmMethod, FunctionDescriptor functionDescriptor) {
|
||||
ClassContext funContext = owner.intoFunction(functionDescriptor);
|
||||
|
||||
final JetExpression bodyExpression = f.getBodyExpression();
|
||||
generatedMethod(bodyExpression, jvmMethod, funContext, functionDescriptor);
|
||||
}
|
||||
|
||||
private void generatedMethod(JetExpression bodyExpressions,
|
||||
Method jvmSignature,
|
||||
ClassContext context,
|
||||
FunctionDescriptor functionDescriptor)
|
||||
{
|
||||
List<ValueParameterDescriptor> paramDescrs = functionDescriptor.getValueParameters();
|
||||
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
|
||||
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
OwnerKind kind = context.getContextKind();
|
||||
|
||||
if(kind == OwnerKind.TRAIT_IMPL && bodyExpressions == null)
|
||||
return;
|
||||
|
||||
boolean isStatic = kind == OwnerKind.NAMESPACE || kind == OwnerKind.TRAIT_IMPL;
|
||||
if (isStatic) flags |= Opcodes.ACC_STATIC;
|
||||
|
||||
boolean isAbstract = !isStatic && (bodyExpressions == null || CodegenUtil.isInterface(functionDescriptor.getContainingDeclaration()));
|
||||
if (isAbstract) flags |= Opcodes.ACC_ABSTRACT;
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), jvmSignature.getDescriptor(), null, null);
|
||||
if (!isAbstract) {
|
||||
mv.visitCode();
|
||||
FrameMap frameMap = context.prepareFrame();
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, jvmSignature.getReturnType(), context, state);
|
||||
|
||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||
for (int i = 0; i < paramDescrs.size(); i++) {
|
||||
ValueParameterDescriptor parameter = paramDescrs.get(i);
|
||||
frameMap.enter(parameter, argTypes[i].getSize());
|
||||
}
|
||||
|
||||
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
|
||||
int slot = frameMap.enterTemp();
|
||||
codegen.addTypeParameter(typeParameterDescriptor, StackValue.local(slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
if (kind instanceof OwnerKind.DelegateKind) {
|
||||
OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind;
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||
for (int i = 0; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(i + 1, argType);
|
||||
}
|
||||
iv.invokeinterface(dk.getOwnerClass(), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
iv.areturn(jvmSignature.getReturnType());
|
||||
}
|
||||
else {
|
||||
codegen.returnExpression(bodyExpressions);
|
||||
}
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
generateBridgeIfNeeded(owner, state, v, jvmSignature, functionDescriptor, kind);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateBridgeIfNeeded(ClassContext owner, GenerationState state, ClassVisitor v, Method jvmSignature, FunctionDescriptor functionDescriptor, OwnerKind kind) {
|
||||
Set<? extends FunctionDescriptor> overriddenFunctions = functionDescriptor.getOverriddenDescriptors();
|
||||
if(kind != OwnerKind.TRAIT_IMPL) {
|
||||
for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
|
||||
// TODO should we check params here as well?
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, overriddenFunction);
|
||||
}
|
||||
checkOverride(owner, state, v, jvmSignature, functionDescriptor, functionDescriptor.getOriginal());
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkOverride(ClassContext owner, GenerationState state, ClassVisitor 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 = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(flags, jvmSignature.getName(), overriden.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
Type[] argTypes = jvmSignature.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
if(argType.getSort() == Type.OBJECT) {
|
||||
iv.checkcast(argType);
|
||||
}
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getTypeMapper().jvmName((ClassDescriptor) owner.getContextDescriptor(), OwnerKind.IMPLEMENTATION), jvmSignature.getName(), jvmSignature.getDescriptor());
|
||||
if(JetTypeMapper.isPrimitive(jvmSignature.getReturnType()) && !JetTypeMapper.isPrimitive(overriden.getReturnType()))
|
||||
StackValue.valueOf(iv, jvmSignature.getReturnType());
|
||||
if(jvmSignature.getReturnType() == Type.VOID_TYPE)
|
||||
iv.aconst(null);
|
||||
iv.areturn(overriden.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+29
-8
@@ -7,16 +7,19 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
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;
|
||||
|
||||
public class GenerationState {
|
||||
private final ClassFileFactory factory;
|
||||
private final Project project;
|
||||
@@ -69,8 +72,8 @@ public class GenerationState {
|
||||
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.IMPLEMENTATION) + ".class");
|
||||
}
|
||||
|
||||
public ClassVisitor forClassDelegatingImplementation(ClassDescriptor aClass) {
|
||||
return factory.newVisitor(JetTypeMapper.jvmNameForDelegatingImplementation(aClass) + ".class");
|
||||
public ClassVisitor forTraitImplementation(ClassDescriptor aClass) {
|
||||
return factory.newVisitor(typeMapper.jvmName(aClass, OwnerKind.TRAIT_IMPL) + ".class");
|
||||
}
|
||||
|
||||
public Pair<String, ClassVisitor> forAnonymousSubclass(JetExpression expression) {
|
||||
@@ -85,13 +88,31 @@ public class GenerationState {
|
||||
|
||||
public void compile(JetFile psiFile) {
|
||||
final JetNamespace namespace = psiFile.getRootNamespace();
|
||||
NamespaceCodegen codegen = forNamespace(namespace);
|
||||
final BindingContext bindingContext = AnalyzingUtils.analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||
bindingContexts.push(bindingContext);
|
||||
final BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespace(namespace, JetControlFlowDataTraceFactory.EMPTY);
|
||||
AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||
compileCorrectNamespaces(bindingContext, Collections.singletonList(namespace));
|
||||
// NamespaceCodegen codegen = forNamespace(namespace);
|
||||
// bindingContexts.push(bindingContext);
|
||||
// typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
// try {
|
||||
// AnalyzingUtils.throwExceptionOnErrors(bindingContext);
|
||||
//
|
||||
// codegen.generate(namespace);
|
||||
// }
|
||||
// finally {
|
||||
// bindingContexts.pop();
|
||||
// typeMapper = null;
|
||||
// }
|
||||
}
|
||||
|
||||
public void compileCorrectNamespaces(BindingContext bindingContext, List<JetNamespace> namespaces) {
|
||||
typeMapper = new JetTypeMapper(standardLibrary, bindingContext);
|
||||
bindingContexts.push(bindingContext);
|
||||
try {
|
||||
AnalyzingUtils.applyHandler(ErrorHandler.THROW_EXCEPTION, bindingContext);
|
||||
codegen.generate(namespace);
|
||||
for (JetNamespace namespace : namespaces) {
|
||||
NamespaceCodegen codegen = forNamespace(namespace);
|
||||
codegen.generate(namespace);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
bindingContexts.pop();
|
||||
@@ -0,0 +1,788 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||
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.commons.InstructionAdapter;
|
||||
import org.objectweb.asm.commons.Method;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private JetDelegationSpecifier superCall;
|
||||
private String superClass = "java/lang/Object";
|
||||
|
||||
public ImplementationBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||
super(aClass, context, v, state);
|
||||
}
|
||||
|
||||
private Set<String> getSuperInterfaces(JetClassOrObject aClass) {
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
||||
String superClassName = null;
|
||||
Set<String> superInterfaces = new LinkedHashSet<String>();
|
||||
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
PsiElement superPsi = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
|
||||
if (superPsi instanceof PsiClass) {
|
||||
PsiClass psiClass = (PsiClass) superPsi;
|
||||
String fqn = psiClass.getQualifiedName();
|
||||
if (psiClass.isInterface()) {
|
||||
superInterfaces.add(fqn.replace('.', '/'));
|
||||
}
|
||||
else {
|
||||
if (superClassName == null) {
|
||||
superClassName = fqn.replace('.', '/');
|
||||
|
||||
while (psiClass != null) {
|
||||
for (PsiClass ifs : psiClass.getInterfaces()) {
|
||||
superInterfaces.add(ifs.getQualifiedName().replace('.', '/'));
|
||||
}
|
||||
psiClass = psiClass.getSuperClass();
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Cannot determine single class to inherit from");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(superPsi == null || ((JetClass)superPsi).isTrait())
|
||||
superInterfaces.add(JetTypeMapper.jvmNameForInterface(superClassDescriptor));
|
||||
}
|
||||
}
|
||||
return superInterfaces;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
getSuperClass();
|
||||
|
||||
List<String> interfaces = new ArrayList<String>();
|
||||
interfaces.add("jet/JetObject");
|
||||
interfaces.addAll(getSuperInterfaces(myClass));
|
||||
|
||||
boolean isAbstract = false;
|
||||
boolean isInterface = false;
|
||||
if(myClass instanceof JetClass) {
|
||||
if(((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))
|
||||
isAbstract = true;
|
||||
if(((JetClass) myClass).isTrait()) {
|
||||
isAbstract = true;
|
||||
isInterface = true;
|
||||
}
|
||||
}
|
||||
|
||||
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.visitSource(myClass.getContainingFile().getName(), null);
|
||||
|
||||
if(descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
v.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.visit("value", SignatureUtil.classToSignature((JetClass)myClass, state.getBindingContext(), state.getTypeMapper()));
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private String jvmName() {
|
||||
return state.getTypeMapper().jvmName(descriptor, kind);
|
||||
}
|
||||
|
||||
protected void getSuperClass() {
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||
|
||||
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
||||
return;
|
||||
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
final PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
if (declaration != null) {
|
||||
if (declaration instanceof PsiClass) {
|
||||
if (!((PsiClass) declaration).isInterface()) {
|
||||
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
|
||||
superCall = specifier;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(declaration instanceof JetClass) {
|
||||
if(!((JetClass) declaration).isTrait()) {
|
||||
superClass = state.getTypeMapper().jvmName(superClassDescriptor, kind);
|
||||
superCall = specifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
generateFieldForObjectInstance();
|
||||
generateFieldForClassObject();
|
||||
|
||||
try {
|
||||
generatePrimaryConstructor();
|
||||
}
|
||||
catch(RuntimeException e) {
|
||||
throw new RuntimeException("Error generating primary constructor of class " + myClass.getName() + " with kind " + kind, e);
|
||||
}
|
||||
|
||||
generateGetTypeInfo();
|
||||
//genGetSuperTypesTypeInfo();
|
||||
}
|
||||
|
||||
private void generateFieldForObjectInstance() {
|
||||
if (isNonLiteralObject()) {
|
||||
Type type = JetTypeMapper.jetImplementationType(descriptor);
|
||||
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "$instance", type.getDescriptor(), null, null);
|
||||
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
String name = jvmName();
|
||||
v.anew(Type.getObjectType(name));
|
||||
v.dup();
|
||||
v.invokespecial(name, "<init>", "()V");
|
||||
v.putstatic(name, "$instance", JetTypeMapper.jetImplementationType(descriptor).getDescriptor());
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFieldForClassObject() {
|
||||
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);
|
||||
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
String name = state.getTypeMapper().jvmName(classObject);
|
||||
final Type classObjectType = Type.getObjectType(name);
|
||||
v.anew(classObjectType);
|
||||
v.dup();
|
||||
v.invokespecial(name, "<init>", "()V");
|
||||
v.putstatic(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$classobj",
|
||||
classObjectType.getDescriptor());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected void generatePrimaryConstructor() {
|
||||
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
||||
return;
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, myClass);
|
||||
|
||||
Method method;
|
||||
CallableMethod callableMethod;
|
||||
if (constructorDescriptor == null) {
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
if (CodegenUtil.hasThis0(descriptor)) {
|
||||
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeConstructor().getParameters();
|
||||
for (int n = typeParameters.size(); n > 0; n--) {
|
||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||
}
|
||||
|
||||
method = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
||||
}
|
||||
else {
|
||||
callableMethod = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
|
||||
method = callableMethod.getSignature();
|
||||
}
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO
|
||||
final MethodVisitor mv = v.visitMethod(flags, "<init>", method.getDescriptor(), null, null);
|
||||
mv.visitCode();
|
||||
|
||||
List<ValueParameterDescriptor> paramDescrs = constructorDescriptor != null
|
||||
? constructorDescriptor.getValueParameters()
|
||||
: Collections.<ValueParameterDescriptor>emptyList();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(callableMethod, constructorDescriptor, descriptor, kind);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
|
||||
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||
if(constructorDescriptor != null)
|
||||
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
else
|
||||
codegen.addTypeParameter(descriptor.getTypeConstructor().getParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||
final Type classType = Type.getType("L" + classname + ";");
|
||||
|
||||
HashSet<FunctionDescriptor> overridden = new HashSet<FunctionDescriptor>();
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (declaration instanceof JetFunction) {
|
||||
overridden.addAll(state.getBindingContext().get(BindingContext.FUNCTION, declaration).getOverriddenDescriptors());
|
||||
}
|
||||
}
|
||||
|
||||
if (superCall == null || superCall instanceof JetDelegatorToSuperClass) {
|
||||
iv.load(0, Type.getType("L" + superClass + ";"));
|
||||
if(superCall == null) {
|
||||
iv.invokespecial(superClass, "<init>", "()V");
|
||||
}
|
||||
else {
|
||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, superCall.getTypeReference());
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
if (CodegenUtil.hasThis0(superClassDescriptor)) {
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
parameterTypes.add(state.getTypeMapper().jvmType(CodegenUtil.getOuterClassDescriptor(descriptor), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
for(TypeProjection typeParameterDescriptor : superType.getArguments()) {
|
||||
codegen.generateTypeInfo(typeParameterDescriptor.getType());
|
||||
parameterTypes.add(JetTypeMapper.TYPE_TYPEINFO);
|
||||
}
|
||||
Method superCallMethod = new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
iv.invokespecial(state.getTypeMapper().jvmName(superClassDescriptor, OwnerKind.IMPLEMENTATION), "<init>", superCallMethod.getDescriptor());
|
||||
}
|
||||
}
|
||||
else {
|
||||
iv.load(0, classType);
|
||||
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
||||
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap);
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
for (JetDelegationSpecifier specifier : myClass.getDelegationSpecifiers()) {
|
||||
if(specifier == superCall)
|
||||
continue;
|
||||
|
||||
if (specifier instanceof JetDelegatorByExpressionSpecifier) {
|
||||
iv.load(0, classType);
|
||||
codegen.genToJVMStack(((JetDelegatorByExpressionSpecifier) specifier).getDelegateExpression());
|
||||
|
||||
JetType superType = state.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
String delegateField = "$delegate_" + n;
|
||||
Type fieldType = JetTypeMapper.jetInterfaceType(superClassDescriptor);
|
||||
String fieldDesc = fieldType.getDescriptor();
|
||||
v.visitField(Opcodes.ACC_PRIVATE, delegateField, fieldDesc, /*TODO*/null, null);
|
||||
iv.putfield(classname, delegateField, fieldDesc);
|
||||
|
||||
JetClass superClass = (JetClass) state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
final ClassContext delegateContext = context.intoClass(superClassDescriptor,
|
||||
new OwnerKind.DelegateKind(StackValue.field(fieldType, classname, delegateField, false),
|
||||
JetTypeMapper.jvmNameForInterface(superClassDescriptor)));
|
||||
generateDelegates(superClass, delegateContext, overridden);
|
||||
}
|
||||
}
|
||||
|
||||
final ClassDescriptor outerDescriptor = getOuterClassDescriptor();
|
||||
if (outerDescriptor != null && outerDescriptor.getKind() != ClassKind.OBJECT) {
|
||||
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);
|
||||
iv.load(0, classType);
|
||||
iv.load(frameMap.getOuterThisIndex(), type);
|
||||
iv.putfield(classname, fieldName, interfaceDesc);
|
||||
}
|
||||
|
||||
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
|
||||
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
|
||||
}
|
||||
|
||||
generateInitializers(codegen, iv);
|
||||
|
||||
generateTraitMethods(codegen);
|
||||
|
||||
int curParam = 0;
|
||||
List<JetParameter> constructorParameters = getPrimaryConstructorParameters();
|
||||
for (JetParameter parameter : constructorParameters) {
|
||||
if (parameter.getValOrVarNode() != null) {
|
||||
VariableDescriptor descriptor = paramDescrs.get(curParam);
|
||||
Type type = state.getTypeMapper().mapType(descriptor.getOutType());
|
||||
iv.load(0, classType);
|
||||
iv.load(frameMap.getIndex(descriptor), type);
|
||||
iv.putfield(classname, descriptor.getName(), type.getDescriptor());
|
||||
}
|
||||
curParam++;
|
||||
}
|
||||
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateTraitMethods(ExpressionCodegen codegen) {
|
||||
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait() || ((JetClass)myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD))
|
||||
return;
|
||||
|
||||
for (CallableDescriptor callableDescriptor : OverridingUtil.getEffectiveMembers(descriptor)) {
|
||||
if(callableDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor fun = (FunctionDescriptor) callableDescriptor;
|
||||
DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration();
|
||||
if(containingDeclaration instanceof ClassDescriptor) {
|
||||
ClassDescriptor declaration = (ClassDescriptor) containingDeclaration;
|
||||
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaration);
|
||||
if(psiElement instanceof JetClass) {
|
||||
JetClass jetClass = (JetClass) psiElement;
|
||||
if(jetClass.isTrait()) {
|
||||
int flags = Opcodes.ACC_PUBLIC; // TODO.
|
||||
|
||||
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);
|
||||
mv.visitCode();
|
||||
|
||||
codegen.generateThisOrOuter(descriptor);
|
||||
|
||||
Type[] argTypes = function.getArgumentTypes();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
for (int i = 0, reg = 1; i < argTypes.length; i++) {
|
||||
Type argType = argTypes[i];
|
||||
iv.load(reg, argType);
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(declaration, state.getBindingContext());
|
||||
Type type = state.getTypeMapper().mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = declaration.getDefaultType();
|
||||
type = state.getTypeMapper().mapType(jetType);
|
||||
}
|
||||
|
||||
String fdescriptor = functionOriginal.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||
if(function.getReturnType().getSort() == Type.OBJECT) {
|
||||
iv.checkcast(function.getReturnType());
|
||||
}
|
||||
iv.areturn(function.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
FunctionCodegen.generateBridgeIfNeeded(context, state, v, function, fun, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ClassDescriptor getOuterClassDescriptor() {
|
||||
if (myClass.getParent() instanceof JetClassObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
}
|
||||
|
||||
private void generateDelegatorToConstructorCall(InstructionAdapter iv, ExpressionCodegen codegen, JetCallElement constructorCall,
|
||||
ConstructorDescriptor constructorDescriptor,
|
||||
ConstructorFrameMap frameMap) {
|
||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
||||
PsiElement declaration = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDecl);
|
||||
Type type;
|
||||
if (declaration instanceof PsiClass) {
|
||||
type = JetTypeMapper.psiClassType((PsiClass) declaration);
|
||||
}
|
||||
else {
|
||||
type = JetTypeMapper.jetImplementationType(classDecl);
|
||||
}
|
||||
|
||||
iv.load(0, type);
|
||||
|
||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
iv.load(frameMap.getOuterThisIndex(), state.getTypeMapper().jvmType((ClassDescriptor) descriptor.getContainingDeclaration(), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
|
||||
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
|
||||
codegen.invokeMethodWithArguments(method, constructorCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
|
||||
if (declaration instanceof JetConstructor) {
|
||||
generateSecondaryConstructor((JetConstructor) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetClassObject) {
|
||||
generateClassObject((JetClassObject) declaration);
|
||||
}
|
||||
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);
|
||||
if (myEnumConstants.isEmpty()) {
|
||||
staticInitializerChunks.add(new CodeChunk() {
|
||||
@Override
|
||||
public void generate(InstructionAdapter v) {
|
||||
initializeEnumConstants(v);
|
||||
}
|
||||
});
|
||||
}
|
||||
myEnumConstants.add((JetEnumEntry) declaration);
|
||||
}
|
||||
else {
|
||||
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
||||
|
||||
private void initializeEnumConstants(InstructionAdapter v) {
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
for (JetEnumEntry enumConstant : myEnumConstants) {
|
||||
// TODO type and constructor parameters
|
||||
String implClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
|
||||
if (delegationSpecifiers.size() > 1) {
|
||||
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
|
||||
}
|
||||
|
||||
v.anew(Type.getObjectType(implClass));
|
||||
v.dup();
|
||||
|
||||
if (delegationSpecifiers.size() == 1) {
|
||||
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
|
||||
if (specifier instanceof JetDelegatorToSuperCall) {
|
||||
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
|
||||
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
|
||||
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
codegen.invokeMethodWithArguments(method, superCall);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
|
||||
}
|
||||
}
|
||||
else {
|
||||
v.invokespecial(implClass, "<init>", "()V");
|
||||
}
|
||||
v.putstatic(implClass, enumConstant.getName(), "L" + implClass + ";");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateSecondaryConstructor(JetConstructor constructor) {
|
||||
ConstructorDescriptor constructorDescriptor = state.getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
|
||||
if (constructorDescriptor == null) {
|
||||
throw new UnsupportedOperationException("failed to get descriptor for secondary constructor");
|
||||
}
|
||||
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);
|
||||
mv.visitCode();
|
||||
|
||||
ConstructorFrameMap frameMap = new ConstructorFrameMap(method, constructorDescriptor, descriptor, kind);
|
||||
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
|
||||
for (JetDelegationSpecifier initializer : constructor.getInitializers()) {
|
||||
if (initializer instanceof JetDelegatorToThisCall) {
|
||||
JetDelegatorToThisCall thisCall = (JetDelegatorToThisCall) initializer;
|
||||
DeclarationDescriptor thisDescriptor = state.getBindingContext().get(BindingContext.REFERENCE_TARGET, thisCall.getThisReference());
|
||||
if (!(thisDescriptor instanceof ConstructorDescriptor)) {
|
||||
throw new UnsupportedOperationException("expected 'this' delegator to resolve to constructor");
|
||||
}
|
||||
generateDelegatorToConstructorCall(iv, codegen, thisCall, (ConstructorDescriptor) thisDescriptor, frameMap);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("unknown initializer type");
|
||||
}
|
||||
}
|
||||
|
||||
JetExpression bodyExpression = constructor.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
codegen.gen(bodyExpression, Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
protected void generateTypeInfoInitializer(int firstTypeParameter, int typeParamCount, InstructionAdapter iv) {
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
iv.aconst(state.getTypeMapper().jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
iv.iconst(0);
|
||||
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
if(typeParamCount != 0) {
|
||||
iv.iconst(typeParamCount);
|
||||
iv.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
|
||||
for (int i = 0; i < typeParamCount; i++) {
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
if(CodegenUtil.hasOuterTypeInfo(descriptor)) {
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
|
||||
iv.invokevirtual(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$setTypeInfo", "(Ljet/typeinfo/TypeInfo;)V");
|
||||
}
|
||||
|
||||
protected void generateInitializers(ExpressionCodegen codegen, InstructionAdapter iv) {
|
||||
for (JetDeclaration declaration : myClass.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||
if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null) {
|
||||
CompileTimeConstant<?> compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer);
|
||||
if(compileTimeValue != null) {
|
||||
assert compileTimeValue != null;
|
||||
Object value = compileTimeValue.getValue();
|
||||
Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||
if(JetTypeMapper.isPrimitive(type)) {
|
||||
if( !propertyDescriptor.getOutType().isNullable() && value instanceof Number) {
|
||||
if(type == Type.INT_TYPE && ((Number)value).intValue() == 0)
|
||||
continue;
|
||||
if(type == Type.BYTE_TYPE && ((Number)value).byteValue() == 0)
|
||||
continue;
|
||||
if(type == Type.LONG_TYPE && ((Number)value).longValue() == 0L)
|
||||
continue;
|
||||
if(type == Type.SHORT_TYPE && ((Number)value).shortValue() == 0)
|
||||
continue;
|
||||
if(type == Type.DOUBLE_TYPE && ((Number)value).doubleValue() == 0d)
|
||||
continue;
|
||||
if(type == Type.FLOAT_TYPE && ((Number)value).byteValue() == 0f)
|
||||
continue;
|
||||
}
|
||||
if(type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean)value))
|
||||
continue;
|
||||
if(type == Type.CHAR_TYPE && value instanceof Character && ((Character)value) == 0)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if(value == null)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
Type type = codegen.expressionType(initializer);
|
||||
if(propertyDescriptor.getOutType().isNullable())
|
||||
type = JetTypeMapper.boxType(type);
|
||||
codegen.gen(initializer, type);
|
||||
codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetClassInitializer) {
|
||||
codegen.gen(((JetClassInitializer) declaration).getBody(), Type.VOID_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void generateDelegates(JetClass toClass, ClassContext delegateContext, Set<FunctionDescriptor> overriden) {
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(delegateContext, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(delegateContext, v, functionCodegen, state);
|
||||
|
||||
for (JetDeclaration declaration : toClass.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetFunction) {
|
||||
if (!overriden.contains(state.getBindingContext().get(BindingContext.FUNCTION, declaration))) {
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (JetParameter p : toClass.getPrimaryConstructorParameters()) {
|
||||
if (p.getValOrVarNode() != null) {
|
||||
PropertyDescriptor propertyDescriptor = state.getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, p);
|
||||
if (propertyDescriptor != null) {
|
||||
propertyCodegen.generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
if (propertyDescriptor.isVar()) {
|
||||
propertyCodegen.generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetClassObject getClassObject() {
|
||||
return myClass instanceof JetClass ? ((JetClass) myClass).getClassObject() : null;
|
||||
}
|
||||
|
||||
private boolean isNonLiteralObject() {
|
||||
return myClass instanceof JetObjectDeclaration && !((JetObjectDeclaration) myClass).isObjectLiteral() &&
|
||||
!(myClass.getParent() instanceof JetClassObject);
|
||||
}
|
||||
|
||||
private void generateGetTypeInfo() {
|
||||
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
|
||||
return;
|
||||
|
||||
JetType defaultType = descriptor.getDefaultType();
|
||||
if(CodegenUtil.hasTypeInfoField(defaultType)) {
|
||||
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
|
||||
v.visitField(Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
|
||||
|
||||
MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.getfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
iv.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
mv = v.visitMethod(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);
|
||||
iv.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.load(1, JetTypeMapper.TYPE_OBJECT);
|
||||
iv.putfield(owner, "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
else {
|
||||
genGetStaticGetTypeInfoMethod();
|
||||
staticTypeInfoField();
|
||||
}
|
||||
}
|
||||
|
||||
private void genGetStaticGetTypeInfoMethod() {
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
String owner = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
v.getstatic(owner, "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.areturn(JetTypeMapper.TYPE_TYPEINFO);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void staticTypeInfoField() {
|
||||
v.visitField(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) {
|
||||
JetTypeMapper typeMapper = state.getTypeMapper();
|
||||
v.aconst(typeMapper.jvmType(descriptor, OwnerKind.IMPLEMENTATION));
|
||||
v.iconst(0);
|
||||
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(descriptor);
|
||||
if(outerClassDescriptor == null) {
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.getstatic(state.getTypeMapper().jvmName(outerClassDescriptor, OwnerKind.IMPLEMENTATION), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;ZLjet/typeinfo/TypeInfo;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
v.putstatic(typeMapper.jvmName(descriptor, kind), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void generateClassObject(JetClassObject declaration) {
|
||||
state.forClass().generate(context, declaration.getObjectDeclaration());
|
||||
}
|
||||
|
||||
private void genGetSuperTypesTypeInfo() {
|
||||
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC,
|
||||
"$$getSuperTypesTypeInfo",
|
||||
sig,
|
||||
null /* TODO */,
|
||||
null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
int k = 1;
|
||||
for (TypeParameterDescriptor parameterDescriptor : descriptor.getTypeConstructor().getParameters()) {
|
||||
codegen.addTypeParameter(parameterDescriptor, StackValue.local(k++, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
for(JetType superType : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
for (TypeProjection typeProjection : superType.getArguments()) {
|
||||
codegen.generateTypeInfo(typeProjection.getType());
|
||||
}
|
||||
v.invokestatic(state.getTypeMapper().mapType(superType).getInternalName(), "$$getSuperTypesTypeInfo", getGetSuperTypesTypeInfoSignature(superType));
|
||||
}
|
||||
|
||||
v.areturn(Type.VOID_TYPE);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static String getGetSuperTypesTypeInfoSignature(JetType type) {
|
||||
List<TypeParameterDescriptor> typeParameters = type.getConstructor().getParameters();
|
||||
StringBuilder sb = new StringBuilder("(Ljava/util/Set;");
|
||||
for(TypeParameterDescriptor tp : typeParameters)
|
||||
sb.append("Ljet/typeinfo/TypeInfo;");
|
||||
sb.append(")V");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+245
-96
@@ -2,12 +2,15 @@ package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.Function1;
|
||||
import jet.JetObject;
|
||||
import jet.typeinfo.TypeInfo;
|
||||
import jet.typeinfo.TypeInfoProjection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
@@ -19,20 +22,47 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class JetTypeMapper {
|
||||
public static final Type TYPE_OBJECT = Type.getObjectType("java/lang/Object");
|
||||
public static final Type TYPE_TYPEINFO = Type.getType(TypeInfo.class);
|
||||
public static final Type TYPE_TYPEINFOPROJECTION = Type.getType(TypeInfoProjection.class);
|
||||
public static final Type TYPE_JET_OBJECT = Type.getType(JetObject.class);
|
||||
public static final Type TYPE_NOTHING = Type.getObjectType("jet/Nothing");
|
||||
public static final Type JL_INTEGER_TYPE = Type.getObjectType("java/lang/Integer");
|
||||
public static final Type JL_LONG_TYPE = Type.getObjectType("java/lang/Long");
|
||||
public static final Type JL_SHORT_TYPE = Type.getObjectType("java/lang/Short");
|
||||
public static final Type JL_BYTE_TYPE = Type.getObjectType("java/lang/Byte");
|
||||
public static final Type JL_CHAR_TYPE = Type.getObjectType("java/lang/Character");
|
||||
public static final Type JL_FLOAT_TYPE = Type.getObjectType("java/lang/Float");
|
||||
public static final Type JL_DOUBLE_TYPE = Type.getObjectType("java/lang/Double");
|
||||
public static final Type JL_BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
|
||||
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
|
||||
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
|
||||
|
||||
public static final Type ARRAY_INT_TYPE = Type.getType(int[].class);
|
||||
public static final Type ARRAY_LONG_TYPE = Type.getType(long[].class);
|
||||
public static final Type ARRAY_SHORT_TYPE = Type.getType(short[].class);
|
||||
public static final Type ARRAY_BYTE_TYPE = Type.getType(byte[].class);
|
||||
public static final Type ARRAY_CHAR_TYPE = Type.getType(char[].class);
|
||||
public static final Type ARRAY_FLOAT_TYPE = Type.getType(float[].class);
|
||||
public static final Type ARRAY_DOUBLE_TYPE = Type.getType(double[].class);
|
||||
public static final Type ARRAY_BOOL_TYPE = Type.getType(boolean[].class);
|
||||
public static final Type ARRAY_GENERIC_TYPE = Type.getType(Object[].class);
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final BindingContext bindingContext;
|
||||
private final Map<JetExpression, String> classNamesForAnonymousClasses = new HashMap<JetExpression, String>();
|
||||
private final Map<String, Integer> anonymousSubclassesCount = new HashMap<String, Integer>();
|
||||
|
||||
private final HashMap<JetType,String> knowTypes = new HashMap<JetType, String>();
|
||||
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
|
||||
|
||||
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
this.bindingContext = bindingContext;
|
||||
initKnownTypes();
|
||||
}
|
||||
|
||||
static String jvmName(PsiClass psiClass) {
|
||||
@@ -47,7 +77,25 @@ public class JetTypeMapper {
|
||||
return type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE || type == Type.CHAR_TYPE;
|
||||
}
|
||||
|
||||
public static boolean isPrimitive(Type type) {
|
||||
return type == Type.INT_TYPE
|
||||
|| type == Type.SHORT_TYPE
|
||||
|| type == Type.BYTE_TYPE
|
||||
|| type == Type.CHAR_TYPE
|
||||
|| type == Type.SHORT_TYPE
|
||||
|| type == Type.FLOAT_TYPE
|
||||
|| type == Type.DOUBLE_TYPE
|
||||
|| type == Type.LONG_TYPE
|
||||
|| type == Type.BOOLEAN_TYPE
|
||||
|| type == Type.VOID_TYPE;
|
||||
}
|
||||
|
||||
static Type psiTypeToAsm(PsiType type) {
|
||||
if(type instanceof PsiArrayType) {
|
||||
PsiArrayType psiArrayType = (PsiArrayType) type;
|
||||
return Type.getType("[" + psiTypeToAsm(psiArrayType.getComponentType()).getDescriptor());
|
||||
}
|
||||
|
||||
if (type instanceof PsiPrimitiveType) {
|
||||
if (type == PsiType.VOID) {
|
||||
return Type.VOID_TYPE;
|
||||
@@ -121,6 +169,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else {
|
||||
needsReceiver = true;
|
||||
assert containingClass != null;
|
||||
if (containingClass.isInterface()) {
|
||||
opcode = Opcodes.INVOKEINTERFACE;
|
||||
}
|
||||
@@ -137,6 +186,28 @@ public class JetTypeMapper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Type getBoxedType(final Type type) {
|
||||
switch (type.getSort()) {
|
||||
case Type.BYTE:
|
||||
return JL_BYTE_TYPE;
|
||||
case Type.BOOLEAN:
|
||||
return JL_BOOLEAN_TYPE;
|
||||
case Type.SHORT:
|
||||
return JL_SHORT_TYPE;
|
||||
case Type.CHAR:
|
||||
return JL_CHAR_TYPE;
|
||||
case Type.INT:
|
||||
return JL_INTEGER_TYPE;
|
||||
case Type.FLOAT:
|
||||
return JL_FLOAT_TYPE;
|
||||
case Type.LONG:
|
||||
return JL_LONG_TYPE;
|
||||
case Type.DOUBLE:
|
||||
return JL_DOUBLE_TYPE;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
|
||||
if (declaration instanceof PsiClass) {
|
||||
@@ -147,9 +218,9 @@ public class JetTypeMapper {
|
||||
if (parent instanceof JetClassObject) {
|
||||
JetClass containingClass = PsiTreeUtil.getParentOfType(parent, JetClass.class);
|
||||
final ClassDescriptor containingClassDescriptor = bindingContext.get(BindingContext.CLASS, containingClass);
|
||||
return jvmName(containingClassDescriptor, OwnerKind.INTERFACE) + "$$ClassObj";
|
||||
return jvmName(containingClassDescriptor, OwnerKind.IMPLEMENTATION) + "$$ClassObj";
|
||||
}
|
||||
String className = classNamesForAnonymousClasses.get(declaration);
|
||||
@SuppressWarnings("SuspiciousMethodCalls") String className = classNamesForAnonymousClasses.get(declaration);
|
||||
if (className == null) {
|
||||
throw new UnsupportedOperationException("Unexpected forward reference to anonymous class " + declaration);
|
||||
}
|
||||
@@ -160,29 +231,18 @@ public class JetTypeMapper {
|
||||
|
||||
public String jvmName(JetClassObject classObject) {
|
||||
final ClassDescriptor descriptor = bindingContext.get(BindingContext.CLASS, classObject.getObjectDeclaration());
|
||||
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
|
||||
public boolean isInterface(ClassDescriptor jetClass, OwnerKind kind) {
|
||||
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
|
||||
if (declaration instanceof JetObjectDeclaration) {
|
||||
return false;
|
||||
}
|
||||
return kind == OwnerKind.INTERFACE;
|
||||
return jvmName(descriptor, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
|
||||
private static String jetJvmName(ClassDescriptor jetClass, OwnerKind kind) {
|
||||
if (jetClass.isObject()) {
|
||||
if (jetClass.getKind() == ClassKind.OBJECT) {
|
||||
return jvmNameForImplementation(jetClass);
|
||||
}
|
||||
if (kind == OwnerKind.INTERFACE) {
|
||||
return jvmNameForInterface(jetClass);
|
||||
}
|
||||
else if (kind == OwnerKind.IMPLEMENTATION) {
|
||||
return jvmNameForImplementation(jetClass);
|
||||
}
|
||||
else if (kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||
return jvmNameForDelegatingImplementation(jetClass);
|
||||
else if (kind == OwnerKind.TRAIT_IMPL) {
|
||||
return jvmNameForTraitImpl(jetClass);
|
||||
}
|
||||
else {
|
||||
assert false : "Unsuitable kind";
|
||||
@@ -209,10 +269,6 @@ public class JetTypeMapper {
|
||||
return Type.getType("L" + jvmNameForImplementation(classDescriptor) + ";");
|
||||
}
|
||||
|
||||
static Type jetDelegatingImplementationType(ClassDescriptor classDescriptor) {
|
||||
return Type.getType("L" + jvmNameForDelegatingImplementation(classDescriptor) + ";");
|
||||
}
|
||||
|
||||
public static String jvmName(JetNamespace namespace) {
|
||||
return NamespaceCodegen.getJVMClassName(namespace.getFQName());
|
||||
}
|
||||
@@ -226,11 +282,11 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
public static String jvmNameForImplementation(ClassDescriptor descriptor) {
|
||||
return jvmNameForInterface(descriptor) + "$$Impl";
|
||||
return jvmNameForInterface(descriptor);
|
||||
}
|
||||
|
||||
public static String jvmNameForDelegatingImplementation(ClassDescriptor descriptor) {
|
||||
return jvmNameForInterface(descriptor) + "$$DImpl";
|
||||
private static String jvmNameForTraitImpl(ClassDescriptor descriptor) {
|
||||
return jvmNameForInterface(descriptor) + "$$TImpl";
|
||||
}
|
||||
|
||||
public String getOwner(DeclarationDescriptor descriptor, OwnerKind kind) {
|
||||
@@ -241,11 +297,14 @@ public class JetTypeMapper {
|
||||
else if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) descriptor.getContainingDeclaration();
|
||||
if (kind instanceof OwnerKind.DelegateKind) {
|
||||
kind = OwnerKind.INTERFACE;
|
||||
}
|
||||
else if (classDescriptor.isObject()) {
|
||||
kind = OwnerKind.IMPLEMENTATION;
|
||||
}
|
||||
else {
|
||||
assert classDescriptor != null;
|
||||
if (classDescriptor.getKind() == ClassKind.OBJECT) {
|
||||
kind = OwnerKind.IMPLEMENTATION;
|
||||
}
|
||||
}
|
||||
owner = jvmName(classDescriptor, kind);
|
||||
}
|
||||
else {
|
||||
@@ -254,74 +313,112 @@ public class JetTypeMapper {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public Type mapType(final JetType jetType) {
|
||||
return mapType(jetType, OwnerKind.INTERFACE);
|
||||
}
|
||||
|
||||
public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
|
||||
@NotNull public Type mapReturnType(@NotNull final JetType jetType, OwnerKind kind) {
|
||||
if (jetType.equals(JetStandardClasses.getUnitType()) || jetType.equals(JetStandardClasses.getNothingType())) {
|
||||
return Type.VOID_TYPE;
|
||||
}
|
||||
return mapType(jetType, kind);
|
||||
}
|
||||
|
||||
@NotNull public Type mapReturnType(final JetType jetType) {
|
||||
return mapReturnType(jetType, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
|
||||
@NotNull public Type mapType(final JetType jetType) {
|
||||
return mapType(jetType, OwnerKind.IMPLEMENTATION);
|
||||
}
|
||||
|
||||
@NotNull public Type mapType(@NotNull final JetType jetType, OwnerKind kind) {
|
||||
if (jetType.equals(JetStandardClasses.getNothingType()) || jetType.equals(JetStandardClasses.getNullableNothingType())) {
|
||||
return TYPE_NOTHING;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getIntType())) {
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getIntType()))) {
|
||||
return Type.getObjectType("java/lang/Integer");
|
||||
if (jetType.equals(standardLibrary.getNullableIntType())) {
|
||||
return JL_INTEGER_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getLongType())) {
|
||||
return Type.LONG_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getLongType()))) {
|
||||
return Type.getObjectType("java/lang/Long");
|
||||
if (jetType.equals(standardLibrary.getNullableLongType())) {
|
||||
return JL_LONG_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getShortType())) {
|
||||
return Type.SHORT_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getShortType()))) {
|
||||
return Type.getObjectType("java/lang/Short");
|
||||
if (jetType.equals(standardLibrary.getNullableShortType())) {
|
||||
return JL_SHORT_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getByteType())) {
|
||||
return Type.BYTE_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getByteType()))) {
|
||||
return Type.getObjectType("java/lang/Byte");
|
||||
if (jetType.equals(standardLibrary.getNullableByteType())) {
|
||||
return JL_BYTE_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getCharType())) {
|
||||
return Type.CHAR_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getCharType()))) {
|
||||
return Type.getObjectType("java/lang/Char");
|
||||
if (jetType.equals(standardLibrary.getNullableCharType())) {
|
||||
return JL_CHAR_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getFloatType())) {
|
||||
return Type.FLOAT_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getFloatType()))) {
|
||||
return Type.getObjectType("java/lang/Float");
|
||||
if (jetType.equals(standardLibrary.getNullableFloatType())) {
|
||||
return JL_FLOAT_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getDoubleType())) {
|
||||
return Type.DOUBLE_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getDoubleType()))) {
|
||||
return Type.getObjectType("java/lang/Double");
|
||||
if (jetType.equals(standardLibrary.getNullableDoubleType())) {
|
||||
return JL_DOUBLE_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getBooleanType())) {
|
||||
return Type.BOOLEAN_TYPE;
|
||||
}
|
||||
if (jetType.equals(TypeUtils.makeNullable(standardLibrary.getBooleanType()))) {
|
||||
return Type.getObjectType("java/lang/Boolean");
|
||||
if (jetType.equals(standardLibrary.getNullableBooleanType())) {
|
||||
return JL_BOOLEAN_TYPE;
|
||||
}
|
||||
if (jetType.equals(standardLibrary.getStringType()) || jetType.equals(standardLibrary.getNullableStringType())) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
if(jetType.equals(standardLibrary.getByteArrayType())){
|
||||
return ARRAY_BYTE_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getShortArrayType())){
|
||||
return ARRAY_SHORT_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getIntArrayType())){
|
||||
return ARRAY_INT_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getLongArrayType())){
|
||||
return ARRAY_LONG_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getFloatArrayType())){
|
||||
return ARRAY_FLOAT_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getDoubleArrayType())){
|
||||
return ARRAY_DOUBLE_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getCharArrayType())){
|
||||
return ARRAY_CHAR_TYPE;
|
||||
}
|
||||
if(jetType.equals(standardLibrary.getBooleanArrayType())){
|
||||
return ARRAY_BOOL_TYPE;
|
||||
}
|
||||
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (standardLibrary.getArray().equals(descriptor)) {
|
||||
if (jetType.getArguments().size() != 1) {
|
||||
throw new UnsupportedOperationException("arrays must have one type argument");
|
||||
}
|
||||
TypeProjection memberType = jetType.getArguments().get(0);
|
||||
Type elementType = mapType(memberType.getType());
|
||||
return Type.getType("[" + elementType.getDescriptor());
|
||||
JetType memberType = jetType.getArguments().get(0).getType();
|
||||
if(!isGenericsArray(jetType))
|
||||
return Type.getType("[" + boxType(mapType(memberType, kind)).getDescriptor());
|
||||
else
|
||||
return ARRAY_GENERIC_TYPE;
|
||||
}
|
||||
if (JetStandardClasses.getAny().equals(descriptor)) {
|
||||
return Type.getType(Object.class);
|
||||
@@ -338,39 +435,33 @@ public class JetTypeMapper {
|
||||
throw new UnsupportedOperationException("Unknown type " + jetType);
|
||||
}
|
||||
|
||||
public Type boxType(Type asmType) {
|
||||
public static Type boxType(Type asmType) {
|
||||
switch (asmType.getSort()) {
|
||||
case Type.VOID:
|
||||
return Type.getObjectType("java/lang/Void");
|
||||
return Type.VOID_TYPE;
|
||||
case Type.BYTE:
|
||||
return Type.getObjectType("java/lang/Byte");
|
||||
return JL_BYTE_TYPE;
|
||||
case Type.BOOLEAN:
|
||||
return Type.getObjectType("java/lang/Boolean");
|
||||
return JL_BOOLEAN_TYPE;
|
||||
case Type.SHORT:
|
||||
return Type.getObjectType("java/lang.Short");
|
||||
return JL_SHORT_TYPE;
|
||||
case Type.CHAR:
|
||||
return Type.getObjectType("java/lang/Character");
|
||||
return JL_CHAR_TYPE;
|
||||
case Type.INT:
|
||||
return Type.getObjectType("java/lang/Integer");
|
||||
return JL_INTEGER_TYPE;
|
||||
case Type.FLOAT:
|
||||
return Type.getObjectType("java/lang/Float");
|
||||
return JL_FLOAT_TYPE;
|
||||
case Type.LONG:
|
||||
return Type.getObjectType("java/lang/Long");
|
||||
return JL_LONG_TYPE;
|
||||
case Type.DOUBLE:
|
||||
return Type.getObjectType("java/lang/Double");
|
||||
return JL_DOUBLE_TYPE;
|
||||
}
|
||||
|
||||
return asmType;
|
||||
}
|
||||
|
||||
|
||||
private static Type getBoxedType(final Type type) {
|
||||
switch (type.getSort()) {
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private Method mapSignature(JetNamedFunction f, List<Type> valueParameterTypes) {
|
||||
private Method mapSignature(JetNamedFunction f, List<Type> valueParameterTypes, OwnerKind kind) {
|
||||
final JetTypeReference receiverTypeRef = f.getReceiverTypeRef();
|
||||
final JetType receiverType = receiverTypeRef == null ? null : bindingContext.get(BindingContext.TYPE, receiverTypeRef);
|
||||
final List<JetParameter> parameters = f.getValueParameters();
|
||||
@@ -378,28 +469,40 @@ public class JetTypeMapper {
|
||||
if (receiverType != null) {
|
||||
parameterTypes.add(mapType(receiverType));
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
||||
Type type = mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = containingDeclaration.getDefaultType();
|
||||
type = mapType(jetType);
|
||||
}
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
for (JetParameter parameter : parameters) {
|
||||
final Type type = mapType(bindingContext.get(BindingContext.TYPE, parameter.getTypeReference()));
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
for (JetTypeParameter p: f.getTypeParameters()) {
|
||||
for (int n = f.getTypeParameters().size(); n > 0; n--) {
|
||||
parameterTypes.add(TYPE_TYPEINFO);
|
||||
}
|
||||
final JetTypeReference returnTypeRef = f.getReturnTypeRef();
|
||||
Type returnType;
|
||||
if (returnTypeRef == null) {
|
||||
final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
assert functionDescriptor != null;
|
||||
final JetType type = functionDescriptor.getReturnType();
|
||||
returnType = mapType(type);
|
||||
returnType = mapReturnType(type);
|
||||
}
|
||||
else {
|
||||
returnType = mapType(bindingContext.get(BindingContext.TYPE, returnTypeRef));
|
||||
returnType = mapReturnType(bindingContext.get(BindingContext.TYPE, returnTypeRef));
|
||||
}
|
||||
return new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
public CallableMethod mapToCallableMethod(PsiNamedElement declaration) {
|
||||
public CallableMethod mapToCallableMethod(PsiNamedElement declaration, OwnerKind kind) {
|
||||
if (declaration instanceof PsiMethod) {
|
||||
return mapToCallableMethod((PsiMethod) declaration);
|
||||
}
|
||||
@@ -408,9 +511,10 @@ public class JetTypeMapper {
|
||||
}
|
||||
JetNamedFunction f = (JetNamedFunction) declaration;
|
||||
final FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
assert functionDescriptor != null;
|
||||
final DeclarationDescriptor functionParent = functionDescriptor.getContainingDeclaration();
|
||||
final List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
Method descriptor = mapSignature(f, valueParameterTypes);
|
||||
Method descriptor = mapSignature(f, valueParameterTypes, kind);
|
||||
String owner;
|
||||
int invokeOpcode;
|
||||
boolean needsReceiver;
|
||||
@@ -422,8 +526,8 @@ public class JetTypeMapper {
|
||||
}
|
||||
else if (functionParent instanceof ClassDescriptor) {
|
||||
ClassDescriptor containingClass = (ClassDescriptor) functionParent;
|
||||
owner = jvmName(containingClass, OwnerKind.INTERFACE);
|
||||
invokeOpcode = isInterface(containingClass, OwnerKind.INTERFACE)
|
||||
owner = jvmName(containingClass, OwnerKind.IMPLEMENTATION);
|
||||
invokeOpcode = CodegenUtil.isInterface(containingClass)
|
||||
? Opcodes.INVOKEINTERFACE
|
||||
: Opcodes.INVOKEVIRTUAL;
|
||||
needsReceiver = true;
|
||||
@@ -442,16 +546,16 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
public Method mapSignature(String name, FunctionDescriptor f) {
|
||||
final JetType receiverType = f.getReceiverType();
|
||||
final ReceiverDescriptor receiver = f.getReceiver();
|
||||
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
if (receiverType != null) {
|
||||
parameterTypes.add(mapType(receiverType));
|
||||
if (receiver.exists()) {
|
||||
parameterTypes.add(mapType(receiver.getType()));
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
parameterTypes.add(mapType(parameter.getOutType()));
|
||||
}
|
||||
Type returnType = mapType(f.getReturnType());
|
||||
Type returnType = mapReturnType(f.getReturnType());
|
||||
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
|
||||
}
|
||||
|
||||
@@ -481,7 +585,7 @@ public class JetTypeMapper {
|
||||
answer.append(mapType(type).getDescriptor()); // TODO: type parameter references!
|
||||
}
|
||||
|
||||
private void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) {
|
||||
private static void appendTypeParameterSignature(StringBuffer answer, TypeParameterDescriptor p) {
|
||||
answer.append(p.getName()); // TODO: BOUND!
|
||||
}
|
||||
|
||||
@@ -499,17 +603,12 @@ public class JetTypeMapper {
|
||||
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
|
||||
}
|
||||
|
||||
private Method mapConstructorSignature(ConstructorDescriptor descriptor, OwnerKind kind, List<Type> valueParameterTypes) {
|
||||
boolean delegate = kind == OwnerKind.DELEGATING_IMPLEMENTATION;
|
||||
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
|
||||
List<ValueParameterDescriptor> parameters = descriptor.getOriginal().getValueParameters();
|
||||
List<Type> parameterTypes = new ArrayList<Type>();
|
||||
ClassDescriptor classDescriptor = descriptor.getContainingDeclaration();
|
||||
final DeclarationDescriptor outerDescriptor = classDescriptor.getContainingDeclaration();
|
||||
if (outerDescriptor instanceof ClassDescriptor) {
|
||||
parameterTypes.add(jvmType((ClassDescriptor) outerDescriptor, OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
if (delegate) {
|
||||
parameterTypes.add(jetInterfaceType(classDescriptor));
|
||||
if (CodegenUtil.hasThis0(classDescriptor)) {
|
||||
parameterTypes.add(jvmType(CodegenUtil.getOuterClassDescriptor(classDescriptor), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
for (ValueParameterDescriptor parameter : parameters) {
|
||||
final Type type = mapType(parameter.getOutType());
|
||||
@@ -518,7 +617,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
|
||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
||||
for (int n = typeParameters.size(); n > 0; n--) {
|
||||
parameterTypes.add(TYPE_TYPEINFO);
|
||||
}
|
||||
|
||||
@@ -527,7 +626,7 @@ public class JetTypeMapper {
|
||||
|
||||
public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) {
|
||||
List<Type> valueParameterTypes = new ArrayList<Type>();
|
||||
final Method method = mapConstructorSignature(descriptor, kind, valueParameterTypes);
|
||||
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
|
||||
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
|
||||
final CallableMethod result = new CallableMethod(owner, method, Opcodes.INVOKESPECIAL, valueParameterTypes);
|
||||
result.setAcceptsTypeArguments(true);
|
||||
@@ -554,15 +653,15 @@ public class JetTypeMapper {
|
||||
return name;
|
||||
}
|
||||
|
||||
JetNamedDeclaration container = PsiTreeUtil.getParentOfType(expression, JetNamespace.class, JetClass.class, JetObjectDeclaration.class);
|
||||
@SuppressWarnings("unchecked") JetNamedDeclaration container = PsiTreeUtil.getParentOfType(expression, JetNamespace.class, JetClass.class, JetObjectDeclaration.class);
|
||||
|
||||
String baseName;
|
||||
if (container instanceof JetNamespace) {
|
||||
baseName = NamespaceCodegen.getJVMClassName(((JetNamespace) container).getFQName());
|
||||
}
|
||||
else {
|
||||
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, (JetClassOrObject) container);
|
||||
baseName = JetTypeMapper.jvmNameForInterface(aClass);
|
||||
ClassDescriptor aClass = bindingContext.get(BindingContext.CLASS, container);
|
||||
baseName = jvmNameForInterface(aClass);
|
||||
}
|
||||
|
||||
Integer count = anonymousSubclassesCount.get(baseName);
|
||||
@@ -579,10 +678,60 @@ public class JetTypeMapper {
|
||||
Set<String> result = new HashSet<String>();
|
||||
final ClassDescriptor classDescriptor = bindingContext.get(BindingContext.CLASS, jetClass);
|
||||
if (classDescriptor != null) {
|
||||
result.add(jvmName(classDescriptor, OwnerKind.INTERFACE));
|
||||
result.add(jvmName(classDescriptor, OwnerKind.IMPLEMENTATION));
|
||||
result.add(jvmName(classDescriptor, OwnerKind.DELEGATING_IMPLEMENTATION));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void initKnownTypes() {
|
||||
knowTypes.put(standardLibrary.getIntType(), "INT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableIntType(), "NULLABLE_INT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getLongType(), "LONG_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableLongType(), "NULLABLE_LONG_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getShortType(),"SHORT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableShortType(),"NULLABLE_SHORT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getByteType(),"BYTE_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableByteType(),"NULLABLE_BYTE_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getCharType(),"CHAR_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableCharType(),"NULLABLE_CHAR_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getFloatType(),"FLOAT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableFloatType(),"NULLABLE_FLOAT_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getDoubleType(),"DOUBLE_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableDoubleType(),"NULLABLE_DOUBLE_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getBooleanType(),"BOOLEAN_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableBooleanType(),"NULLABLE_BOOLEAN_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getStringType(),"STRING_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableStringType(),"NULLABLE_STRING_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getTuple0Type(),"TUPLE0_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getNullableTuple0Type(),"NULLABLE_TUPLE0_TYPE_INFO");
|
||||
|
||||
knowTypes.put(standardLibrary.getIntArrayType(), "INT_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getLongArrayType(), "LONG_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getShortArrayType(),"SHORT_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getByteArrayType(),"BYTE_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getCharArrayType(),"CHAR_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getFloatArrayType(),"FLOAT_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getDoubleArrayType(),"DOUBLE_ARRAY_TYPE_INFO");
|
||||
knowTypes.put(standardLibrary.getBooleanArrayType(),"BOOLEAN_ARRAY_TYPE_INFO");
|
||||
}
|
||||
|
||||
public String isKnownTypeInfo(JetType jetType) {
|
||||
return knowTypes.get(jetType);
|
||||
}
|
||||
|
||||
public boolean isGenericsArray(JetType type) {
|
||||
DeclarationDescriptor declarationDescriptor = type.getConstructor().getDeclarationDescriptor();
|
||||
if(declarationDescriptor instanceof TypeParameterDescriptor)
|
||||
return true;
|
||||
|
||||
if(standardLibrary.getArray().equals(declarationDescriptor))
|
||||
return isGenericsArray(type.getArguments().get(0).getType());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public JetType getGenericsElementType(JetType arrayType) {
|
||||
JetType type = arrayType.getArguments().get(0).getType();
|
||||
return isGenericsArray(type) ? type : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
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.commons.InstructionAdapter;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class NamespaceCodegen {
|
||||
private final ClassVisitor v;
|
||||
private final GenerationState state;
|
||||
|
||||
public NamespaceCodegen(ClassVisitor 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]
|
||||
);
|
||||
// TODO figure something out for a namespace that spans multiple files
|
||||
v.visitSource(sourceFile.getName(), null);
|
||||
}
|
||||
|
||||
public void generate(JetNamespace namespace) {
|
||||
final ClassContext context = ClassContext.STATIC.intoNamespace(state.getBindingContext().get(BindingContext.NAMESPACE, namespace));
|
||||
|
||||
final FunctionCodegen functionCodegen = new FunctionCodegen(context, v, state);
|
||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(context, v, functionCodegen, state);
|
||||
final ClassCodegen classCodegen = state.forClass();
|
||||
|
||||
GenerationState.prepareAnonymousClasses(namespace, state.getTypeMapper());
|
||||
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
propertyCodegen.gen((JetProperty) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamedFunction) {
|
||||
try {
|
||||
functionCodegen.gen((JetNamedFunction) declaration);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to generate function " + declaration.getName(), e);
|
||||
}
|
||||
}
|
||||
else if (declaration instanceof JetClassOrObject) {
|
||||
classCodegen.generate(context, (JetClassOrObject) declaration);
|
||||
}
|
||||
else if (declaration instanceof JetNamespace) {
|
||||
JetNamespace childNamespace = (JetNamespace) declaration;
|
||||
state.forNamespace(childNamespace).generate(childNamespace);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNonConstantPropertyInitializers(namespace)) {
|
||||
generateStaticInitializers(namespace);
|
||||
}
|
||||
|
||||
generateTypeInfoFields(namespace, context);
|
||||
}
|
||||
|
||||
private void generateStaticInitializers(JetNamespace namespace) {
|
||||
MethodVisitor mv = v.visitMethod(ACC_PUBLIC | ACC_STATIC,
|
||||
"<clinit>", "()V", null, null);
|
||||
mv.visitCode();
|
||||
|
||||
FrameMap frameMap = new FrameMap();
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, ClassContext.STATIC, state);
|
||||
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
|
||||
codegen.genToJVMStack(initializer);
|
||||
codegen.intermediateValueForProperty(descriptor, true, false).store(new InstructionAdapter(mv));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private void generateTypeInfoFields(JetNamespace namespace, ClassContext context) {
|
||||
if(context.typeInfoConstants != null) {
|
||||
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);
|
||||
|
||||
MethodVisitor mmv = v.visitMethod(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);
|
||||
Label end = new Label();
|
||||
v.visitJumpInsn(IFNONNULL, end);
|
||||
|
||||
v.pop();
|
||||
generateTypeInfo(context, v, e.getKey(), state.getTypeMapper(), e.getKey());
|
||||
v.dup();
|
||||
|
||||
v.visitFieldInsn(PUTSTATIC, jvmClassName, fieldName, "Ljet/typeinfo/TypeInfo;");
|
||||
v.visitLabel(end);
|
||||
v.visitInsn(ARETURN);
|
||||
v.visitMaxs(0, 0);
|
||||
v.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateTypeInfo(ClassContext context, InstructionAdapter v, JetType jetType, JetTypeMapper typeMapper, JetType root) {
|
||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||
if(knownTypeInfo != null) {
|
||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
|
||||
DeclarationDescriptor declarationDescriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if(!jetType.equals(root) && jetType.getArguments().size() == 0 && !(declarationDescriptor instanceof JavaClassDescriptor)) {
|
||||
// TODO: we need some better checks here
|
||||
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasUnsubstituted = TypeUtils.hasUnsubstitutedTypeParameters(jetType);
|
||||
if(!jetType.equals(root) && !hasUnsubstituted) {
|
||||
int typeInfoConstantIndex = context.getTypeInfoConstantIndex(jetType);
|
||||
v.invokestatic(context.getNamespaceClassName(), "$getCachedTypeInfo$" + typeInfoConstantIndex, "()Ljet/typeinfo/TypeInfo;");
|
||||
return;
|
||||
}
|
||||
|
||||
final Type jvmType = typeMapper.mapType(jetType);
|
||||
|
||||
v.aconst(jvmType);
|
||||
v.iconst(jetType.isNullable() ? 1 : 0);
|
||||
List<TypeProjection> arguments = jetType.getArguments();
|
||||
if (arguments.size() > 0 && !(jvmType.getSort() == Type.ARRAY && jvmType.getElementType().getSort() != Type.OBJECT)) {
|
||||
v.iconst(arguments.size());
|
||||
v.newarray(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
|
||||
for (int i = 0, argumentsSize = arguments.size(); i < argumentsSize; i++) {
|
||||
TypeProjection argument = arguments.get(i);
|
||||
v.dup();
|
||||
v.iconst(i);
|
||||
generateTypeInfo(context, v, argument.getType(), typeMapper, root);
|
||||
ExpressionCodegen.genTypeInfoToProjection(v, argument.getProjectionKind());
|
||||
v.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
else {
|
||||
v.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z)Ljet/typeinfo/TypeInfo;");
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasNonConstantPropertyInitializers(JetNamespace namespace) {
|
||||
for (JetDeclaration declaration : namespace.getDeclarations()) {
|
||||
if (declaration instanceof JetProperty) {
|
||||
final JetExpression initializer = ((JetProperty) declaration).getInitializer();
|
||||
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void done() {
|
||||
v.visitEnd();
|
||||
}
|
||||
|
||||
public static String getJVMClassName(String fqName) {
|
||||
if (fqName.length() == 0) {
|
||||
return "namespace";
|
||||
}
|
||||
return fqName.replace('.', '/') + "/namespace";
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -11,9 +11,8 @@ public class OwnerKind {
|
||||
}
|
||||
|
||||
public static final OwnerKind NAMESPACE = new OwnerKind("namespace");
|
||||
public static final OwnerKind INTERFACE = new OwnerKind("interface");
|
||||
public static final OwnerKind IMPLEMENTATION = new OwnerKind("implementation");
|
||||
public static final OwnerKind DELEGATING_IMPLEMENTATION = new OwnerKind("delegating implementation");
|
||||
public static final OwnerKind TRAIT_IMPL = new OwnerKind("trait implementation");
|
||||
|
||||
public static class DelegateKind extends OwnerKind {
|
||||
private final StackValue delegate;
|
||||
+18
-29
@@ -1,9 +1,8 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
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.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
@@ -36,29 +35,11 @@ public class PropertyCodegen {
|
||||
throw new UnsupportedOperationException("expect a property to have a property descriptor");
|
||||
}
|
||||
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
|
||||
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.DELEGATING_IMPLEMENTATION) {
|
||||
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION) {
|
||||
generateBackingField(p, propertyDescriptor);
|
||||
generateGetter(p, propertyDescriptor);
|
||||
generateSetter(p, propertyDescriptor);
|
||||
}
|
||||
else if (kind == OwnerKind.INTERFACE) {
|
||||
final JetPropertyAccessor getter = p.getGetter();
|
||||
if ((getter != null && !getter.hasModifier(JetTokens.PRIVATE_KEYWORD) ||
|
||||
(getter == null && isExternallyAccessible(p)))) {
|
||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||
getterName(p.getName()),
|
||||
state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor(),
|
||||
null, null);
|
||||
}
|
||||
final JetPropertyAccessor setter = p.getSetter();
|
||||
if ((setter != null && !setter.hasModifier(JetTokens.PRIVATE_KEYWORD) ||
|
||||
(setter == null && isExternallyAccessible(p) && p.isVar()))) {
|
||||
v.visitMethod(Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,
|
||||
setterName(p.getName()),
|
||||
state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor(),
|
||||
null, null);
|
||||
}
|
||||
}
|
||||
else if (kind instanceof OwnerKind.DelegateKind) {
|
||||
generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC);
|
||||
if (propertyDescriptor.isVar()) {
|
||||
@@ -68,7 +49,11 @@ public class PropertyCodegen {
|
||||
}
|
||||
|
||||
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) {
|
||||
if ((boolean) state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) {
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
if(CodegenUtil.isInterface(containingDeclaration))
|
||||
return;
|
||||
|
||||
Object value = null;
|
||||
final JetExpression initializer = p.getInitializer();
|
||||
if (initializer != null) {
|
||||
@@ -136,14 +121,16 @@ public class PropertyCodegen {
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
flags |= Opcodes.ACC_STATIC;
|
||||
}
|
||||
else if (kind == OwnerKind.INTERFACE) {
|
||||
|
||||
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration());
|
||||
boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait();
|
||||
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
|
||||
flags |= Opcodes.ACC_ABSTRACT;
|
||||
}
|
||||
|
||||
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
|
||||
String getterName = getterName(propertyDescriptor.getName());
|
||||
MethodVisitor mv = v.visitMethod(flags, getterName, signature, null, null);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
if (kind != OwnerKind.NAMESPACE) {
|
||||
@@ -176,13 +163,15 @@ public class PropertyCodegen {
|
||||
if (kind == OwnerKind.NAMESPACE) {
|
||||
flags |= Opcodes.ACC_STATIC;
|
||||
}
|
||||
else if (kind == OwnerKind.INTERFACE) {
|
||||
|
||||
PsiElement psiElement = state.getBindingContext().get(BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration());
|
||||
boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait();
|
||||
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
|
||||
flags |= Opcodes.ACC_ABSTRACT;
|
||||
}
|
||||
|
||||
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
|
||||
MethodVisitor mv = v.visitMethod(flags, setterName(propertyDescriptor.getName()), signature, null, null);
|
||||
if (kind != OwnerKind.INTERFACE) {
|
||||
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
final Type type = state.getTypeMapper().mapType(propertyDescriptor.getOutType());
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeParameter;
|
||||
import org.jetbrains.jet.lang.psi.JetTypeReference;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class SignatureUtil {
|
||||
public static String classToSignature(JetClass type, BindingContext bindingContext, JetTypeMapper typeMapper) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
genTypeParams(type, sb);
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = type.getDelegationSpecifiers();
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
JetTypeReference typeReference = specifier.getTypeReference();
|
||||
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
||||
genJetType(sb, jetType, typeMapper);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void genJetType(StringBuilder sb, JetType jetType, JetTypeMapper typeMapper) {
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if(descriptor instanceof ClassDescriptor) {
|
||||
JetType defaultType = ((ClassDescriptor) descriptor).getDefaultType();
|
||||
org.objectweb.asm.Type type = typeMapper.mapType(defaultType, OwnerKind.IMPLEMENTATION);
|
||||
if(JetTypeMapper.isPrimitive(type)) {
|
||||
type = JetTypeMapper.boxType(type);
|
||||
}
|
||||
sb.append(type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
sb.append("T");
|
||||
sb.append(descriptor.getContainingDeclaration().getName());
|
||||
sb.append(";");
|
||||
sb.append(descriptor.getName());
|
||||
sb.append(";");
|
||||
}
|
||||
if(!jetType.getArguments().isEmpty()) {
|
||||
sb.append("<");
|
||||
for (TypeProjection typeProjection : jetType.getArguments()) {
|
||||
if(typeProjection.getProjectionKind() == Variance.IN_VARIANCE)
|
||||
sb.append("in ");
|
||||
if(typeProjection.getProjectionKind() == Variance.OUT_VARIANCE)
|
||||
sb.append("out ");
|
||||
genJetType(sb, typeProjection.getType(), typeMapper);
|
||||
}
|
||||
sb.append(">");
|
||||
}
|
||||
if(jetType.isNullable())
|
||||
sb.append("?");
|
||||
}
|
||||
|
||||
private static void genTypeParams(JetClass type, StringBuilder sb) {
|
||||
List<JetTypeParameter> parameters = type.getTypeParameterList().getParameters();
|
||||
for(JetTypeParameter param : parameters) {
|
||||
sb.append("T");
|
||||
Variance variance = param.getVariance();
|
||||
if(variance == Variance.IN_VARIANCE)
|
||||
sb.append("in ");
|
||||
else if(variance == Variance.OUT_VARIANCE)
|
||||
sb.append("out ");
|
||||
sb.append(param.getName());
|
||||
sb.append(";");
|
||||
}
|
||||
}
|
||||
}
|
||||
+77
-14
@@ -13,12 +13,24 @@ import org.objectweb.asm.commons.Method;
|
||||
* @author yole
|
||||
*/
|
||||
public abstract class StackValue {
|
||||
protected final Type type;
|
||||
public final Type type;
|
||||
|
||||
public StackValue(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public static void valueOf(InstructionAdapter instructionAdapter, final Type type) {
|
||||
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
|
||||
return;
|
||||
}
|
||||
if (type == Type.VOID_TYPE) {
|
||||
instructionAdapter.aconst(null);
|
||||
} else {
|
||||
Type boxed = JetTypeMapper.getBoxedType(type);
|
||||
instructionAdapter.invokestatic(boxed.getInternalName(), "valueOf", "(" + type.getDescriptor() + ")" + boxed.getDescriptor());
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void put(Type type, InstructionAdapter v);
|
||||
|
||||
public void store(InstructionAdapter v) {
|
||||
@@ -48,8 +60,7 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
public static StackValue onStack(Type type) {
|
||||
assert type != Type.VOID_TYPE;
|
||||
return new OnStack(type);
|
||||
return type == Type.VOID_TYPE ? none() : new OnStack(type);
|
||||
}
|
||||
|
||||
public static StackValue constant(Object value, Type type) {
|
||||
@@ -64,8 +75,8 @@ public abstract class StackValue {
|
||||
return new Invert(stackValue);
|
||||
}
|
||||
|
||||
public static StackValue arrayElement(Type type) {
|
||||
return new ArrayElement(type);
|
||||
public static StackValue arrayElement(Type type, boolean unbox) {
|
||||
return new ArrayElement(type, unbox);
|
||||
}
|
||||
|
||||
public static StackValue collectionElement(Type type, CallableMethod getter, CallableMethod setter) {
|
||||
@@ -157,8 +168,26 @@ public abstract class StackValue {
|
||||
protected void coerce(Type type, InstructionAdapter v) {
|
||||
if (type.equals(this.type)) return;
|
||||
|
||||
if (type.getSort() == Type.OBJECT && this.type.getSort() == Type.OBJECT) {
|
||||
// v.checkcast(type);
|
||||
if (type.getSort() == Type.VOID && this.type.getSort() != Type.VOID) {
|
||||
if(this.type.getSize() == 1)
|
||||
v.pop();
|
||||
else
|
||||
v.pop2();
|
||||
}
|
||||
else if (type.getSort() != Type.VOID && this.type.getSort() == Type.VOID) {
|
||||
if(type.getSort() == Type.OBJECT)
|
||||
v.visitFieldInsn(Opcodes.GETSTATIC, "jet/Tuple0", "INSTANCE", "Ljet/Tuple0;");
|
||||
else if(type == Type.LONG_TYPE)
|
||||
v.lconst(0);
|
||||
else if(type == Type.FLOAT_TYPE)
|
||||
v.fconst(0);
|
||||
else if(type == Type.DOUBLE_TYPE)
|
||||
v.dconst(0);
|
||||
else
|
||||
v.iconst(0);
|
||||
}
|
||||
else if (type.getSort() == Type.OBJECT && this.type.equals(JetTypeMapper.TYPE_OBJECT) || type.getSort() == Type.ARRAY) {
|
||||
v.checkcast(type);
|
||||
}
|
||||
else if (type.getSort() == Type.OBJECT) {
|
||||
box(this.type, type, v);
|
||||
@@ -166,10 +195,10 @@ public abstract class StackValue {
|
||||
else if (this.type.getSort() == Type.OBJECT && type.getSort() <= Type.DOUBLE) {
|
||||
if (this.type.equals(JetTypeMapper.TYPE_OBJECT)) {
|
||||
if (type.getSort() == Type.BOOLEAN) {
|
||||
v.checkcast(Type.getObjectType("java/lang/Boolean"));
|
||||
v.checkcast(JetTypeMapper.JL_BOOLEAN_TYPE);
|
||||
}
|
||||
else {
|
||||
v.checkcast(Type.getObjectType("java/lang/Number"));
|
||||
v.checkcast(JetTypeMapper.JL_NUMBER_TYPE);
|
||||
}
|
||||
}
|
||||
unbox(type, v);
|
||||
@@ -190,6 +219,22 @@ public abstract class StackValue {
|
||||
v.mark(end);
|
||||
}
|
||||
|
||||
public static StackValue none() {
|
||||
return None.INSTANCE;
|
||||
}
|
||||
|
||||
private static class None extends StackValue {
|
||||
public static None INSTANCE = new None();
|
||||
private None() {
|
||||
super(Type.VOID_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
coerce(type, v);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Local extends StackValue {
|
||||
private final int index;
|
||||
|
||||
@@ -242,14 +287,26 @@ public abstract class StackValue {
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
v.aconst(value);
|
||||
if(value instanceof Integer)
|
||||
v.iconst((Integer) value);
|
||||
else
|
||||
if(value instanceof Long)
|
||||
v.lconst((Long) value);
|
||||
else
|
||||
if(value instanceof Float)
|
||||
v.fconst((Float) value);
|
||||
else
|
||||
if(value instanceof Double)
|
||||
v.dconst((Double) value);
|
||||
else
|
||||
v.aconst(value);
|
||||
coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
|
||||
if (value instanceof Boolean) {
|
||||
boolean boolValue = ((Boolean) value).booleanValue();
|
||||
boolean boolValue = (Boolean) value;
|
||||
if (boolValue ^ jumpIfFalse) {
|
||||
v.goTo(label);
|
||||
}
|
||||
@@ -367,18 +424,23 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private static class ArrayElement extends StackValue {
|
||||
public ArrayElement(Type type) {
|
||||
private Type boxed;
|
||||
|
||||
public ArrayElement(Type type, boolean unbox) {
|
||||
super(type);
|
||||
this.boxed = unbox ? JetTypeMapper.boxType(type) : type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Type type, InstructionAdapter v) {
|
||||
v.aload(type); // assumes array and index are on the stack
|
||||
v.aload(boxed); // assumes array and index are on the stack
|
||||
onStack(boxed).coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store(InstructionAdapter v) {
|
||||
v.astore(type); // assumes array and index are on the stack
|
||||
onStack(type).coerce(boxed, v);
|
||||
v.astore(boxed);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,6 +470,7 @@ public abstract class StackValue {
|
||||
throw new UnsupportedOperationException("no getter specified");
|
||||
}
|
||||
getter.invoke(v);
|
||||
coerce(type, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
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) {
|
||||
super(aClass, context, v, state);
|
||||
}
|
||||
|
||||
//todo not needed when frontend will be able to calculate properly
|
||||
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
|
||||
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
||||
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
if (declaration != null) {
|
||||
if (declaration instanceof PsiClass) {
|
||||
if (!((PsiClass) declaration).isInterface()) {
|
||||
return superClassDescriptor.getDefaultType();
|
||||
}
|
||||
}
|
||||
else if(declaration instanceof JetClass) {
|
||||
if(!((JetClass) declaration).isTrait()) {
|
||||
return superClassDescriptor.getDefaultType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return JetStandardClasses.getAnyType();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
v.visit(Opcodes.V1_6,
|
||||
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
|
||||
jvmName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
new String[0]
|
||||
);
|
||||
v.visitSource(myClass.getContainingFile().getName(), null);
|
||||
}
|
||||
|
||||
private String jvmName() {
|
||||
return state.getTypeMapper().jvmName(descriptor, OwnerKind.TRAIT_IMPL);
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -5,6 +5,7 @@ import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
@@ -15,9 +16,10 @@ import java.util.List;
|
||||
*/
|
||||
public class ArraySize implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
codegen.ensureReceiverOnStack(element, null, JetTypeMapper.TYPE_OBJECT);
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
v.arraylength();
|
||||
|
||||
return StackValue.onStack(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
@@ -21,16 +20,16 @@ public class BinaryOp implements IntrinsicMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
if (arguments.size() == 1) {
|
||||
// intrinsic is called as an ordinary function
|
||||
codegen.ensureReceiverOnStack(element, null, expectedType);
|
||||
if (receiver != null) {
|
||||
receiver.put(expectedType, v);
|
||||
}
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
}
|
||||
else {
|
||||
if (!haveReceiver) {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
}
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
codegen.gen(arguments.get(1), expectedType);
|
||||
}
|
||||
v.visitInsn(expectedType.getOpcode(opcode));
|
||||
+9
-7
@@ -14,16 +14,18 @@ import java.util.List;
|
||||
*/
|
||||
public class Concat implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
codegen.generateStringBuilderConstructor();
|
||||
if (haveReceiver) {
|
||||
v.swap();
|
||||
codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0)));
|
||||
}
|
||||
else {
|
||||
if (receiver == null) { // LHS.plus(RHS)
|
||||
v.swap(); // StringBuilder LHS
|
||||
codegen.invokeAppendMethod(codegen.expressionType(arguments.get(0))); // StringBuilder(LHS)
|
||||
codegen.invokeAppend(arguments.get(0));
|
||||
}
|
||||
codegen.invokeAppend(arguments.get(1));
|
||||
else { // LHS + RHS
|
||||
codegen.invokeAppend(arguments.get(0)); // StringBuilder(LHS)
|
||||
codegen.invokeAppend(arguments.get(1));
|
||||
}
|
||||
|
||||
v.invokevirtual(ExpressionCodegen.CLASS_STRING_BUILDER, "toString", "()Ljava/lang/String;");
|
||||
return StackValue.onStack(Type.getObjectType("java/lang/String"));
|
||||
}
|
||||
+5
-5
@@ -22,7 +22,7 @@ public class Increment implements IntrinsicMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
final JetExpression operand = arguments.get(0);
|
||||
if (operand instanceof JetReferenceExpression) {
|
||||
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
|
||||
@@ -31,17 +31,17 @@ public class Increment implements IntrinsicMethod {
|
||||
return StackValue.local(index, expectedType);
|
||||
}
|
||||
}
|
||||
StackValue value = codegen.generateIntermediateValue(operand);
|
||||
StackValue value = codegen.genQualified(receiver, operand);
|
||||
value.dupReceiver(v, 0);
|
||||
value.put(expectedType, v);
|
||||
if (expectedType == Type.LONG_TYPE) {
|
||||
v.aconst(Long.valueOf(myDelta));
|
||||
v.lconst(myDelta);
|
||||
}
|
||||
else if (expectedType == Type.FLOAT_TYPE) {
|
||||
v.aconst(Float.valueOf(myDelta));
|
||||
v.fconst(myDelta);
|
||||
}
|
||||
else if (expectedType == Type.DOUBLE_TYPE) {
|
||||
v.aconst(Double.valueOf(myDelta));
|
||||
v.dconst(myDelta);
|
||||
}
|
||||
else {
|
||||
v.aconst(myDelta);
|
||||
+1
-1
@@ -14,5 +14,5 @@ import java.util.List;
|
||||
* @author yole
|
||||
*/
|
||||
public interface IntrinsicMethod extends Callable {
|
||||
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver);
|
||||
StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver);
|
||||
}
|
||||
+21
-6
@@ -7,7 +7,7 @@ import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
@@ -29,6 +29,7 @@ public class IntrinsicMethods {
|
||||
private static final IntrinsicMethod DEC = new Increment(-1);
|
||||
|
||||
private static final List<String> PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
|
||||
public static final ArraySize ARRAY_SIZE = new ArraySize();
|
||||
|
||||
private final Project myProject;
|
||||
private final JetStandardLibrary myStdLib;
|
||||
@@ -41,7 +42,6 @@ public class IntrinsicMethods {
|
||||
for (String method : primitiveCastMethods) {
|
||||
declareIntrinsicProperty("Number", method, NUMBER_CAST);
|
||||
}
|
||||
declareIntrinsicProperty("Array", "size", new ArraySize());
|
||||
|
||||
for (String type : PRIMITIVE_NUMBER_TYPES) {
|
||||
declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS);
|
||||
@@ -51,7 +51,7 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction(type, "dec", 0, DEC);
|
||||
}
|
||||
|
||||
final FunctionGroup typeInfoFunctionGroup = stdlib.getTypeInfoFunctionGroup();
|
||||
final Set<FunctionDescriptor> typeInfoFunctionGroup = stdlib.getTypeInfoFunctions();
|
||||
declareOverload(typeInfoFunctionGroup, 0, TYPEINFO);
|
||||
declareOverload(typeInfoFunctionGroup, 1, VALUE_TYPEINFO);
|
||||
|
||||
@@ -72,6 +72,21 @@ public class IntrinsicMethods {
|
||||
declareIntrinsicFunction("String", "plus", 1, new Concat());
|
||||
|
||||
declareIntrinsicStringMethods();
|
||||
declareIntrinsicProperty("String", "length", new StringLength());
|
||||
|
||||
declareArrayMethods();
|
||||
}
|
||||
|
||||
private void declareArrayMethods() {
|
||||
declareIntrinsicProperty("Array", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("ByteArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("ShortArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("IntArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("LongArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("FloatArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("DoubleArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("CharArray", "size", ARRAY_SIZE);
|
||||
declareIntrinsicProperty("BooleanArray", "size", ARRAY_SIZE);
|
||||
}
|
||||
|
||||
private void declareIntrinsicStringMethods() {
|
||||
@@ -107,12 +122,12 @@ public class IntrinsicMethods {
|
||||
|
||||
private void declareIntrinsicFunction(String className, String functionName, int arity, IntrinsicMethod implementation) {
|
||||
JetScope memberScope = getClassMemberScope(className);
|
||||
final FunctionGroup group = memberScope.getFunctionGroup(functionName);
|
||||
final Set<FunctionDescriptor> group = memberScope.getFunctions(functionName);
|
||||
declareOverload(group, arity, implementation);
|
||||
}
|
||||
|
||||
private void declareOverload(FunctionGroup group, int arity, IntrinsicMethod implementation) {
|
||||
for (FunctionDescriptor descriptor : group.getFunctionDescriptors()) {
|
||||
private void declareOverload(Set<FunctionDescriptor> group, int arity, IntrinsicMethod implementation) {
|
||||
for (FunctionDescriptor descriptor : group) {
|
||||
if (descriptor.getValueParameters().size() == arity) {
|
||||
myMethods.put(descriptor.getOriginal(), implementation);
|
||||
}
|
||||
+3
-3
@@ -14,9 +14,9 @@ import java.util.List;
|
||||
*/
|
||||
public class Inv implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
codegen.putTopOfStack(expectedType);
|
||||
v.aconst(-1);
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(expectedType, v);
|
||||
v.iconst(-1);
|
||||
v.xor(expectedType);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
+3
-3
@@ -14,13 +14,13 @@ import java.util.List;
|
||||
*/
|
||||
public class Not implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
final StackValue stackValue;
|
||||
if (arguments.size() == 1) {
|
||||
stackValue = codegen.generateIntermediateValue(arguments.get(0));
|
||||
stackValue = codegen.gen(arguments.get(0));
|
||||
}
|
||||
else {
|
||||
stackValue = codegen.getReceiverAsStackValue(element, null, expectedType);
|
||||
stackValue = receiver;
|
||||
}
|
||||
return StackValue.not(stackValue);
|
||||
}
|
||||
+2
-2
@@ -14,8 +14,8 @@ import java.util.List;
|
||||
*/
|
||||
public class NumberCast implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
codegen.putTopOfStack(expectedType);
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(expectedType, v);
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -24,9 +24,9 @@ public class PsiMethodCall implements IntrinsicMethod {
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element,
|
||||
List<JetExpression> arguments, boolean haveReceiver) {
|
||||
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod);
|
||||
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, haveReceiver);
|
||||
List<JetExpression> arguments, StackValue receiver) {
|
||||
final CallableMethod callableMethod = codegen.getTypeMapper().mapToCallableMethod(myMethod, null);
|
||||
codegen.invokeMethodWithArguments(callableMethod, (JetCallExpression) element, receiver);
|
||||
return StackValue.onStack(callableMethod.getSignature().getReturnType());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class RangeTo implements IntrinsicMethod {
|
||||
private static final String CLASS_INT_RANGE = "jet/IntRange";
|
||||
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
||||
final Type leftType = codegen.expressionType(expression.getLeft());
|
||||
if (JetTypeMapper.isIntPrimitive(leftType)) {
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.jet.codegen.intrinsics;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.jet.codegen.JetTypeMapper;
|
||||
import org.jetbrains.jet.codegen.StackValue;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author alex.tkachman
|
||||
*/
|
||||
public class StringLength implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
|
||||
v.invokevirtual("java/lang/String", "length", "()I");
|
||||
return StackValue.onStack(Type.INT_TYPE);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@ import java.util.List;
|
||||
*/
|
||||
public class TypeInfo implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
final List<JetTypeProjection> typeArguments = ((JetCallExpression) element).getTypeArguments();
|
||||
if (typeArguments.size() != 1) {
|
||||
throw new UnsupportedOperationException("one type argument expected");
|
||||
+2
-2
@@ -14,12 +14,12 @@ import java.util.List;
|
||||
*/
|
||||
public class UnaryMinus implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
if (arguments.size() == 1) {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
}
|
||||
else {
|
||||
codegen.ensureReceiverOnStack(element, null, expectedType);
|
||||
receiver.put(expectedType, v);
|
||||
}
|
||||
v.neg(expectedType);
|
||||
return StackValue.onStack(expectedType);
|
||||
+1
-1
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
*/
|
||||
public class ValueTypeInfo implements IntrinsicMethod {
|
||||
@Override
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
|
||||
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
|
||||
codegen.gen(arguments.get(0), JetTypeMapper.TYPE_JET_OBJECT);
|
||||
v.invokeinterface("jet/JetObject", "getTypeInfo", "()Ljet/typeinfo/TypeInfo;");
|
||||
return StackValue.onStack(JetTypeMapper.TYPE_TYPEINFO);
|
||||
@@ -0,0 +1,13 @@
|
||||
<?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="frontend" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
+60
-12
@@ -1,15 +1,19 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -19,16 +23,31 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
private TypeConstructor typeConstructor;
|
||||
private JavaClassMembersScope unsubstitutedMemberScope;
|
||||
private JetType classObjectType;
|
||||
private final WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
||||
private final Set<FunctionDescriptor> constructors = Sets.newLinkedHashSet();
|
||||
private Modality modality;
|
||||
private Visibility visibility;
|
||||
private JetType superclassType;
|
||||
private final ClassKind kind;
|
||||
private ClassReceiver implicitReceiver;
|
||||
|
||||
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration) {
|
||||
|
||||
public JavaClassDescriptor(DeclarationDescriptor containingDeclaration, @NotNull ClassKind kind) {
|
||||
super(containingDeclaration);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public void setTypeConstructor(TypeConstructor typeConstructor) {
|
||||
this.typeConstructor = typeConstructor;
|
||||
}
|
||||
|
||||
public void setModality(Modality modality) {
|
||||
this.modality = modality;
|
||||
}
|
||||
|
||||
public void setVisibility(Visibility visibility) {
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public void setUnsubstitutedMemberScope(JavaClassMembersScope memberScope) {
|
||||
this.unsubstitutedMemberScope = memberScope;
|
||||
}
|
||||
@@ -48,7 +67,7 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
}
|
||||
|
||||
public void addConstructor(ConstructorDescriptor constructorDescriptor) {
|
||||
this.constructors.addFunction(constructorDescriptor);
|
||||
this.constructors.add(constructorDescriptor);
|
||||
}
|
||||
|
||||
private TypeSubstitutor createTypeSubstitutor(List<TypeProjection> typeArguments) {
|
||||
@@ -70,10 +89,17 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getConstructors() {
|
||||
// assert typeArguments.size() == typeConstructor.getParameters().size();
|
||||
// if (typeArguments.isEmpty()) return constructors;
|
||||
// return new LazySubstitutingFunctionGroup(createTypeSubstitutor(typeArguments), constructors);
|
||||
public JetType getSuperclassType() {
|
||||
return superclassType;
|
||||
}
|
||||
|
||||
public void setSuperclassType(@NotNull JetType superclassType) {
|
||||
this.superclassType = superclassType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<FunctionDescriptor> getConstructors() {
|
||||
return constructors;
|
||||
}
|
||||
|
||||
@@ -111,13 +137,26 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject() {
|
||||
public boolean isClassObjectAValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public boolean isClassObjectAValue() {
|
||||
return false;
|
||||
public ClassKind getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Modality getModality() {
|
||||
return modality;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,4 +168,13 @@ public class JavaClassDescriptor extends MutableDeclarationDescriptor implements
|
||||
public String toString() {
|
||||
return "java class " + typeConstructor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverDescriptor getImplicitReceiver() {
|
||||
if (implicitReceiver == null) {
|
||||
implicitReceiver = new ClassReceiver(this);
|
||||
}
|
||||
return implicitReceiver;
|
||||
}
|
||||
}
|
||||
+31
-15
@@ -5,12 +5,14 @@ import com.google.common.collect.Sets;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -20,7 +22,7 @@ public class JavaClassMembersScope implements JetScope {
|
||||
private final JavaSemanticServices semanticServices;
|
||||
private final boolean staticMembers;
|
||||
private final DeclarationDescriptor containingDeclaration;
|
||||
private final Map<String, FunctionGroup> functionGroups = Maps.newHashMap();
|
||||
private final Map<String, Set<FunctionDescriptor>> functionGroups = Maps.newHashMap();
|
||||
private final Map<String, VariableDescriptor> variables = Maps.newHashMap();
|
||||
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
|
||||
private Collection<DeclarationDescriptor> allDescriptors;
|
||||
@@ -64,17 +66,12 @@ public class JavaClassMembersScope implements JetScope {
|
||||
return classifierDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DeclarationDescriptor> getAllDescriptors() {
|
||||
if (allDescriptors == null) {
|
||||
allDescriptors = Sets.newHashSet();
|
||||
TypeSubstitutor substitutorForGenericSupertypes;
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes((ClassDescriptor) containingDeclaration);
|
||||
}
|
||||
else {
|
||||
substitutorForGenericSupertypes = TypeSubstitutor.EMPTY;
|
||||
}
|
||||
TypeSubstitutor substitutorForGenericSupertypes = getTypeSubstitutorForSupertypes();
|
||||
|
||||
for (HierarchicalMethodSignature signature : psiClass.getVisibleSignatures()) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
@@ -88,6 +85,9 @@ public class JavaClassMembersScope implements JetScope {
|
||||
}
|
||||
|
||||
for (PsiField field : psiClass.getAllFields()) {
|
||||
if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
VariableDescriptor variableDescriptor = semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
||||
allDescriptors.add(variableDescriptor);
|
||||
}
|
||||
@@ -95,6 +95,17 @@ public class JavaClassMembersScope implements JetScope {
|
||||
return allDescriptors;
|
||||
}
|
||||
|
||||
private TypeSubstitutor getTypeSubstitutorForSupertypes() {
|
||||
TypeSubstitutor substitutorForGenericSupertypes;
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes((ClassDescriptor) containingDeclaration);
|
||||
}
|
||||
else {
|
||||
substitutorForGenericSupertypes = TypeSubstitutor.EMPTY;
|
||||
}
|
||||
return substitutorForGenericSupertypes;
|
||||
}
|
||||
|
||||
private ClassifierDescriptor doGetClassifierDescriptor(String name) {
|
||||
// TODO : suboptimal, walk the list only once
|
||||
for (PsiClass innerClass : psiClass.getAllInnerClasses()) {
|
||||
@@ -123,13 +134,13 @@ public class JavaClassMembersScope implements JetScope {
|
||||
return null;
|
||||
}
|
||||
|
||||
return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor((ClassDescriptor) containingDeclaration, field);
|
||||
return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = functionGroups.get(name);
|
||||
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
||||
Set<FunctionDescriptor> functionGroup = functionGroups.get(name);
|
||||
if (functionGroup == null) {
|
||||
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup(
|
||||
containingDeclaration,
|
||||
@@ -149,7 +160,12 @@ public class JavaClassMembersScope implements JetScope {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getThisType() {
|
||||
return null;
|
||||
public ReceiverDescriptor getImplicitReceiver() {
|
||||
throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class...
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getImplicitReceiversHierarchy(@NotNull List<ReceiverDescriptor> result) {
|
||||
throw new UnsupportedOperationException(); // Should never occur, we don't sit in a Java class...
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.ImportingStrategy;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
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));
|
||||
}
|
||||
};
|
||||
}
|
||||
+122
-29
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
@@ -10,6 +11,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.*;
|
||||
@@ -18,12 +20,14 @@ import java.util.*;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class JavaDescriptorResolver {
|
||||
|
||||
public static String JAVA_ROOT = "<java_root>";
|
||||
|
||||
/*package*/ static final DeclarationDescriptor JAVA_METHOD_TYPE_PARAMETER_PARENT = new DeclarationDescriptorImpl(null, Collections.<AnnotationDescriptor>emptyList(), "<java_generic_method>") {
|
||||
|
||||
/*package*/ static final DeclarationDescriptor JAVA_ROOT = new DeclarationDescriptorImpl(null, Collections.<AnnotationDescriptor>emptyList(), "<java_root>") {
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -36,7 +40,7 @@ public class JavaDescriptorResolver {
|
||||
@NotNull
|
||||
@Override
|
||||
public DeclarationDescriptor substitute(TypeSubstitutor substitutor) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,7 +53,7 @@ public class JavaDescriptorResolver {
|
||||
protected final Map<PsiTypeParameter, TypeParameterDescriptor> typeParameterDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
|
||||
protected final Map<String, NamespaceDescriptor> namespaceDescriptorCache = new HashMap<String, NamespaceDescriptor>();
|
||||
protected final Map<PsiPackage, NamespaceDescriptor> namespaceDescriptorCache = Maps.newHashMap();
|
||||
protected final JavaPsiFacade javaFacade;
|
||||
protected final GlobalSearchScope javaSearchScope;
|
||||
protected final JavaSemanticServices semanticServices;
|
||||
@@ -90,7 +94,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
String name = psiClass.getName();
|
||||
JavaClassDescriptor classDescriptor = new JavaClassDescriptor(
|
||||
JAVA_ROOT
|
||||
resolveParentDescriptor(psiClass), psiClass.isInterface() ? ClassKind.TRAIT : ClassKind.CLASS
|
||||
);
|
||||
classDescriptor.setName(name);
|
||||
|
||||
@@ -106,11 +110,27 @@ public class JavaDescriptorResolver {
|
||||
supertypes
|
||||
|
||||
));
|
||||
classDescriptor.setModality(Modality.convertFromFlags(
|
||||
psiClass.hasModifierProperty(PsiModifier.ABSTRACT) || psiClass.isInterface(),
|
||||
!psiClass.hasModifierProperty(PsiModifier.FINAL))
|
||||
);
|
||||
classDescriptor.setVisibility(resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), psiClass));
|
||||
classDescriptorCache.put(psiClass.getQualifiedName(), classDescriptor);
|
||||
classDescriptor.setUnsubstitutedMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false));
|
||||
classDescriptor.setClassObjectMemberScope(new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, true));
|
||||
// UGLY HACK
|
||||
supertypes.addAll(getSupertypes(psiClass));
|
||||
if (psiClass.isInterface()) {
|
||||
classDescriptor.setSuperclassType(JetStandardClasses.getAnyType()); // TODO : Make it java.lang.Object
|
||||
}
|
||||
else {
|
||||
PsiClassType[] extendsListTypes = psiClass.getExtendsListTypes();
|
||||
assert extendsListTypes.length == 0 || extendsListTypes.length == 1;
|
||||
JetType superclassType = extendsListTypes.length == 0
|
||||
? JetStandardClasses.getAnyType()
|
||||
: semanticServices.getTypeTransformer().transformToType(extendsListTypes[0]);
|
||||
classDescriptor.setSuperclassType(superclassType);
|
||||
}
|
||||
|
||||
PsiMethod[] psiConstructors = psiClass.getConstructors();
|
||||
|
||||
@@ -120,7 +140,7 @@ public class JavaDescriptorResolver {
|
||||
classDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
false);
|
||||
constructorDescriptor.initialize(typeParameters, Collections.<ValueParameterDescriptor>emptyList());
|
||||
constructorDescriptor.initialize(typeParameters, Collections.<ValueParameterDescriptor>emptyList(), Modality.FINAL, classDescriptor.getVisibility());
|
||||
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
classDescriptor.addConstructor(constructorDescriptor);
|
||||
semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, psiClass, constructorDescriptor);
|
||||
@@ -132,7 +152,8 @@ public class JavaDescriptorResolver {
|
||||
classDescriptor,
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
false);
|
||||
constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()));
|
||||
constructorDescriptor.initialize(typeParameters, resolveParameterDescriptors(constructorDescriptor, constructor.getParameterList().getParameters()), Modality.FINAL,
|
||||
resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), constructor));
|
||||
constructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
classDescriptor.addConstructor(constructorDescriptor);
|
||||
semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, constructor, constructorDescriptor);
|
||||
@@ -144,6 +165,17 @@ public class JavaDescriptorResolver {
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
private DeclarationDescriptor resolveParentDescriptor(PsiClass psiClass) {
|
||||
PsiClass containingClass = psiClass.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
return resolveClass(psiClass);
|
||||
}
|
||||
|
||||
PsiJavaFile containingFile = (PsiJavaFile) psiClass.getContainingFile();
|
||||
String packageName = containingFile.getPackageName();
|
||||
return resolveNamespace(packageName);
|
||||
}
|
||||
|
||||
private List<TypeParameterDescriptor> resolveTypeParameters(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter[] typeParameters) {
|
||||
List<TypeParameterDescriptor> result = Lists.newArrayList();
|
||||
for (PsiTypeParameter typeParameter : typeParameters) {
|
||||
@@ -204,7 +236,15 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
|
||||
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(qualifiedName);
|
||||
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
|
||||
if (psiPackage == null) {
|
||||
return null;
|
||||
}
|
||||
return resolveNamespace(psiPackage);
|
||||
}
|
||||
|
||||
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
|
||||
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(psiPackage);
|
||||
if (namespaceDescriptor == null) {
|
||||
// TODO : packages
|
||||
|
||||
@@ -213,31 +253,37 @@ public class JavaDescriptorResolver {
|
||||
// namespaceDescriptor = createJavaNamespaceDescriptor(psiClass);
|
||||
// }
|
||||
// else {
|
||||
PsiPackage psiPackage = javaFacade.findPackage(qualifiedName);
|
||||
if (psiPackage == null) {
|
||||
return null;
|
||||
}
|
||||
namespaceDescriptor = createJavaNamespaceDescriptor(psiPackage);
|
||||
// }
|
||||
namespaceDescriptorCache.put(qualifiedName, namespaceDescriptor);
|
||||
namespaceDescriptorCache.put(psiPackage, namespaceDescriptor);
|
||||
}
|
||||
return namespaceDescriptor;
|
||||
}
|
||||
|
||||
private NamespaceDescriptor createJavaNamespaceDescriptor(PsiPackage psiPackage) {
|
||||
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull PsiPackage psiPackage) {
|
||||
String name = psiPackage.getName();
|
||||
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
|
||||
JAVA_ROOT,
|
||||
resolveParentDescriptor(psiPackage),
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
psiPackage.getName()
|
||||
name == null ? JAVA_ROOT : name
|
||||
);
|
||||
|
||||
namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceDescriptor, semanticServices));
|
||||
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiPackage, namespaceDescriptor);
|
||||
return namespaceDescriptor;
|
||||
}
|
||||
|
||||
private DeclarationDescriptor resolveParentDescriptor(@NotNull PsiPackage psiPackage) {
|
||||
PsiPackage parentPackage = psiPackage.getParentPackage();
|
||||
if (parentPackage == null) {
|
||||
return null;
|
||||
}
|
||||
return resolveNamespace(parentPackage);
|
||||
}
|
||||
|
||||
private NamespaceDescriptor createJavaNamespaceDescriptor(@NotNull final PsiClass psiClass) {
|
||||
JavaNamespaceDescriptor namespaceDescriptor = new JavaNamespaceDescriptor(
|
||||
JAVA_ROOT,
|
||||
resolveParentDescriptor(psiClass),
|
||||
Collections.<AnnotationDescriptor>emptyList(), // TODO
|
||||
psiClass.getName()
|
||||
);
|
||||
@@ -275,7 +321,8 @@ public class JavaDescriptorResolver {
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||
containingDeclaration,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
new MemberModifiers(false, false, false),
|
||||
Modality.FINAL,
|
||||
resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), field),
|
||||
!isFinal,
|
||||
null,
|
||||
field.getName(),
|
||||
@@ -287,27 +334,38 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FunctionGroup resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
||||
WritableFunctionGroup writableFunctionGroup = new WritableFunctionGroup(methodName);
|
||||
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
|
||||
Set<FunctionDescriptor> writableFunctionGroup = Sets.newLinkedHashSet();
|
||||
final Collection<HierarchicalMethodSignature> signatures = psiClass.getVisibleSignatures();
|
||||
TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor);
|
||||
for (HierarchicalMethodSignature signature: signatures) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
continue;
|
||||
}
|
||||
if (!methodName.equals(method.getName())) {
|
||||
if (!methodName.equals(signature.getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FunctionDescriptor substitutedFunctionDescriptor = resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutor, method);
|
||||
FunctionDescriptor substitutedFunctionDescriptor = resolveHierarchicalSignatureToFunction(owner, psiClass, staticMembers, typeSubstitutor, signature);
|
||||
if (substitutedFunctionDescriptor != null) {
|
||||
writableFunctionGroup.addFunction(substitutedFunctionDescriptor);
|
||||
writableFunctionGroup.add(substitutedFunctionDescriptor);
|
||||
}
|
||||
}
|
||||
return writableFunctionGroup;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor resolveHierarchicalSignatureToFunction(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers, TypeSubstitutor typeSubstitutor, HierarchicalMethodSignature signature) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
|
||||
return null;
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutor, method);
|
||||
// if (functionDescriptor != null && !staticMembers) {
|
||||
// for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) {
|
||||
// ((FunctionDescriptorImpl) functionDescriptor).addOverriddenFunction(resolveHierarchicalSignatureToFunction(owner, superSignature.getMethod().getContainingClass(), false, typeSubstitutor, superSignature));
|
||||
// }
|
||||
// }
|
||||
return functionDescriptor;
|
||||
}
|
||||
|
||||
public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) {
|
||||
TypeSubstitutor typeSubstitutor;
|
||||
if (classDescriptor != null) {
|
||||
@@ -343,7 +401,9 @@ public class JavaDescriptorResolver {
|
||||
null,
|
||||
resolveTypeParameters(functionDescriptorImpl, method.getTypeParameters()),
|
||||
semanticServices.getDescriptorResolver().resolveParameterDescriptors(functionDescriptorImpl, parameters),
|
||||
semanticServices.getTypeTransformer().transformToType(returnType)
|
||||
semanticServices.getTypeTransformer().transformToType(returnType),
|
||||
Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)),
|
||||
resolveVisibilityFromPsiModifiers(semanticServices.getTrace(), method)
|
||||
);
|
||||
semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl);
|
||||
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
|
||||
@@ -352,4 +412,37 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
return substitutedFunctionDescriptor;
|
||||
}
|
||||
|
||||
private static Visibility resolveVisibilityFromPsiModifiers(BindingTrace trace, PsiModifierListOwner modifierListOwner) {
|
||||
//TODO report error
|
||||
return modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC) ? Visibility.PUBLIC :
|
||||
(modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE) ? Visibility.PRIVATE :
|
||||
(modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED) ? Visibility.PROTECTED : Visibility.INTERNAL));
|
||||
}
|
||||
|
||||
public TypeParameterDescriptor resolveTypeParameter(PsiTypeParameter typeParameter) {
|
||||
PsiTypeParameterListOwner owner = typeParameter.getOwner();
|
||||
if (owner instanceof PsiClass) {
|
||||
PsiClass psiClass = (PsiClass) owner;
|
||||
return resolveTypeParameter(resolveClass(psiClass), typeParameter);
|
||||
}
|
||||
if (owner instanceof PsiMethod) {
|
||||
PsiMethod psiMethod = (PsiMethod) owner;
|
||||
PsiClass containingClass = psiMethod.getContainingClass();
|
||||
DeclarationDescriptor ownerOwner;
|
||||
TypeSubstitutor substitutorForGenericSupertypes;
|
||||
if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
substitutorForGenericSupertypes = TypeSubstitutor.EMPTY;
|
||||
return resolveTypeParameter(JAVA_METHOD_TYPE_PARAMETER_PARENT, typeParameter);
|
||||
}
|
||||
else {
|
||||
ClassDescriptor classDescriptor = resolveClass(containingClass);
|
||||
ownerOwner = classDescriptor;
|
||||
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(classDescriptor);
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, psiMethod);
|
||||
return resolveTypeParameter(functionDescriptor, typeParameter);
|
||||
}
|
||||
throw new IllegalStateException("Unknown parent type: " + owner);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.AbstractNamespaceDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
+6
-8
@@ -2,7 +2,10 @@ package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.JetScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -31,13 +34,8 @@ public class JavaPackageScope extends JetScopeImpl {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
ClassifierDescriptor classifier = getClassifier(name);
|
||||
if (classifier instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) classifier;
|
||||
return classDescriptor.getConstructors();
|
||||
}
|
||||
return FunctionGroup.EMPTY;
|
||||
public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
+17
-2
@@ -70,7 +70,7 @@ public class JavaTypeTransformer {
|
||||
|
||||
if (psiClass instanceof PsiTypeParameter) {
|
||||
PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass;
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolver.resolveTypeParameter(JavaDescriptorResolver.JAVA_ROOT, typeParameter);
|
||||
TypeParameterDescriptor typeParameterDescriptor = resolver.resolveTypeParameter(typeParameter);
|
||||
return typeParameterDescriptor.getDefaultType();
|
||||
}
|
||||
else {
|
||||
@@ -114,7 +114,14 @@ public class JavaTypeTransformer {
|
||||
|
||||
@Override
|
||||
public JetType visitArrayType(PsiArrayType arrayType) {
|
||||
JetType type = transformToType(arrayType.getComponentType());
|
||||
PsiType componentType = arrayType.getComponentType();
|
||||
if(componentType instanceof PsiPrimitiveType) {
|
||||
JetType jetType = getPrimitiveTypesMap().get("[" + componentType.getCanonicalText());
|
||||
if(jetType != null)
|
||||
return TypeUtils.makeNullable(jetType);
|
||||
}
|
||||
|
||||
JetType type = transformToType(componentType);
|
||||
return TypeUtils.makeNullable(standardLibrary.getArrayType(type));
|
||||
}
|
||||
|
||||
@@ -136,6 +143,14 @@ public class JavaTypeTransformer {
|
||||
primitiveTypesMap.put("float", standardLibrary.getFloatType());
|
||||
primitiveTypesMap.put("double", standardLibrary.getDoubleType());
|
||||
primitiveTypesMap.put("boolean", standardLibrary.getBooleanType());
|
||||
primitiveTypesMap.put("[byte", standardLibrary.getByteArrayType());
|
||||
primitiveTypesMap.put("[short", standardLibrary.getShortArrayType());
|
||||
primitiveTypesMap.put("[char", standardLibrary.getCharArrayType());
|
||||
primitiveTypesMap.put("[int", standardLibrary.getIntArrayType());
|
||||
primitiveTypesMap.put("[long", standardLibrary.getLongArrayType());
|
||||
primitiveTypesMap.put("[float", standardLibrary.getFloatArrayType());
|
||||
primitiveTypesMap.put("[double", standardLibrary.getDoubleArrayType());
|
||||
primitiveTypesMap.put("[boolean", standardLibrary.getBooleanArrayType());
|
||||
primitiveTypesMap.put("void", JetStandardClasses.getUnitType());
|
||||
primitiveTypesMap.put("java.lang.Byte", TypeUtils.makeNullable(standardLibrary.getByteType()));
|
||||
primitiveTypesMap.put("java.lang.Short", TypeUtils.makeNullable(standardLibrary.getShortType()));
|
||||
@@ -1,4 +1,4 @@
|
||||
<project name="Lexer" default="lexer">
|
||||
<project name="JetLexer" default="lexer">
|
||||
<property name="home" value="${basedir}"/>
|
||||
<property file="${home}/idea.properties"/>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?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" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -40,27 +40,83 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
|
||||
// Returns "null" for null
|
||||
fun Any?.toString() : String// = this === other
|
||||
|
||||
class Iterator<out T> {
|
||||
trait Iterator<out T> {
|
||||
fun next() : T
|
||||
abstract val hasNext : Boolean
|
||||
abstract fun hasNext() : Boolean
|
||||
}
|
||||
|
||||
class Iterable<out T> {
|
||||
trait Iterable<out T> {
|
||||
fun iterator() : Iterator<T>
|
||||
}
|
||||
|
||||
class Array<T>(val size : Int) {
|
||||
class Array<T>(val size : Int, init : fun(Int) : T = null ) {
|
||||
fun get(index : Int) : T
|
||||
fun set(index : Int, value : T) : Unit
|
||||
|
||||
fun iterator() : Iterator<T>
|
||||
}
|
||||
|
||||
virtual class Comparable<in T> {
|
||||
class ByteArray(val size : Int) {
|
||||
fun get(index : Int) : Byte
|
||||
fun set(index : Int, value : Byte) : Unit
|
||||
|
||||
fun iterator() : Iterator<Byte>
|
||||
}
|
||||
|
||||
class ShortArray(val size : Int) {
|
||||
fun get(index : Int) : Short
|
||||
fun set(index : Int, value : Short) : Unit
|
||||
|
||||
fun iterator() : Iterator<Short>
|
||||
}
|
||||
|
||||
class IntArray(val size : Int) {
|
||||
fun get(index : Int) : Int
|
||||
fun set(index : Int, value : Int) : Unit
|
||||
|
||||
fun iterator() : Iterator<Int>
|
||||
}
|
||||
|
||||
class LongArray(val size : Int) {
|
||||
fun get(index : Int) : Long
|
||||
fun set(index : Int, value : Long) : Unit
|
||||
|
||||
fun iterator() : Iterator<Long>
|
||||
}
|
||||
|
||||
class FloatArray(val size : Int) {
|
||||
fun get(index : Int) : Float
|
||||
fun set(index : Int, value : Float) : Unit
|
||||
|
||||
fun iterator() : Iterator<Float>
|
||||
}
|
||||
|
||||
class DoubleArray(val size : Int) {
|
||||
fun get(index : Int) : Double
|
||||
fun set(index : Int, value : Double) : Unit
|
||||
|
||||
fun iterator() : Iterator<Double>
|
||||
}
|
||||
|
||||
class CharArray(val size : Int) {
|
||||
fun get(index : Int) : Char
|
||||
fun set(index : Int, value : Char) : Unit
|
||||
|
||||
fun iterator() : Iterator<Char>
|
||||
}
|
||||
|
||||
class BooleanArray(val size : Int) {
|
||||
fun get(index : Int) : Boolean
|
||||
fun set(index : Int, value : Boolean) : Unit
|
||||
|
||||
fun iterator() : Iterator<Boolean>
|
||||
}
|
||||
|
||||
trait Comparable<in T> {
|
||||
fun compareTo(other : T) : Int
|
||||
}
|
||||
|
||||
virtual class Hashable {
|
||||
trait Hashable {
|
||||
fun hashCode() : Int
|
||||
fun equals(other : Any?) : Boolean
|
||||
}
|
||||
@@ -92,11 +148,11 @@ class String() : Comparable<String> {
|
||||
fun trim(): String
|
||||
}
|
||||
|
||||
class Range<in T : Comparable<T>> {
|
||||
trait Range<in T : Comparable<T>> {
|
||||
fun contains(item : T) : Boolean
|
||||
}
|
||||
|
||||
class IntRange<T : Comparable<T>> : Range<T>, Iterable<T> {
|
||||
class IntRange<T : Comparable<T>>(val start : Int, val end : Int) : Range<T>, Iterable<T> {
|
||||
|
||||
}
|
||||
|
||||
@@ -118,7 +174,7 @@ abstract class Number : Hashable {
|
||||
}
|
||||
|
||||
class Double : Number, Comparable<Double> {
|
||||
fun compareTo(other : Double) : Int
|
||||
override fun compareTo(other : Double) : Int
|
||||
fun compareTo(other : Float) : Int
|
||||
fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
@@ -181,7 +237,7 @@ class Double : Number, Comparable<Double> {
|
||||
|
||||
class Float : Number, Comparable<Float> {
|
||||
fun compareTo(other : Double) : Int
|
||||
fun compareTo(other : Float) : Int
|
||||
override fun compareTo(other : Float) : Int
|
||||
fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
@@ -245,7 +301,7 @@ class Float : Number, Comparable<Float> {
|
||||
class Long : Number, Comparable<Long> {
|
||||
fun compareTo(other : Double) : Int
|
||||
fun compareTo(other : Float) : Int
|
||||
fun compareTo(other : Long) : Int
|
||||
override fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
fun compareTo(other : Byte) : Int
|
||||
@@ -317,7 +373,7 @@ class Int : Number, Comparable<Int> {
|
||||
fun compareTo(other : Double) : Int
|
||||
fun compareTo(other : Float) : Int
|
||||
fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
override fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
fun compareTo(other : Byte) : Int
|
||||
fun compareTo(other : Char) : Int
|
||||
@@ -390,7 +446,7 @@ class Char : Number, Comparable<Char> {
|
||||
fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
fun compareTo(other : Char) : Int
|
||||
override fun compareTo(other : Char) : Int
|
||||
fun compareTo(other : Byte) : Int
|
||||
|
||||
fun plus(other : Double) : Double
|
||||
@@ -452,7 +508,7 @@ class Short : Number, Comparable<Short> {
|
||||
fun compareTo(other : Float) : Int
|
||||
fun compareTo(other : Long) : Int
|
||||
fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
override fun compareTo(other : Short) : Int
|
||||
fun compareTo(other : Byte) : Int
|
||||
fun compareTo(other : Char) : Int
|
||||
|
||||
@@ -517,7 +573,7 @@ class Byte : Number, Comparable<Byte> {
|
||||
fun compareTo(other : Int) : Int
|
||||
fun compareTo(other : Short) : Int
|
||||
fun compareTo(other : Char) : Int
|
||||
fun compareTo(other : Byte) : Int
|
||||
override fun compareTo(other : Byte) : Int
|
||||
|
||||
fun plus(other : Double) : Double
|
||||
fun plus(other : Float) : Float
|
||||
+4
-3
@@ -29,7 +29,7 @@ public interface JetNodeTypes {
|
||||
JetNodeType DELEGATOR_BY = new JetNodeType("DELEGATOR_BY", JetDelegatorByExpressionSpecifier.class);
|
||||
JetNodeType DELEGATOR_SUPER_CALL = new JetNodeType("DELEGATOR_SUPER_CALL", JetDelegatorToSuperCall.class);
|
||||
JetNodeType DELEGATOR_SUPER_CLASS = new JetNodeType("DELEGATOR_SUPER_CLASS", JetDelegatorToSuperClass.class);
|
||||
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
|
||||
JetNodeType CONSTRUCTOR_CALLEE = new JetNodeType("CONSTRUCTOR_CALLEE", JetConstructorCalleeExpression.class);
|
||||
JetNodeType VALUE_PARAMETER_LIST = new JetNodeType("VALUE_PARAMETER_LIST", JetParameterList.class);
|
||||
JetNodeType VALUE_PARAMETER = new JetNodeType("VALUE_PARAMETER", JetParameter.class);
|
||||
|
||||
@@ -44,6 +44,7 @@ public interface JetNodeTypes {
|
||||
JetNodeType TYPE_ARGUMENT_LIST = new JetNodeType("TYPE_ARGUMENT_LIST", JetTypeArgumentList.class);
|
||||
JetNodeType VALUE_ARGUMENT_LIST = new JetNodeType("VALUE_ARGUMENT_LIST", JetValueArgumentList.class);
|
||||
JetNodeType VALUE_ARGUMENT = new JetNodeType("VALUE_ARGUMENT", JetValueArgument.class);
|
||||
JetNodeType VALUE_ARGUMENT_NAME = new JetNodeType("VALUE_ARGUMENT_NAME", JetValueArgumentName.class);
|
||||
JetNodeType TYPE_REFERENCE = new JetNodeType("TYPE_REFERENCE", JetTypeReference.class);
|
||||
JetNodeType LABELED_TUPLE_ENTRY = new JetNodeType("LABELED_TUPLE_ENTRY");
|
||||
JetNodeType LABELED_TUPLE_TYPE_ENTRY = new JetNodeType("LABELED_TUPLE_TYPE_ENTRY");
|
||||
@@ -116,10 +117,10 @@ public interface JetNodeTypes {
|
||||
JetNodeType CALL_EXPRESSION = new JetNodeType("CALL_EXPRESSION", JetCallExpression.class);
|
||||
JetNodeType ARRAY_ACCESS_EXPRESSION = new JetNodeType("ARRAY_ACCESS_EXPRESSION", JetArrayAccessExpression.class);
|
||||
JetNodeType INDICES = new JetNodeType("INDICES", JetContainerNode.class);
|
||||
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
|
||||
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
|
||||
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
|
||||
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
|
||||
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
|
||||
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
|
||||
|
||||
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
|
||||
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
|
||||
+1
-8
@@ -25,13 +25,11 @@ public class JetSemanticServices {
|
||||
|
||||
private final JetStandardLibrary standardLibrary;
|
||||
private final JetTypeChecker typeChecker;
|
||||
private final OverloadResolver overloadResolver;
|
||||
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
|
||||
|
||||
private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
this.standardLibrary = standardLibrary;
|
||||
this.typeChecker = new JetTypeChecker(standardLibrary);
|
||||
this.overloadResolver = new OverloadResolver(typeChecker);
|
||||
this.flowDataTraceFactory = flowDataTraceFactory;
|
||||
}
|
||||
|
||||
@@ -55,9 +53,4 @@ public class JetSemanticServices {
|
||||
return typeChecker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolver getOverloadResolver() {
|
||||
return overloadResolver;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+89
-92
@@ -3,7 +3,6 @@ package org.jetbrains.jet.lang.cfg;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
@@ -12,6 +11,8 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
@@ -19,21 +20,19 @@ public class JetControlFlowProcessor {
|
||||
|
||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final JetControlFlowBuilder builder;
|
||||
private final BindingTrace trace;
|
||||
|
||||
public JetControlFlowProcessor(JetSemanticServices semanticServices, BindingTrace trace, JetControlFlowBuilder builder) {
|
||||
this.semanticServices = semanticServices;
|
||||
public JetControlFlowProcessor(BindingTrace trace, JetControlFlowBuilder builder) {
|
||||
this.builder = builder;
|
||||
this.trace = trace;
|
||||
}
|
||||
|
||||
public void generate(@NotNull JetElement subroutineElement, @NotNull JetExpression body) {
|
||||
generateSubroutineControlFlow(subroutineElement, Collections.singletonList(body), false);
|
||||
generateSubroutineControlFlow(subroutineElement, Collections.singletonList(body));
|
||||
}
|
||||
|
||||
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body, boolean preferBlocks) {
|
||||
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
|
||||
if (subroutineElement instanceof JetNamedDeclaration) {
|
||||
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
|
||||
enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
|
||||
@@ -41,7 +40,7 @@ public class JetControlFlowProcessor {
|
||||
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
|
||||
builder.enterSubroutine(subroutineElement, functionLiteral);
|
||||
for (JetElement statement : body) {
|
||||
statement.accept(new CFPVisitor(preferBlocks, false));
|
||||
statement.accept(new CFPVisitor(false));
|
||||
}
|
||||
builder.exitSubroutine(subroutineElement, functionLiteral);
|
||||
}
|
||||
@@ -77,12 +76,13 @@ public class JetControlFlowProcessor {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
trace.getErrorHandler().unresolvedReference(labelExpression);
|
||||
trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (stack.size() > 1) {
|
||||
trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||
// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||
trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = stack.peek();
|
||||
@@ -91,22 +91,22 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
private class CFPVisitor extends JetVisitorVoid {
|
||||
private final boolean preferBlock;
|
||||
// private final boolean preferBlock;
|
||||
private final boolean inCondition;
|
||||
|
||||
private CFPVisitor(boolean preferBlock, boolean inCondition) {
|
||||
this.preferBlock = preferBlock;
|
||||
private CFPVisitor(boolean inCondition) {
|
||||
// this.preferBlock = preferBlock;
|
||||
this.inCondition = inCondition;
|
||||
}
|
||||
|
||||
private void value(@Nullable JetElement element, boolean preferBlock, boolean inCondition) {
|
||||
private void value(@Nullable JetElement element, boolean inCondition) {
|
||||
if (element == null) return;
|
||||
CFPVisitor visitor;
|
||||
if (this.preferBlock == preferBlock && this.inCondition == inCondition) {
|
||||
if (this.inCondition == inCondition) {
|
||||
visitor = this;
|
||||
}
|
||||
else {
|
||||
visitor = new CFPVisitor(preferBlock, inCondition);
|
||||
visitor = new CFPVisitor(inCondition);
|
||||
}
|
||||
element.accept(visitor);
|
||||
exitElement(element);
|
||||
@@ -116,7 +116,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
|
||||
JetExpression innerExpression = expression.getExpression();
|
||||
if (innerExpression != null) {
|
||||
value(innerExpression, false, inCondition);
|
||||
value(innerExpression, inCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class JetControlFlowProcessor {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
||||
if (deparenthesized != null) {
|
||||
enterLabeledElement(labelName, deparenthesized);
|
||||
value(labeledExpression, false, inCondition);
|
||||
value(labeledExpression, inCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,11 +163,11 @@ public class JetControlFlowProcessor {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
JetExpression right = expression.getRight();
|
||||
if (operationType == JetTokens.ANDAND) {
|
||||
value(expression.getLeft(), false, true);
|
||||
value(expression.getLeft(), true);
|
||||
Label resultLabel = builder.createUnboundLabel();
|
||||
builder.jumpOnFalse(resultLabel);
|
||||
if (right != null) {
|
||||
value(right, false, true);
|
||||
value(right, true);
|
||||
}
|
||||
builder.bindLabel(resultLabel);
|
||||
if (!inCondition) {
|
||||
@@ -175,11 +175,11 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
}
|
||||
else if (operationType == JetTokens.OROR) {
|
||||
value(expression.getLeft(), false, true);
|
||||
value(expression.getLeft(), true);
|
||||
Label resultLabel = builder.createUnboundLabel();
|
||||
builder.jumpOnTrue(resultLabel);
|
||||
if (right != null) {
|
||||
value(right, false, true);
|
||||
value(right, true);
|
||||
}
|
||||
builder.bindLabel(resultLabel);
|
||||
if (!inCondition) {
|
||||
@@ -189,7 +189,7 @@ public class JetControlFlowProcessor {
|
||||
else if (operationType == JetTokens.EQ) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (right != null) {
|
||||
value(right, false, false);
|
||||
value(right, false);
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression) {
|
||||
builder.write(expression, left);
|
||||
@@ -201,8 +201,8 @@ public class JetControlFlowProcessor {
|
||||
assert !(left instanceof JetPredicateExpression) : left; // TODO
|
||||
assert !(left instanceof JetHashQualifiedExpression) : left; // TODO
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) left;
|
||||
value(qualifiedExpression.getReceiverExpression(), false, false);
|
||||
value(expression.getOperationReference(), false, false);
|
||||
value(qualifiedExpression.getReceiverExpression(), false);
|
||||
value(expression.getOperationReference(), false);
|
||||
builder.write(expression, left);
|
||||
} else {
|
||||
builder.unsupported(expression); // TODO
|
||||
@@ -211,13 +211,13 @@ public class JetControlFlowProcessor {
|
||||
else if (JetTypeInferrer.assignmentOperationNames.containsKey(operationType)) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left != null) {
|
||||
value(left, false, false);
|
||||
value(left, false);
|
||||
}
|
||||
if (right != null) {
|
||||
value(right, false, false);
|
||||
value(right, false);
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression || left instanceof JetArrayAccessExpression) {
|
||||
value(expression.getOperationReference(), false, false);
|
||||
value(expression.getOperationReference(), false);
|
||||
builder.write(expression, left);
|
||||
}
|
||||
else if (left != null) {
|
||||
@@ -225,21 +225,21 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
}
|
||||
else {
|
||||
value(expression.getLeft(), false, false);
|
||||
value(expression.getLeft(), false);
|
||||
if (right != null) {
|
||||
value(right, false, false);
|
||||
value(right, false);
|
||||
}
|
||||
value(expression.getOperationReference(), false, false);
|
||||
value(expression.getOperationReference(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitAssignToArrayAccess(JetBinaryExpression expression, JetArrayAccessExpression arrayAccessExpression) {
|
||||
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
||||
value(index, false, false);
|
||||
value(index, false);
|
||||
}
|
||||
value(arrayAccessExpression.getArrayExpression(), false, false);
|
||||
value(expression.getOperationReference(), false, false);
|
||||
value(arrayAccessExpression.getArrayExpression(), false);
|
||||
value(expression.getOperationReference(), false);
|
||||
builder.write(expression, arrayAccessExpression); // TODO : ???
|
||||
}
|
||||
|
||||
@@ -254,8 +254,8 @@ public class JetControlFlowProcessor {
|
||||
visitLabeledExpression(referencedName.substring(1), baseExpression);
|
||||
}
|
||||
else {
|
||||
value(baseExpression, false, false);
|
||||
value(operationSign, false, false);
|
||||
value(baseExpression, false);
|
||||
value(operationSign, false);
|
||||
|
||||
boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
|
||||
if (incrementOrDecrement) {
|
||||
@@ -275,13 +275,13 @@ public class JetControlFlowProcessor {
|
||||
public void visitIfExpression(JetIfExpression expression) {
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
value(condition, false, true);
|
||||
value(condition, true);
|
||||
}
|
||||
Label elseLabel = builder.createUnboundLabel();
|
||||
builder.jumpOnFalse(elseLabel);
|
||||
JetExpression thenBranch = expression.getThen();
|
||||
if (thenBranch != null) {
|
||||
value(thenBranch, true, inCondition);
|
||||
value(thenBranch, inCondition);
|
||||
}
|
||||
else {
|
||||
builder.readUnit(expression);
|
||||
@@ -291,7 +291,7 @@ public class JetControlFlowProcessor {
|
||||
builder.bindLabel(elseLabel);
|
||||
JetExpression elseBranch = expression.getElse();
|
||||
if (elseBranch != null) {
|
||||
value(elseBranch, true, inCondition);
|
||||
value(elseBranch, inCondition);
|
||||
}
|
||||
else {
|
||||
builder.readUnit(expression);
|
||||
@@ -311,7 +311,7 @@ public class JetControlFlowProcessor {
|
||||
// This checks are needed for the case of having e.g. return inside finally: 'try {return} finally{return}'
|
||||
if (working) return;
|
||||
working = true;
|
||||
value(finallyBlock.getFinalExpression(), true, inCondition);
|
||||
value(finallyBlock.getFinalExpression(), inCondition);
|
||||
working = false;
|
||||
}
|
||||
});
|
||||
@@ -319,7 +319,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
Label onException = builder.createUnboundLabel();
|
||||
builder.nondeterministicJump(onException);
|
||||
value(expression.getTryBlock(), true, inCondition);
|
||||
value(expression.getTryBlock(), inCondition);
|
||||
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
if (!catchClauses.isEmpty()) {
|
||||
@@ -331,7 +331,7 @@ public class JetControlFlowProcessor {
|
||||
JetCatchClause catchClause = iterator.next();
|
||||
JetExpression catchBody = catchClause.getCatchBody();
|
||||
if (catchBody != null) {
|
||||
value(catchBody, true, false);
|
||||
value(catchBody, false);
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
builder.nondeterministicJump(afterCatches);
|
||||
@@ -345,7 +345,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
if (finallyBlock != null) {
|
||||
builder.exitTryFinally();
|
||||
value(finallyBlock.getFinalExpression(), true, inCondition);
|
||||
value(finallyBlock.getFinalExpression(), inCondition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,14 +356,14 @@ public class JetControlFlowProcessor {
|
||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
value(condition, false, true);
|
||||
value(condition, true);
|
||||
}
|
||||
builder.jumpOnFalse(loopInfo.getExitPoint());
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
value(body, false);
|
||||
}
|
||||
builder.jump(loopInfo.getEntryPoint());
|
||||
builder.exitLoop(expression);
|
||||
@@ -377,12 +377,12 @@ public class JetControlFlowProcessor {
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
value(body, false);
|
||||
}
|
||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||
JetExpression condition = expression.getCondition();
|
||||
if (condition != null) {
|
||||
value(condition, false, true);
|
||||
value(condition, true);
|
||||
}
|
||||
builder.jumpOnTrue(loopInfo.getEntryPoint());
|
||||
builder.exitLoop(expression);
|
||||
@@ -393,7 +393,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitForExpression(JetForExpression expression) {
|
||||
JetExpression loopRange = expression.getLoopRange();
|
||||
if (loopRange != null) {
|
||||
value(loopRange, false, false);
|
||||
value(loopRange, false);
|
||||
}
|
||||
// TODO : primitive cases
|
||||
Label loopExitPoint = builder.createUnboundLabel();
|
||||
@@ -407,7 +407,7 @@ public class JetControlFlowProcessor {
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
JetExpression body = expression.getBody();
|
||||
if (body != null) {
|
||||
value(body, true, false);
|
||||
value(body, false);
|
||||
}
|
||||
|
||||
builder.nondeterministicJump(loopInfo.getEntryPoint());
|
||||
@@ -439,14 +439,16 @@ public class JetControlFlowProcessor {
|
||||
assert targetLabel != null;
|
||||
loop = resolveLabel(labelName, targetLabel, true);
|
||||
if (!isLoop(loop)) {
|
||||
trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
||||
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
||||
loop = null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
loop = builder.getCurrentLoop();
|
||||
if (loop == null) {
|
||||
trace.getErrorHandler().genericError(expression.getNode(), "'break' and 'continue' are only allowed inside a loop");
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "'break' and 'continue' are only allowed inside a loop");
|
||||
trace.report(BREAK_OR_CONTINUE_OUTSIDE_A_LOOP.on(expression));
|
||||
}
|
||||
}
|
||||
return loop;
|
||||
@@ -462,7 +464,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
JetExpression returnedExpression = expression.getReturnedExpression();
|
||||
if (returnedExpression != null) {
|
||||
value(returnedExpression, false, false);
|
||||
value(returnedExpression, false);
|
||||
}
|
||||
JetSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
JetElement subroutine;
|
||||
@@ -487,8 +489,12 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitBlockExpression(JetBlockExpression expression) {
|
||||
for (JetElement statement : expression.getStatements()) {
|
||||
value(statement, true, false);
|
||||
List<JetElement> statements = expression.getStatements();
|
||||
for (JetElement statement : statements) {
|
||||
value(statement, false);
|
||||
}
|
||||
if (statements.isEmpty()) {
|
||||
builder.readUnit(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,52 +512,42 @@ public class JetControlFlowProcessor {
|
||||
JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
List<JetElement> statements = bodyExpression.getStatements();
|
||||
if (preferBlock && !functionLiteral.hasParameterSpecification()) {
|
||||
for (JetElement statement : statements) {
|
||||
value(statement, true, false);
|
||||
}
|
||||
if (statements.isEmpty()) {
|
||||
builder.readUnit(expression);
|
||||
}
|
||||
}
|
||||
else {
|
||||
generateSubroutineControlFlow(expression, statements, true);
|
||||
}
|
||||
generateSubroutineControlFlow(expression, statements);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQualifiedExpression(JetQualifiedExpression expression) {
|
||||
value(expression.getReceiverExpression(), false, false);
|
||||
value(expression.getReceiverExpression(), false);
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
if (selectorExpression != null) {
|
||||
value(selectorExpression, false, false);
|
||||
value(selectorExpression, false);
|
||||
}
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
private void visitCall(JetCall call) {
|
||||
for (JetValueArgument argument : call.getValueArguments()) {
|
||||
private void visitCall(JetCallElement call) {
|
||||
for (ValueArgument argument : call.getValueArguments()) {
|
||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
value(argumentExpression, false, false);
|
||||
value(argumentExpression, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression functionLiteral : call.getFunctionLiteralArguments()) {
|
||||
value(functionLiteral, false, false);
|
||||
value(functionLiteral, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(JetCallExpression expression) {
|
||||
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
|
||||
value(typeArgument, false, false);
|
||||
value(typeArgument, false);
|
||||
}
|
||||
|
||||
visitCall(expression);
|
||||
|
||||
value(expression.getCalleeExpression(), false, false);
|
||||
value(expression.getCalleeExpression(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@@ -567,7 +563,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitProperty(JetProperty property) {
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer != null) {
|
||||
value(initializer, false, false);
|
||||
value(initializer, false);
|
||||
builder.write(property, property);
|
||||
}
|
||||
}
|
||||
@@ -575,7 +571,7 @@ public class JetControlFlowProcessor {
|
||||
@Override
|
||||
public void visitTupleExpression(JetTupleExpression expression) {
|
||||
for (JetExpression entry : expression.getEntries()) {
|
||||
value(entry, false, false);
|
||||
value(entry, false);
|
||||
}
|
||||
builder.read(expression);
|
||||
}
|
||||
@@ -584,7 +580,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
|
||||
IElementType operationType = expression.getOperationSign().getReferencedNameElementType();
|
||||
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
|
||||
value(expression.getLeft(), false, false);
|
||||
value(expression.getLeft(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
else {
|
||||
@@ -596,7 +592,7 @@ public class JetControlFlowProcessor {
|
||||
public void visitThrowExpression(JetThrowExpression expression) {
|
||||
JetExpression thrownExpression = expression.getThrownExpression();
|
||||
if (thrownExpression != null) {
|
||||
value(thrownExpression, false, false);
|
||||
value(thrownExpression, false);
|
||||
}
|
||||
builder.jumpToError(expression);
|
||||
}
|
||||
@@ -604,16 +600,16 @@ public class JetControlFlowProcessor {
|
||||
@Override
|
||||
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
|
||||
for (JetExpression index : expression.getIndexExpressions()) {
|
||||
value(index, false, false);
|
||||
value(index, false);
|
||||
}
|
||||
value(expression.getArrayExpression(), false, false);
|
||||
value(expression.getArrayExpression(), false);
|
||||
// TODO : read 'get' or 'set' function
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIsExpression(JetIsExpression expression) {
|
||||
value(expression.getLeftHandSide(), false, inCondition);
|
||||
value(expression.getLeftHandSide(), inCondition);
|
||||
// TODO : builder.read(expression.getPattern());
|
||||
builder.read(expression);
|
||||
}
|
||||
@@ -624,7 +620,7 @@ public class JetControlFlowProcessor {
|
||||
// TODO : else must be the last
|
||||
JetExpression subjectExpression = expression.getSubjectExpression();
|
||||
if (subjectExpression != null) {
|
||||
value(subjectExpression, false, inCondition);
|
||||
value(subjectExpression, inCondition);
|
||||
}
|
||||
|
||||
Label doneLabel = builder.createUnboundLabel();
|
||||
@@ -635,7 +631,8 @@ public class JetControlFlowProcessor {
|
||||
|
||||
if (whenEntry.isElse()) {
|
||||
if (iterator.hasNext()) {
|
||||
trace.getErrorHandler().genericError(whenEntry.getNode(), "'else' entry must be the last one in a when-expression");
|
||||
// trace.getErrorHandler().genericError(whenEntry.getNode(), "'else' entry must be the last one in a when-expression");
|
||||
trace.report(ELSE_MISPLACED_IN_WHEN.on(whenEntry));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,13 +646,13 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitWhenConditionCall(JetWhenConditionCall condition) {
|
||||
value(condition.getCallSuffixExpression(), false, inCondition); // TODO : inCondition?
|
||||
value(condition.getCallSuffixExpression(), inCondition); // TODO : inCondition?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhenConditionInRange(JetWhenConditionInRange condition) {
|
||||
value(condition.getRangeExpression(), false, inCondition); // TODO : inCondition?
|
||||
value(condition.getOperationReference(), false, inCondition); // TODO : inCondition?
|
||||
value(condition.getRangeExpression(), inCondition); // TODO : inCondition?
|
||||
value(condition.getOperationReference(), inCondition); // TODO : inCondition?
|
||||
// TODO : read the call to contains()...
|
||||
}
|
||||
|
||||
@@ -676,7 +673,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitExpressionPattern(JetExpressionPattern pattern) {
|
||||
value(pattern.getExpression(), false, inCondition);
|
||||
value(pattern.getExpression(), inCondition);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -686,7 +683,7 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitDecomposerPattern(JetDecomposerPattern pattern) {
|
||||
value(pattern.getDecomposerExpression(), false, inCondition);
|
||||
value(pattern.getDecomposerExpression(), inCondition);
|
||||
pattern.getArgumentList().accept(this);
|
||||
}
|
||||
|
||||
@@ -719,7 +716,7 @@ public class JetControlFlowProcessor {
|
||||
builder.nondeterministicJump(nextLabel);
|
||||
|
||||
builder.bindLabel(bodyLabel);
|
||||
value(whenEntry.getExpression(), true, inCondition);
|
||||
value(whenEntry.getExpression(), inCondition);
|
||||
builder.jump(doneLabel);
|
||||
builder.bindLabel(nextLabel);
|
||||
nextLabel = builder.createUnboundLabel();
|
||||
@@ -741,17 +738,17 @@ public class JetControlFlowProcessor {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
value(expression.getObjectDeclaration(), false, inCondition);
|
||||
value(expression.getObjectDeclaration(), inCondition);
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
||||
for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
|
||||
value(delegationSpecifier, false, inCondition);
|
||||
value(delegationSpecifier, inCondition);
|
||||
}
|
||||
for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
|
||||
FOR_LOCAL_CLASSES.value(jetDeclaration, false, false);
|
||||
FOR_LOCAL_CLASSES.value(jetDeclaration, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,7 +757,7 @@ public class JetControlFlowProcessor {
|
||||
for (JetStringTemplateEntry entry : expression.getEntries()) {
|
||||
if (entry instanceof JetStringTemplateEntryWithExpression) {
|
||||
JetStringTemplateEntryWithExpression entryWithExpression = (JetStringTemplateEntryWithExpression) entry;
|
||||
value(entryWithExpression.getExpression(), true, false);
|
||||
value(entryWithExpression.getExpression(), false);
|
||||
}
|
||||
}
|
||||
builder.read(expression);
|
||||
@@ -777,7 +774,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private final CFPVisitor FOR_LOCAL_CLASSES = new CFPVisitor(false, false) {
|
||||
private final CFPVisitor FOR_LOCAL_CLASSES = new CFPVisitor(false) {
|
||||
@Override
|
||||
public void visitNamedFunction(JetNamedFunction function) {
|
||||
// Nothing
|
||||
+13
-15
@@ -1,7 +1,8 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
@@ -9,31 +10,28 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface FunctionDescriptor extends DeclarationDescriptor {
|
||||
@Override
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface CallableDescriptor extends DeclarationDescriptor {
|
||||
@NotNull
|
||||
DeclarationDescriptor getContainingDeclaration();
|
||||
|
||||
@Nullable
|
||||
JetType getReceiverType();
|
||||
ReceiverDescriptor getReceiver();
|
||||
|
||||
@NotNull
|
||||
List<TypeParameterDescriptor> getTypeParameters();
|
||||
|
||||
@NotNull
|
||||
List<ValueParameterDescriptor> getValueParameters();
|
||||
|
||||
@NotNull
|
||||
JetType getReturnType();
|
||||
|
||||
@NotNull
|
||||
FunctionDescriptor getOriginal();
|
||||
@Override
|
||||
CallableDescriptor getOriginal();
|
||||
|
||||
@Override
|
||||
FunctionDescriptor substitute(TypeSubstitutor substitutor);
|
||||
CallableDescriptor substitute(TypeSubstitutor substitutor);
|
||||
|
||||
@NotNull
|
||||
Set<? extends FunctionDescriptor> getOverriddenFunctions();
|
||||
List<ValueParameterDescriptor> getValueParameters();
|
||||
|
||||
@NotNull
|
||||
Set<? extends CallableDescriptor> getOverriddenDescriptors();
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public interface CallableMemberDescriptor extends CallableDescriptor, MemberDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
Set<? extends CallableMemberDescriptor> getOverriddenDescriptors();
|
||||
|
||||
@NotNull
|
||||
CallableMemberDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract);
|
||||
}
|
||||
+21
-3
@@ -2,12 +2,14 @@ package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -17,8 +19,14 @@ public interface ClassDescriptor extends ClassifierDescriptor {
|
||||
@NotNull
|
||||
JetScope getMemberScope(List<TypeProjection> typeArguments);
|
||||
|
||||
/**
|
||||
* @return the superclass for a class descriptor, and the required class fro a trait descriptor
|
||||
*/
|
||||
@NotNull
|
||||
FunctionGroup getConstructors();
|
||||
JetType getSuperclassType();
|
||||
|
||||
@NotNull
|
||||
Set<FunctionDescriptor> getConstructors();
|
||||
|
||||
@Nullable
|
||||
ConstructorDescriptor getUnsubstitutedPrimaryConstructor();
|
||||
@@ -42,5 +50,15 @@ public interface ClassDescriptor extends ClassifierDescriptor {
|
||||
@Nullable
|
||||
JetType getClassObjectType();
|
||||
|
||||
boolean isObject();
|
||||
@NotNull
|
||||
ClassKind getKind();
|
||||
|
||||
@NotNull
|
||||
Modality getModality();
|
||||
|
||||
@NotNull
|
||||
Visibility getVisibility();
|
||||
|
||||
@NotNull
|
||||
ReceiverDescriptor getImplicitReceiver();
|
||||
}
|
||||
+66
-17
@@ -3,13 +3,16 @@ package org.jetbrains.jet.lang.descriptors;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ClassReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -18,8 +21,10 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
private TypeConstructor typeConstructor;
|
||||
|
||||
private JetScope memberDeclarations;
|
||||
private FunctionGroup constructors;
|
||||
private Set<FunctionDescriptor> constructors;
|
||||
private ConstructorDescriptor primaryConstructor;
|
||||
private JetType superclassType;
|
||||
private ReceiverDescriptor implicitReceiver;
|
||||
|
||||
public ClassDescriptorImpl(
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
@@ -28,20 +33,41 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
super(containingDeclaration, annotations, name);
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull Set<FunctionDescriptor> constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor) {
|
||||
return initialize(sealed, typeParameters, supertypes, memberDeclarations, constructors, primaryConstructor, getClassType(supertypes));
|
||||
}
|
||||
|
||||
public final ClassDescriptorImpl initialize(boolean sealed,
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull Collection<JetType> superclasses,
|
||||
@NotNull Collection<JetType> supertypes,
|
||||
@NotNull JetScope memberDeclarations,
|
||||
@NotNull FunctionGroup constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor) {
|
||||
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName(), typeParameters, superclasses);
|
||||
@NotNull Set<FunctionDescriptor> constructors,
|
||||
@Nullable ConstructorDescriptor primaryConstructor,
|
||||
@Nullable JetType superclassType) {
|
||||
this.typeConstructor = new TypeConstructorImpl(this, getAnnotations(), sealed, getName(), typeParameters, supertypes);
|
||||
this.memberDeclarations = memberDeclarations;
|
||||
this.constructors = constructors;
|
||||
this.primaryConstructor = primaryConstructor;
|
||||
// assert !constructors.isEmpty() || primaryConstructor == null;
|
||||
this.superclassType = superclassType;
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JetType getClassType(@NotNull Collection<JetType> types) {
|
||||
for (JetType type : types) {
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(type);
|
||||
if (classDescriptor != null) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return JetStandardClasses.getAnyType();
|
||||
}
|
||||
|
||||
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
|
||||
this.primaryConstructor = primaryConstructor;
|
||||
}
|
||||
@@ -63,6 +89,12 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
return new SubstitutingScope(memberDeclarations, TypeSubstitutor.create(substitutionContext));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getSuperclassType() {
|
||||
return superclassType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
@@ -71,13 +103,8 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getConstructors() {
|
||||
// assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Argument list length mismatch for " + getName();
|
||||
// if (typeArguments.size() == 0) {
|
||||
// return constructors;
|
||||
// }
|
||||
// Map<TypeConstructor, TypeProjection> substitutionContext = TypeUtils.buildSubstitutionContext(getTypeConstructor().getParameters(), typeArguments);
|
||||
return constructors;// LazySubstitutingFunctionGroup(TypeSubstitutor.create(substitutionContext), constructors);
|
||||
public Set<FunctionDescriptor> getConstructors() {
|
||||
return constructors;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -91,9 +118,10 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public boolean isObject() {
|
||||
return false;
|
||||
public ClassKind getKind() {
|
||||
return ClassKind.CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,4 +143,25 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
|
||||
public boolean hasConstructors() {
|
||||
return !constructors.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Modality getModality() {
|
||||
return Modality.FINAL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Visibility getVisibility() {
|
||||
return Visibility.PUBLIC;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ReceiverDescriptor getImplicitReceiver() {
|
||||
if (implicitReceiver == null) {
|
||||
implicitReceiver = new ClassReceiver(this);
|
||||
}
|
||||
return implicitReceiver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public enum ClassKind {
|
||||
CLASS,
|
||||
TRAIT,
|
||||
ENUM_CLASS,
|
||||
ANNOTATION_CLASS,
|
||||
OBJECT
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user