KT-1202 object construction fix
This commit is contained in:
@@ -793,7 +793,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(closureCodegen.superCall != null) {
|
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);
|
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
||||||
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
Type[] argumentTypes = superCallable.getSignature().getAsmMethod().getArgumentTypes();
|
||||||
Collections.addAll(consArgTypes, argumentTypes);
|
Collections.addAll(consArgTypes, argumentTypes);
|
||||||
|
|||||||
@@ -385,7 +385,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
JvmMethodSignature constructorMethod;
|
JvmMethodSignature constructorMethod;
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (constructorDescriptor == null) {
|
if (constructorDescriptor == null) {
|
||||||
|
|
||||||
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
BothSignatureWriter signatureWriter = new BothSignatureWriter(BothSignatureWriter.Mode.METHOD, false);
|
||||||
|
|
||||||
signatureWriter.writeFormalTypeParametersStart();
|
signatureWriter.writeFormalTypeParametersStart();
|
||||||
@@ -417,10 +416,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
ObjectOrClosureCodegen closure = context.closure;
|
ObjectOrClosureCodegen closure = context.closure;
|
||||||
int firstSuperArgument = -1;
|
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(closure.captureThis) {
|
||||||
if(!CodegenUtil.hasThis0(descriptor))
|
if(!CodegenUtil.hasThis0(descriptor))
|
||||||
consArgTypes.add(insert, new JvmMethodParameterSignature(Type.getObjectType(context.getThisDescriptor().getName()), "", JvmMethodParameterKind.THIS0));
|
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;
|
assert closure.captureReceiver != null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(myClass instanceof JetObjectDeclaration) {
|
if(myClass instanceof JetObjectDeclaration && ((JetObjectDeclaration) myClass).isObjectLiteral()) {
|
||||||
if(superCall instanceof JetDelegatorToSuperCall) {
|
if(superCall instanceof JetDelegatorToSuperCall) {
|
||||||
|
if(closure != null)
|
||||||
closure.superCall = (JetDelegatorToSuperCall) superCall;
|
closure.superCall = (JetDelegatorToSuperCall) superCall;
|
||||||
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
if(declarationDescriptor instanceof ClassDescriptor) {
|
||||||
firstSuperArgument = insert;
|
declarationDescriptor = ((ClassDescriptor)declarationDescriptor).getUnsubstitutedPrimaryConstructor();
|
||||||
for(Type t : superCallable.getSignature().getAsmMethod().getArgumentTypes()) {
|
}
|
||||||
consArgTypes.add(insert++, new JvmMethodParameterSignature(t, "", JvmMethodParameterKind.SHARED_VAR));
|
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
|
int flags = ACC_PUBLIC; // TODO
|
||||||
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null);
|
final MethodVisitor mv = v.newMethod(myClass, flags, constructorMethod.getName(), constructorMethod.getAsmMethod().getDescriptor(), constructorMethod.getGenericsSignature(), null);
|
||||||
if (!v.generateCode()) return;
|
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());
|
iv.invokespecial(typeMapper.mapType(superClassDescriptor.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "<init>", superCallMethod.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
iv.load(0, classType);
|
|
||||||
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
ConstructorDescriptor constructorDescriptor1 = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
||||||
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument);
|
generateDelegatorToConstructorCall(iv, codegen, (JetDelegatorToSuperCall) superCall, constructorDescriptor1, frameMap, firstSuperArgument);
|
||||||
}
|
}
|
||||||
@@ -726,17 +729,16 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ConstructorDescriptor constructorDescriptor,
|
ConstructorDescriptor constructorDescriptor,
|
||||||
ConstructorFrameMap frameMap, int firstSuperArgument) {
|
ConstructorFrameMap frameMap, int firstSuperArgument) {
|
||||||
ClassDescriptor classDecl = constructorDescriptor.getContainingDeclaration();
|
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) {
|
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||||
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
iv.load(frameMap.getOuterThisIndex(), typeMapper.mapType(((ClassDescriptor) descriptor.getContainingDeclaration()).getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||||
}
|
}
|
||||||
|
|
||||||
CallableMethod method = typeMapper.mapToCallableMethod(constructorDescriptor, kind);
|
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());
|
ConstructorDescriptor superConstructor = (ConstructorDescriptor) bindingContext.get(BindingContext.REFERENCE_TARGET, ((JetDelegatorToSuperCall) superCall).getCalleeExpression().getConstructorReferenceExpression());
|
||||||
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
CallableMethod superCallable = typeMapper.mapToCallableMethod(superConstructor, OwnerKind.IMPLEMENTATION);
|
||||||
int nextVar = firstSuperArgument+1;
|
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 {
|
public void testKt471() throws Exception {
|
||||||
blackBoxFile("regressions/kt471.kt");
|
blackBoxFile("regressions/kt471.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testKt1213() throws Exception {
|
||||||
|
// blackBoxFile("regressions/kt1213.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
<file leaf-file-name="Main.kt" pinned="false" current="true" current-in-tab="true">
|
<file leaf-file-name="Main.kt" pinned="false" current="true" current-in-tab="true">
|
||||||
<entry file="file://$PROJECT_DIR$/src/Main.kt">
|
<entry file="file://$PROJECT_DIR$/src/Main.kt">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<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 />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
@@ -100,12 +100,16 @@
|
|||||||
<sortByType />
|
<sortByType />
|
||||||
</navigator>
|
</navigator>
|
||||||
<panes>
|
<panes>
|
||||||
<pane id="Scope">
|
<pane id="PackagesPane">
|
||||||
<subPane subId="Project Files">
|
<subPane>
|
||||||
<PATH>
|
<PATH>
|
||||||
<PATH_ELEMENT USER_OBJECT="Root">
|
<PATH_ELEMENT>
|
||||||
<option name="myItemId" value="" />
|
<option name="myItemId" value="actors" />
|
||||||
<option name="myItemType" value="" />
|
<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_ELEMENT>
|
||||||
</PATH>
|
</PATH>
|
||||||
</subPane>
|
</subPane>
|
||||||
@@ -144,16 +148,12 @@
|
|||||||
</PATH>
|
</PATH>
|
||||||
</subPane>
|
</subPane>
|
||||||
</pane>
|
</pane>
|
||||||
<pane id="PackagesPane">
|
<pane id="Scope">
|
||||||
<subPane>
|
<subPane subId="Project Files">
|
||||||
<PATH>
|
<PATH>
|
||||||
<PATH_ELEMENT>
|
<PATH_ELEMENT USER_OBJECT="Root">
|
||||||
<option name="myItemId" value="actors" />
|
<option name="myItemId" value="" />
|
||||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
|
<option name="myItemType" value="" />
|
||||||
</PATH_ELEMENT>
|
|
||||||
<PATH_ELEMENT>
|
|
||||||
<option name="myItemId" value="actors" />
|
|
||||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewModuleNode" />
|
|
||||||
</PATH_ELEMENT>
|
</PATH_ELEMENT>
|
||||||
</PATH>
|
</PATH>
|
||||||
</subPane>
|
</subPane>
|
||||||
@@ -161,17 +161,17 @@
|
|||||||
</panes>
|
</panes>
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">
|
<component name="PropertiesComponent">
|
||||||
<property name="project.structure.last.edited" value="Modules" />
|
|
||||||
<property name="GoToFile.includeJavaFiles" value="false" />
|
<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="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="MemberChooser.sorted" value="false" />
|
||||||
|
<property name="recentsLimit" value="5" />
|
||||||
<property name="MemberChooser.showClasses" value="true" />
|
<property name="MemberChooser.showClasses" value="true" />
|
||||||
<property name="project.structure.side.proportion" value="0.2" />
|
|
||||||
<property name="GoToClass.includeLibraries" value="false" />
|
<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="MemberChooser.copyJavadoc" value="false" />
|
||||||
|
<property name="dynamic.classpath" value="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="Kotlin.org.jetbrains.kotlin.examples.actors">
|
<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">
|
<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" />
|
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</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">
|
<configuration default="true" type="TestNG" factoryName="TestNG">
|
||||||
<module name="" />
|
<module name="" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
@@ -260,24 +278,6 @@
|
|||||||
<option name="Maven.BeforeRunTask" enabled="false" />
|
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||||
</method>
|
</method>
|
||||||
</configuration>
|
</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">
|
<configuration default="true" type="Application" factoryName="Application">
|
||||||
<option name="MAIN_CLASS_NAME" />
|
<option name="MAIN_CLASS_NAME" />
|
||||||
<option name="VM_PARAMETERS" />
|
<option name="VM_PARAMETERS" />
|
||||||
@@ -341,7 +341,7 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<component name="ToolWindowManager">
|
||||||
<frame x="0" y="22" width="1440" height="874" extended-state="6" />
|
<frame x="0" y="22" width="1440" height="874" extended-state="6" />
|
||||||
<editor active="true" />
|
<editor active="false" />
|
||||||
<layout>
|
<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="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" />
|
<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="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="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="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="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="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" />
|
<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">
|
<component name="editorHistoryManager">
|
||||||
<entry file="file://$PROJECT_DIR$/src/Main.kt">
|
<entry file="file://$PROJECT_DIR$/src/Main.kt">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<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 />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
|||||||
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user