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) { 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");
}
} }
+41 -41
View File
@@ -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>
+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))
}
}