From 37968a7c65eaf96ff0ab937f0a7827e0891c8880 Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Wed, 30 Sep 2015 20:14:04 +0100 Subject: Throw error on wrong number of arguments --- .../org/zwobble/couscous/interpreter/Arguments.java | 18 +++--------------- .../java/org/zwobble/couscous/values/ConcreteType.java | 17 ++++++++++++----- .../java/org/zwobble/couscous/values/IntegerValue.java | 2 +- .../java/org/zwobble/couscous/values/MethodValue.java | 18 ++++++++++++++++-- .../java/org/zwobble/couscous/values/StringValue.java | 15 +++++++++------ .../couscous/tests/interpreter/EvaluatorTests.java | 9 +++++++++ 6 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/zwobble/couscous/interpreter/Arguments.java b/src/main/java/org/zwobble/couscous/interpreter/Arguments.java index d08393d..af674a1 100644 --- a/src/main/java/org/zwobble/couscous/interpreter/Arguments.java +++ b/src/main/java/org/zwobble/couscous/interpreter/Arguments.java @@ -4,26 +4,14 @@ import java.util.List; import org.zwobble.couscous.values.InterpreterValue; -import lombok.val; - public class Arguments { - private int index = 0; private List values; public Arguments(List values) { this.values = values; } - - @SuppressWarnings("unchecked") - public T pop(Class valueType) { - val value = values.get(index); - index++; - if (valueType.isInstance(value)) { - return (T) value; - } else { - // TODO: throw a more specific error - throw new UnsupportedOperationException(); - } - + + public InterpreterValue get(int index) { + return values.get(index); } } diff --git a/src/main/java/org/zwobble/couscous/values/ConcreteType.java b/src/main/java/org/zwobble/couscous/values/ConcreteType.java index c3ead74..ef6665e 100644 --- a/src/main/java/org/zwobble/couscous/values/ConcreteType.java +++ b/src/main/java/org/zwobble/couscous/values/ConcreteType.java @@ -6,6 +6,7 @@ import java.util.function.BiFunction; import org.zwobble.couscous.interpreter.Arguments; import org.zwobble.couscous.interpreter.NoSuchMethod; +import org.zwobble.couscous.interpreter.WrongNumberOfArguments; import com.google.common.collect.ImmutableMap; @@ -13,11 +14,14 @@ import lombok.val; public class ConcreteType { public static class Builder { - private final ImmutableMap.Builder> methods = + private final ImmutableMap.Builder> methods = ImmutableMap.builder(); - public Builder method(String name, BiFunction method) { - methods.put(name, method); + public Builder method( + String name, + List> argumentsTypes, + BiFunction method) { + methods.put(name, new MethodValue(argumentsTypes, method)); return this; } @@ -26,9 +30,9 @@ public class ConcreteType { } } - private Map> methods; + private Map> methods; - public ConcreteType(Map> methods) { + public ConcreteType(Map> methods) { this.methods = methods; } @@ -41,6 +45,9 @@ public class ConcreteType { throw new NoSuchMethod(methodName); } val method = methods.get(methodName); + if (method.getArgumentTypes().size() != arguments.size()) { + throw new WrongNumberOfArguments(method.getArgumentTypes().size(), arguments.size()); + } return method.apply((T)receiver, new Arguments(arguments)); } } diff --git a/src/main/java/org/zwobble/couscous/values/IntegerValue.java b/src/main/java/org/zwobble/couscous/values/IntegerValue.java index eb7031d..8b5b423 100644 --- a/src/main/java/org/zwobble/couscous/values/IntegerValue.java +++ b/src/main/java/org/zwobble/couscous/values/IntegerValue.java @@ -4,7 +4,7 @@ import lombok.Value; @Value public class IntegerValue implements InterpreterValue { - private static final ConcreteType TYPE = ConcreteType.builder() + public static final ConcreteType TYPE = ConcreteType.builder() .build(); int value; diff --git a/src/main/java/org/zwobble/couscous/values/MethodValue.java b/src/main/java/org/zwobble/couscous/values/MethodValue.java index 38ef1d5..fe23f94 100644 --- a/src/main/java/org/zwobble/couscous/values/MethodValue.java +++ b/src/main/java/org/zwobble/couscous/values/MethodValue.java @@ -1,7 +1,21 @@ package org.zwobble.couscous.values; import java.util.List; +import java.util.function.BiFunction; -public interface MethodValue { - InterpreterValue call(List arguments); +import org.zwobble.couscous.interpreter.Arguments; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Value; + +@Value +public class MethodValue { + List> argumentTypes; + @Getter(value=AccessLevel.NONE) + BiFunction apply; + + public InterpreterValue apply(T receiver, Arguments arguments) { + return apply.apply(receiver, arguments); + } } diff --git a/src/main/java/org/zwobble/couscous/values/StringValue.java b/src/main/java/org/zwobble/couscous/values/StringValue.java index da45f02..2d4bf17 100644 --- a/src/main/java/org/zwobble/couscous/values/StringValue.java +++ b/src/main/java/org/zwobble/couscous/values/StringValue.java @@ -1,18 +1,21 @@ package org.zwobble.couscous.values; +import static java.util.Arrays.asList; + import lombok.Value; import lombok.val; @Value public class StringValue implements InterpreterValue { private static final ConcreteType TYPE = ConcreteType.builder() - .method("length", (receiver, arguments) -> new IntegerValue(receiver.value.length())) + .method("length", asList(), (receiver, arguments) -> new IntegerValue(receiver.value.length())) - .method("substring", (receiver, arguments) -> { - val startIndex = arguments.pop(IntegerValue.class); - val endIndex = arguments.pop(IntegerValue.class); - return new StringValue(receiver.value.substring(startIndex.getValue(), endIndex.getValue())); - }) + .method("substring", asList(IntegerValue.TYPE, IntegerValue.TYPE), + (receiver, arguments) -> { + val startIndex = (IntegerValue)arguments.get(0); + val endIndex = (IntegerValue)arguments.get(1); + return new StringValue(receiver.value.substring(startIndex.getValue(), endIndex.getValue())); + }) .build(); diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java index ee4f700..5ebb948 100644 --- a/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/EvaluatorTests.java @@ -6,6 +6,7 @@ import org.zwobble.couscous.ast.TernaryConditionalNode; import org.zwobble.couscous.interpreter.ConditionMustBeBoolean; import org.zwobble.couscous.interpreter.Environment; import org.zwobble.couscous.interpreter.NoSuchMethod; +import org.zwobble.couscous.interpreter.WrongNumberOfArguments; import org.zwobble.couscous.values.IntegerValue; import org.zwobble.couscous.values.StringValue; @@ -73,6 +74,14 @@ public class EvaluatorTests { assertEquals(new NoSuchMethod("size"), exception); } + @Test + public void errorIfWrongNumberOfArgumentsArePassed() { + val exception = assertThrows(WrongNumberOfArguments.class, + () -> eval(emptyEnvironment(), + methodCall(literal("hello"), "substring", literal(1)))); + assertEquals(new WrongNumberOfArguments(2, 1), exception); + } + private static Environment emptyEnvironment() { return new Environment(ImmutableMap.of()); } -- cgit v1.2.3