diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2016-06-22 22:33:33 +0300 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2016-07-26 19:47:10 +0300 |
| commit | fa02123ab00be8b8fe212c5d34ed021f1b63de74 (patch) | |
| tree | a16534cafb01cf7e7dc12713815a2bc7188834b1 | |
| parent | 695f7f3e2613d96a597e15a8c6142019098745c8 (diff) | |
Add double type and fix exception types
| -rw-r--r-- | main/core/parser/ast/AdditionNode.java | 9 | ||||
| -rw-r--r-- | main/core/parser/ast/NegationNode.java | 2 | ||||
| -rw-r--r-- | main/core/parser/ast/SubtractionNode.java | 9 | ||||
| -rw-r--r-- | main/core/parser/ast/SymbolNode.java | 12 | ||||
| -rw-r--r-- | main/core/parser/datatype/BooleanDataContainer.java | 18 | ||||
| -rw-r--r-- | main/core/parser/datatype/DataContainer.java | 10 | ||||
| -rw-r--r-- | main/core/parser/datatype/DoubleDataContainer.java | 50 | ||||
| -rw-r--r-- | main/core/parser/datatype/IntegerDataContainer.java | 77 | ||||
| -rw-r--r-- | main/core/parser/datatype/StringDataContainer.java | 17 | ||||
| -rw-r--r-- | main/core/parser/datatype/VoidDataContainer.java | 17 | ||||
| -rw-r--r-- | main/core/runtime/Scope.java | 3 | ||||
| -rw-r--r-- | main/core/runtime/builtins/AsIntBuiltinFunction.java | 5 | ||||
| -rw-r--r-- | main/exception/InterpreterException.java | 16 | ||||
| -rw-r--r-- | test/MainTest.java | 22 | ||||
| -rw-r--r-- | test/resources/program.bork | 14 |
15 files changed, 244 insertions, 37 deletions
diff --git a/main/core/parser/ast/AdditionNode.java b/main/core/parser/ast/AdditionNode.java index 0820370..00db230 100644 --- a/main/core/parser/ast/AdditionNode.java +++ b/main/core/parser/ast/AdditionNode.java @@ -2,6 +2,7 @@ package com.jantuomi.interpreter.main.core.parser.ast; import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer; import com.jantuomi.interpreter.main.core.tokenizer.token.Token; +import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; import java.util.Arrays; @@ -22,7 +23,13 @@ public class AdditionNode extends BinaryOperatorNode { DataContainer operand2 = rhs.evaluate(); DataContainer result = operand1.add(operand2); - return result; + if (result != null) { + return result; + } else { + ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, source.getLine(), + operand1.getType().toString(), operand2.getType().toString()); + return null; + } } @Override diff --git a/main/core/parser/ast/NegationNode.java b/main/core/parser/ast/NegationNode.java index ec3be2a..1d381cb 100644 --- a/main/core/parser/ast/NegationNode.java +++ b/main/core/parser/ast/NegationNode.java @@ -27,7 +27,7 @@ public class NegationNode extends UnaryOperatorNode { ((IntegerDataContainer) d).getData() != 0 ); } - ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, -1, "not", d.toString()); + ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, source.getLine(), "not", d.toString()); return null; } diff --git a/main/core/parser/ast/SubtractionNode.java b/main/core/parser/ast/SubtractionNode.java index b234d0d..6b05073 100644 --- a/main/core/parser/ast/SubtractionNode.java +++ b/main/core/parser/ast/SubtractionNode.java @@ -2,6 +2,7 @@ package com.jantuomi.interpreter.main.core.parser.ast; import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer; import com.jantuomi.interpreter.main.core.tokenizer.token.Token; +import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; import java.util.Arrays; @@ -21,7 +22,13 @@ public class SubtractionNode extends BinaryOperatorNode { DataContainer operand2 = rhs.evaluate(); DataContainer result = operand1.subtract(operand2); - return result; + if (result != null) { + return result; + } else { + ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, source.getLine(), + operand1.getType().toString(), operand2.getType().toString()); + return null; + } } @Override diff --git a/main/core/parser/ast/SymbolNode.java b/main/core/parser/ast/SymbolNode.java index c44d41b..5a4346a 100644 --- a/main/core/parser/ast/SymbolNode.java +++ b/main/core/parser/ast/SymbolNode.java @@ -3,11 +3,14 @@ package com.jantuomi.interpreter.main.core.parser.ast; import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer; import com.jantuomi.interpreter.main.core.runtime.State; import com.jantuomi.interpreter.main.core.tokenizer.token.Token; +import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; +import com.sun.deploy.util.StringUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * Created by jan on 17.6.2016. @@ -46,7 +49,14 @@ public class SymbolNode extends ASTNode { paramValues.add(param.evaluate()); } } - return State.getInstance().getSymbolValue(name, paramValues); + DataContainer returnValue = State.getInstance().getSymbolValue(name, paramValues); + if (returnValue != null) { + return returnValue; + } else { + ExceptionManager.raise(InterpreterException.ExceptionType.UndeclaredSymbolError, source.getLine(), name, + StringUtils.join(paramValues.stream().map(dataContainer -> dataContainer.toString()).collect(Collectors.toList()), ",")); + return null; + } } @Override diff --git a/main/core/parser/datatype/BooleanDataContainer.java b/main/core/parser/datatype/BooleanDataContainer.java index af814bb..e21ed96 100644 --- a/main/core/parser/datatype/BooleanDataContainer.java +++ b/main/core/parser/datatype/BooleanDataContainer.java @@ -1,6 +1,5 @@ package com.jantuomi.interpreter.main.core.parser.datatype; -import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; /** @@ -14,19 +13,32 @@ public class BooleanDataContainer extends DataContainer<Boolean> { } @Override + public Type getType() { + return Type.Boolean; + } + + @Override public String toString() { return Boolean.toString(getData()); } @Override public DataContainer<Boolean> add(DataContainer<Boolean> other) throws InterpreterException { - ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, -1, "boolean", "boolean"); return null; } @Override public DataContainer<Boolean> subtract(DataContainer<Boolean> other) throws InterpreterException { - ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, -1, "boolean", "boolean"); + return null; + } + + @Override + public DataContainer<Boolean> multiply(DataContainer<Boolean> other) throws InterpreterException { + return null; + } + + @Override + public DataContainer<Boolean> divide(DataContainer<Boolean> other) throws InterpreterException { return null; } } diff --git a/main/core/parser/datatype/DataContainer.java b/main/core/parser/datatype/DataContainer.java index 2214d80..5f46640 100644 --- a/main/core/parser/datatype/DataContainer.java +++ b/main/core/parser/datatype/DataContainer.java @@ -8,10 +8,14 @@ import com.jantuomi.interpreter.main.exception.InterpreterException; abstract public class DataContainer<T> { public enum Type { - Integer + Integer, + Double, + String, + Boolean, + Void } - private Type type; + abstract public Type getType(); private T data; @@ -28,4 +32,6 @@ abstract public class DataContainer<T> { abstract public DataContainer<T> add(DataContainer<T> other) throws InterpreterException; public abstract DataContainer<T> subtract(DataContainer<T> other) throws InterpreterException; + public abstract DataContainer<T> multiply(DataContainer<T> other) throws InterpreterException; + public abstract DataContainer<T> divide(DataContainer<T> other) throws InterpreterException; } diff --git a/main/core/parser/datatype/DoubleDataContainer.java b/main/core/parser/datatype/DoubleDataContainer.java new file mode 100644 index 0000000..76849c2 --- /dev/null +++ b/main/core/parser/datatype/DoubleDataContainer.java @@ -0,0 +1,50 @@ +package com.jantuomi.interpreter.main.core.parser.datatype; + +import com.jantuomi.interpreter.main.exception.InterpreterException; + +/** + * Created by jan on 22.6.2016. + */ +public class DoubleDataContainer extends DataContainer<Double> { + public DoubleDataContainer(double value) { + setData(value); + } + + @Override + public Type getType() { + return Type.Double; + } + + @Override + public String toString() { + return getData().toString(); + } + + @Override + public DataContainer<Double> add(DataContainer<Double> other) throws InterpreterException { + return new DoubleDataContainer( + getData() + other.getData() + ); + } + + @Override + public DataContainer<Double> subtract(DataContainer<Double> other) throws InterpreterException { + return new DoubleDataContainer( + getData() - other.getData() + ); + } + + @Override + public DataContainer<Double> multiply(DataContainer<Double> other) throws InterpreterException { + return new DoubleDataContainer( + getData() * other.getData() + ); + } + + @Override + public DataContainer<Double> divide(DataContainer<Double> other) throws InterpreterException { + return new DoubleDataContainer( + getData() / other.getData() + ); + } +} diff --git a/main/core/parser/datatype/IntegerDataContainer.java b/main/core/parser/datatype/IntegerDataContainer.java index 1999131..4f71e2b 100644 --- a/main/core/parser/datatype/IntegerDataContainer.java +++ b/main/core/parser/datatype/IntegerDataContainer.java @@ -1,5 +1,7 @@ package com.jantuomi.interpreter.main.core.parser.datatype; +import com.jantuomi.interpreter.main.exception.InterpreterException; + /** * Created by jan on 16.6.2016. */ @@ -10,21 +12,80 @@ public class IntegerDataContainer extends DataContainer<Integer> { } @Override + public Type getType() { + return Type.Integer; + } + + @Override public String toString() { return Integer.toString(getData()); } @Override - public DataContainer<Integer> add(DataContainer<Integer> other) { - return new IntegerDataContainer( - this.getData() + other.getData() - ); + public DataContainer add(DataContainer other) { + switch (other.getType()) { + case Integer: + return new IntegerDataContainer( + this.getData() + ((IntegerDataContainer) other).getData() + ); + case Double: + return new DoubleDataContainer( + (double) getData() + ((DoubleDataContainer) other).getData() + ); + default: + return null; + + } + } + + @Override + public DataContainer subtract(DataContainer other) { + switch (other.getType()) { + case Integer: + return new IntegerDataContainer( + this.getData() - ((IntegerDataContainer) other).getData() + ); + case Double: + return new DoubleDataContainer( + (double) getData() - ((DoubleDataContainer) other).getData() + ); + default: + return null; + + } } @Override - public DataContainer<Integer> subtract(DataContainer<Integer> other) { - return new IntegerDataContainer( - this.getData() - other.getData() - ); + public DataContainer multiply(DataContainer other) throws InterpreterException { + switch (other.getType()) { + case Integer: + return new IntegerDataContainer( + this.getData() * ((IntegerDataContainer) other).getData() + ); + case Double: + return new DoubleDataContainer( + (double) getData() * ((DoubleDataContainer) other).getData() + ); + default: + return null; + + } + } + + @Override + public DataContainer divide(DataContainer other) throws InterpreterException { + switch (other.getType()) { + case Integer: + return new IntegerDataContainer( + this.getData() / ((IntegerDataContainer) other).getData() + ); + case Double: + return new DoubleDataContainer( + (double) getData() / ((DoubleDataContainer) other).getData() + ); + default: + return null; + + } } } diff --git a/main/core/parser/datatype/StringDataContainer.java b/main/core/parser/datatype/StringDataContainer.java index bbc9b29..68f41d9 100644 --- a/main/core/parser/datatype/StringDataContainer.java +++ b/main/core/parser/datatype/StringDataContainer.java @@ -1,6 +1,5 @@ package com.jantuomi.interpreter.main.core.parser.datatype; -import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; /** @@ -14,6 +13,11 @@ public class StringDataContainer extends DataContainer<String> { } @Override + public Type getType() { + return Type.String; + } + + @Override public String toString() { return getData(); } @@ -27,7 +31,16 @@ public class StringDataContainer extends DataContainer<String> { @Override public DataContainer<String> subtract(DataContainer<String> other) throws InterpreterException { - ExceptionManager.raise(InterpreterException.ExceptionType.TypeError, -1, "string", "string"); + return null; + } + + @Override + public DataContainer<String> multiply(DataContainer<String> other) throws InterpreterException { + return null; + } + + @Override + public DataContainer<String> divide(DataContainer<String> other) throws InterpreterException { return null; } } diff --git a/main/core/parser/datatype/VoidDataContainer.java b/main/core/parser/datatype/VoidDataContainer.java index 8e078d9..098de8d 100644 --- a/main/core/parser/datatype/VoidDataContainer.java +++ b/main/core/parser/datatype/VoidDataContainer.java @@ -1,11 +1,18 @@ package com.jantuomi.interpreter.main.core.parser.datatype; +import com.jantuomi.interpreter.main.exception.InterpreterException; + /** * Created by jan on 17.6.2016. */ public class VoidDataContainer extends DataContainer<Integer> { @Override + public Type getType() { + return Type.Void; + } + + @Override public String toString() { return ""; } @@ -19,4 +26,14 @@ public class VoidDataContainer extends DataContainer<Integer> { public DataContainer<Integer> subtract(DataContainer<Integer> other) { return null; } + + @Override + public DataContainer<Integer> multiply(DataContainer<Integer> other) throws InterpreterException { + return null; + } + + @Override + public DataContainer<Integer> divide(DataContainer<Integer> other) throws InterpreterException { + return null; + } } diff --git a/main/core/runtime/Scope.java b/main/core/runtime/Scope.java index e3bf899..0bf8907 100644 --- a/main/core/runtime/Scope.java +++ b/main/core/runtime/Scope.java @@ -26,7 +26,8 @@ public class Scope { public DataContainer resolveSymbol(String symbol, List<DataContainer> params) throws InterpreterException { if (functions.containsKey(symbol)) { - return functions.get(symbol).evaluate(params); + DataContainer r = functions.get(symbol).evaluate(params); + return r; } if (variables.containsKey(symbol)) { return variables.get(symbol); diff --git a/main/core/runtime/builtins/AsIntBuiltinFunction.java b/main/core/runtime/builtins/AsIntBuiltinFunction.java index 3e1c71c..210e1e4 100644 --- a/main/core/runtime/builtins/AsIntBuiltinFunction.java +++ b/main/core/runtime/builtins/AsIntBuiltinFunction.java @@ -5,7 +5,6 @@ import com.jantuomi.interpreter.main.core.parser.datatype.DataContainer; import com.jantuomi.interpreter.main.core.parser.datatype.IntegerDataContainer; import com.jantuomi.interpreter.main.core.parser.datatype.StringDataContainer; import com.jantuomi.interpreter.main.core.runtime.Function; -import com.jantuomi.interpreter.main.exception.ExceptionManager; import com.jantuomi.interpreter.main.exception.InterpreterException; import java.util.Arrays; @@ -30,7 +29,7 @@ public class AsIntBuiltinFunction extends Function { @Override public DataContainer evaluate(List<DataContainer> params) throws InterpreterException { if (params.size() != 1) { - ExceptionManager.raise(InterpreterException.ExceptionType.SyntaxError, -1, "amount of parameters to as_int"); + return null; } DataContainer param = params.get(0); int i = 0; @@ -39,8 +38,6 @@ public class AsIntBuiltinFunction extends Function { i = Integer.parseInt(((StringDataContainer) param).getData()); } catch (NumberFormatException ex) { - ExceptionManager.raise(InterpreterException.ExceptionType.SyntaxError, -1, - String.format("parameter %s to as_int", param.toString())); return null; } } diff --git a/main/exception/InterpreterException.java b/main/exception/InterpreterException.java index 8421edc..ac021c0 100644 --- a/main/exception/InterpreterException.java +++ b/main/exception/InterpreterException.java @@ -21,19 +21,20 @@ public class InterpreterException extends Exception { public static Map<ExceptionType, String> errorTexts = new HashMap<>(); static { - errorTexts.put(ExceptionType.IllegalTokenError, "Illegal token %s found."); - errorTexts.put(ExceptionType.UnknownOperatorError, "Unexpected operator %s found."); + errorTexts.put(ExceptionType.IllegalTokenError, "Unknown or illegal token %s found."); errorTexts.put(ExceptionType.SyntaxError, "Unexpected %s."); errorTexts.put(ExceptionType.TypeError, "Incompatible types %s and %s."); - errorTexts.put(ExceptionType.ArgumentError, "Function %s requires %s arguments."); - errorTexts.put(ExceptionType.UndeclaredSymbolError, "No symbol %s defined."); + errorTexts.put(ExceptionType.ArgumentError, "The parameter list given to function %s is either of wrong length or the parameters are of wrong type. Actual: %s"); + errorTexts.put(ExceptionType.UndeclaredSymbolError, "No symbol %s defined, parameters: [%s]."); } private ExceptionType exceptionType; + private String completeMessage; public InterpreterException(ExceptionType exceptionType, int line, String... args) { - super(formatMessage(exceptionType.toString() + ": " + what(exceptionType), line, args), null, false, false); + super(exceptionType.toString(), null, false, false); this.exceptionType = exceptionType; + this.completeMessage = formatMessage(exceptionType.toString() + ": " + what(exceptionType), line, args); } private static String formatMessage(String message, int line, String... args) { @@ -45,4 +46,9 @@ public class InterpreterException extends Exception { public static String what(ExceptionType type) { return errorTexts.get(type); } + + @Override + public void printStackTrace() { + System.err.println(completeMessage); + } } diff --git a/test/MainTest.java b/test/MainTest.java index 1730a6b..f90e367 100644 --- a/test/MainTest.java +++ b/test/MainTest.java @@ -2,8 +2,13 @@ package com.jantuomi.interpreter.test; import com.jantuomi.interpreter.main.Main; import com.jantuomi.interpreter.main.exception.InterpreterException; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -11,6 +16,21 @@ import static org.junit.Assert.assertTrue; * Created by jan on 10.6.2016. */ public class MainTest { + + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + private PrintStream originalOut; + + @Before + public void setupStreams() { + originalOut = System.out; + System.setOut(new PrintStream(out)); + } + + @After + public void cleanStreams() { + System.setOut(originalOut); + } + @Test public void testParseArguments1() { String[] notAnArgument = {"--not-an-argument"}; @@ -26,6 +46,8 @@ public class MainTest { @Test public void testWholeProcedure() throws InterpreterException { String input = "- + 2 5 1"; + Main.run(input); + assertTrue(out.toString().contains("6")); } }
\ No newline at end of file diff --git a/test/resources/program.bork b/test/resources/program.bork index 52cee38..7034625 100644 --- a/test/resources/program.bork +++ b/test/resources/program.bork @@ -1,15 +1,13 @@ /* get an integer from the user */ -decl user_input -set user_input in("give integer: ") -out( concat("your input was: " user_input "!") ) - -/* add 10 to the integer */ -decl operand set operand 10 +decl lhs decl rhs +set lhs in("give an integer: ") +set rhs in("give another: ") +/* add the inputs together */ decl sum -set sum + as_int(user_input) operand +set sum + as_int(lhs) as_int(rhs) /* print the sum */ -out( concat(user_input " + " operand " = " sum) ) +out( concat(lhs " + " rhs " = " sum) ) "done"
\ No newline at end of file |
