KT-1202 object construction fix

This commit is contained in:
Alex Tkachman
2012-02-13 08:34:10 +02:00
parent 84ed18c7e2
commit ace34b01bc
6 changed files with 197 additions and 61 deletions
@@ -793,7 +793,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
if(closureCodegen.superCall != null) {
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) closureCodegen.superCall).getCalleeExpression().getConstructorReferenceExpression());
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, closureCodegen.superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
Collections.addAll(consArgTypes, argumentTypes);
@@ -385,7 +385,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
JvmMethodSignature constructorMethod;
CallableMethod callableMethod;
if (constructorDescriptor == null) {
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
signatureWriter.writeFormalTypeParametersStart();
@@ -417,10 +416,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ObjectOrClosureCodegen closure = context.closure;
int firstSuperArgument = -1;
if(closure != null) {
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
final LinkedList<JvmMethodParameterSignature> consArgTypes = new LinkedList<JvmMethodParameterSignature>(constructorMethod.getKotlinParameterTypes());
int insert = 0;
int insert = 0;
if(closure != null) {
if(closure.captureThis) {
if(!CodegenUtil.hasThis0(descriptor))
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0));
@@ -444,22 +443,27 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
assert closure.captureReceiver != null;
}
}
}
if(myClass instanceof JetObjectDeclaration) {
if(superCall instanceof JetDelegatorToSuperCall) {
if(myClass instanceof JetObjectDeclaration && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
if(superCall instanceof JetDelegatorToSuperCall) {
if(closure != null)
closure.superCall = (JetDelegatorToSuperCall) superCall;
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
firstSuperArgument = insert;
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
}
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
if(declarationDescriptor instanceof ClassDescriptor) {
declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor();
}
ConstructorDescriptor superConstructor = (ConstructorDescriptor) declarationDescriptor;
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
firstSuperArgument = insert;
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
}
}
constructorMethod = JvmMethodSignature.simple("<init>", Type.VOID_TYPE, consArgTypes);
}
constructorMethod = JvmMethodSignature.simple("<init>", Type.VOID_TYPE, consArgTypes);
int flags = ACC_PUBLIC; // TODO
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null);
if (!v.generateCode()) return;
@@ -547,7 +551,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
}
else {
iv.load(0, classType);
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument);
}
@@ -726,17 +729,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
ConstructorDescriptor constructorDescriptor,
ConstructorFrameMap frameMap, int firstSuperArgument) {
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
Type type = typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION);
iv.load(0, type);
iv.load(0, TYPE_OBJECT);
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION));
}
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall) {
iv.load(0, TYPE_OBJECT);
if(myClass instanceof JetObjectDeclaration && superCall instanceof JetDelegatorToSuperCall && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
int nextVar = firstSuperArgument+1;
@@ -0,0 +1,11 @@
package interactive;
class Shape(var height : Double = 1.0, var fillColor : String = "#AAAAAA") {
}
fun box() : String {
var a : Shape? = Shape()
a?.height = 1.0
return "OK"
}
@@ -265,4 +265,8 @@ public class ClassGenTest extends CodegenTestCase {
public void testKt471() throws Exception {
blackBoxFile("regressions/kt471.kt");
}
public void testKt1213() throws Exception {
// blackBoxFile("regressions/kt1213.kt");
}
}
+41 -41
View File
@@ -61,7 +61,7 @@
<file leaf-file-name="Main.kt" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/src/Main.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="32" column="57" selection-start="881" selection-end="881" vertical-scroll-proportion="1.3675214">
<state line="29" column="74" selection-start="845" selection-end="845" vertical-scroll-proportion="1.2393162">
<folding />
</state>
</provider>
@@ -100,12 +100,16 @@
<sortByType />
</navigator>
<panes>
<pane id="Scope">
<subPane subId="Project Files">
<pane id="PackagesPane">
<subPane>
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
<PATH_ELEMENT>
<option name="myItemId" value="actors" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="actors" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
@@ -144,16 +148,12 @@
</PATH>
</subPane>
</pane>
<pane id="PackagesPane">
<subPane>
<pane id="Scope">
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="actors" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="actors" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane>
@@ -161,17 +161,17 @@
</panes>
</component>
<component name="PropertiesComponent">
<property name="project.structure.last.edited" value="Modules" />
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="project.structure.proportion" value="0.15" />
<property name="project.structure.last.edited" value="Modules" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
<property name="recentsLimit" value="5" />
<property name="project.structure.proportion" value="0.15" />
<property name="MemberChooser.sorted" value="false" />
<property name="recentsLimit" value="5" />
<property name="MemberChooser.showClasses" value="true" />
<property name="project.structure.side.proportion" value="0.2" />
<property name="GoToClass.includeLibraries" value="false" />
<property name="dynamic.classpath" value="false" />
<property name="project.structure.side.proportion" value="0.2" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="dynamic.classpath" value="false" />
</component>
<component name="RunManager" selected="Kotlin.org.jetbrains.kotlin.examples.actors">
<configuration default="false" name="org.jetbrains.kotlin.examples.actors" type="JetRunConfigurationType" factoryName="Kotlin" temporary="true">
@@ -228,6 +228,24 @@
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="TestNG" factoryName="TestNG">
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@@ -260,24 +278,6 @@
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Applet" factoryName="Applet">
<module name="" />
<option name="MAIN_CLASS_NAME" />
<option name="HTML_FILE_NAME" />
<option name="HTML_USED" value="false" />
<option name="WIDTH" value="400" />
<option name="HEIGHT" value="300" />
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<option name="VM_PARAMETERS" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<method>
<option name="AntTarget" enabled="false" />
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
<option name="Maven.BeforeRunTask" enabled="false" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" />
<option name="VM_PARAMETERS" />
@@ -341,7 +341,7 @@
</component>
<component name="ToolWindowManager">
<frame x="0" y="22" width="1440" height="874" extended-state="6" />
<editor active="true" />
<editor active="false" />
<layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
@@ -357,7 +357,7 @@
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="true" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.18175288" sideWeight="0.50199205" order="0" side_tool="false" content_ui="combo" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.10632184" sideWeight="0.50199205" order="0" side_tool="false" content_ui="combo" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.49800798" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="ResolveWindow" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
@@ -426,7 +426,7 @@
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/Main.kt">
<provider selected="true" editor-type-id="text-editor">
<state line="32" column="57" selection-start="881" selection-end="881" vertical-scroll-proportion="1.3675214">
<state line="29" column="74" selection-start="845" selection-end="845" vertical-scroll-proportion="1.2393162">
<folding />
</state>
</provider>
+119
View File
@@ -0,0 +1,119 @@
package testeval
import java.util.*
import junit.framework.TestCase.*
trait Expression
class Num(val value : Int) : Expression
class Sum(val left : Expression, val right : Expression) : Expression
class Mult(val left : Expression, val right : Expression) : Expression
fun eval(e : Expression) : Int {
return when (e) {
is Num -> e.value
is Sum -> eval(e.left) + eval (e.right)
is Mult -> eval(e.left) * eval (e.right)
else -> throw AssertionError("Unknown expression")
}
}
trait ParseResult<out T> {
val success : Boolean
val value : T
}
class Success<T>(override val value : T) : ParseResult<T> {
public override val success : Boolean = true
}
class Failure(val message : String) : ParseResult<Nothing> {
override val success = false
override val value : Nothing = throw UnsupportedOperationException("Don't call value on a Failure")
}
open class Token(val text : String) {
fun toString() = text
}
object LPAR : Token("(")
object RPAR : Token(")")
object PLUS : Token("+")
object TIMES : Token("*")
object EOF : Token("EOF")
class Number(text : String) : Token(text)
class Error(text : String) : Token("[Error: $text]")
fun tokenize(text : String) : Deque<Token> {
val result = LinkedList<Token>()
for (c in text) {
result add when (c) {
'(' -> LPAR
')' -> RPAR
'+' -> PLUS
'*' -> TIMES
in '0'..'9' -> Number(c.toString())
else -> Error(c.toString())
}
}
result.add(EOF)
return result
}
fun parseSum(tokens : Deque<Token>) : ParseResult<Expression> {
val left = parseMult(tokens)
if (!left.success) return left
if (tokens.peek() == PLUS) {
tokens.pop()
val right = parseSum(tokens)
if (!right.success) return right
return Success(Sum(left.value, right.value))
}
return left
}
fun parseMult(tokens : Deque<Token>) : ParseResult<Expression> {
val left = parseAtomic(tokens)
if (!left.success) return left
if (tokens.peek() == PLUS) {
tokens.pop()
val right = parseMult(tokens)
if (!right.success) return right
return Success(Mult(left.value, right.value))
}
return left
}
fun parseAtomic(tokens : Deque<Token>) : ParseResult<Expression> {
val token = tokens.poll()
return when (token) {
LPAR -> {
val result = parseSum(tokens)
val rpar = tokens.poll()
if (rpar == RPAR)
result
else
Failure("Expecting ')'")
}
is Number -> Success(Num(Integer.parseInt((token as Token).text).sure()))
else -> Failure("Unexpected EOF")
}
}
fun parse(text : String) : ParseResult<Expression> = parseSum(tokenize(text))
class EvalTest : junit.framework.TestCase() {
fun testEval() {
assertEquals(1, eval(Num(1)))
assertEquals(2, eval(Sum(Num(1), Num(1))))
assertEquals(3, eval(Mult(Num(3), Num(1))))
assertEquals(6, eval(Mult(Num(3), Sum(Num(1), Num(1)))))
}
fun testParse() {
assertEquals(1, eval(parse("1").value))
}
}