From 5b690c7cf7d024b855b9c75d9c53603b3ba46970 Mon Sep 17 00:00:00 2001 From: jantuomi Date: Thu, 4 Aug 2016 12:45:51 +0300 Subject: Add ObjectDatatype and implement object member lookup Various error fixes Resolves #14 --- .../tunkki/core/parser/ast/ObjectMemberNode.java | 38 +++++++++++++++- .../tunkki/core/parser/datatype/Datatype.java | 3 +- .../core/parser/datatype/ObjectDatatype.java | 53 ++++++++++++++++++++++ .../jantuomi/tunkki/core/runtime/Interpreter.java | 10 ++-- .../com/jantuomi/tunkki/core/runtime/Scope.java | 15 ++++-- .../builtins/globals/IncludeBuiltinFunction.java | 6 ++- .../exception/types/NotAnObjectTunkkiError.java | 20 ++++++++ .../tunkki/exception/types/TunkkiError.java | 2 +- 8 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 src/main/com/jantuomi/tunkki/core/parser/datatype/ObjectDatatype.java create mode 100644 src/main/com/jantuomi/tunkki/exception/types/NotAnObjectTunkkiError.java (limited to 'src/main/com') diff --git a/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java index deed962..51e53fa 100644 --- a/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java +++ b/src/main/com/jantuomi/tunkki/core/parser/ast/ObjectMemberNode.java @@ -1,8 +1,14 @@ package com.jantuomi.tunkki.core.parser.ast; import com.jantuomi.tunkki.core.parser.datatype.Datatype; +import com.jantuomi.tunkki.core.parser.datatype.ObjectDatatype; import com.jantuomi.tunkki.core.parser.tokenizer.token.Token; +import com.jantuomi.tunkki.core.runtime.State; +import com.jantuomi.tunkki.exception.types.NotAnObjectTunkkiError; import com.jantuomi.tunkki.exception.types.TunkkiError; +import com.jantuomi.tunkki.exception.types.UndeclaredSymbolTunkkiError; + +import java.util.Collections; /** * Created by jan on 3.8.2016. @@ -14,7 +20,35 @@ public class ObjectMemberNode extends UnaryOperatorNode { @Override public Datatype evaluate() throws TunkkiError { - // TODO - return null; + Datatype d; + try { + d = State.getInstance().evaluateSymbol(getText()); + } catch (TunkkiError ex) { + ex.setLine(getLine()); + throw ex; + } + + if (d.getType() != Datatype.Type.Object) { + throw new NotAnObjectTunkkiError(getLine(), getText()); + } + + ObjectDatatype od = (ObjectDatatype) d; + ASTNode member = getOperand(); + if (member instanceof CallNode) { + CallNode cn = (CallNode) member; + Datatype res = od.getData().resolveSymbol(cn.getName(), cn.evaluateParameters()); + if (res != null) { + return res; + } + } + else if (member instanceof SymbolNode) { + SymbolNode sn = (SymbolNode) member; + Datatype res = od.getData().resolveSymbol(sn.getName(), Collections.emptyList()); + if (res != null) { + return res; + } + } + + throw new UndeclaredSymbolTunkkiError(getLine(), member.getText()); } } diff --git a/src/main/com/jantuomi/tunkki/core/parser/datatype/Datatype.java b/src/main/com/jantuomi/tunkki/core/parser/datatype/Datatype.java index f2648c3..928f74b 100644 --- a/src/main/com/jantuomi/tunkki/core/parser/datatype/Datatype.java +++ b/src/main/com/jantuomi/tunkki/core/parser/datatype/Datatype.java @@ -18,7 +18,8 @@ abstract public class Datatype { Boolean, Nada, Void, - Callable + Callable, + Object } abstract public Type getType(); diff --git a/src/main/com/jantuomi/tunkki/core/parser/datatype/ObjectDatatype.java b/src/main/com/jantuomi/tunkki/core/parser/datatype/ObjectDatatype.java new file mode 100644 index 0000000..39f1d3d --- /dev/null +++ b/src/main/com/jantuomi/tunkki/core/parser/datatype/ObjectDatatype.java @@ -0,0 +1,53 @@ +package com.jantuomi.tunkki.core.parser.datatype; + +import com.jantuomi.tunkki.core.runtime.Scope; +import com.jantuomi.tunkki.exception.types.TunkkiError; + +/** + * Created by jan on 4.8.2016. + */ +public class ObjectDatatype extends Datatype { + public ObjectDatatype() { + setData(new Scope()); + } + + @Override + public Type getType() { + return Type.Object; + } + + @Override + public String toString() { + String sb = "Object ["; + sb += String.join(", ", getData().getVariableNames()); + sb += String.join(", ", getData().getFunctionNames()); + sb += "]"; + return sb; + } + + @Override + public Datatype add(Datatype other) throws TunkkiError { + return null; + } + + @Override + public Datatype subtract(Datatype other) throws TunkkiError { + return null; + } + + @Override + public Datatype multiply(Datatype other) throws TunkkiError { + return null; + } + + @Override + public Datatype divide(Datatype other) throws TunkkiError { + return null; + } + + @Override + public BooleanDatatype equals(Datatype other) throws TunkkiError { + // TODO + return new BooleanDatatype(false); + } +} diff --git a/src/main/com/jantuomi/tunkki/core/runtime/Interpreter.java b/src/main/com/jantuomi/tunkki/core/runtime/Interpreter.java index e9ee999..c6462ed 100644 --- a/src/main/com/jantuomi/tunkki/core/runtime/Interpreter.java +++ b/src/main/com/jantuomi/tunkki/core/runtime/Interpreter.java @@ -2,6 +2,7 @@ package com.jantuomi.tunkki.core.runtime; import com.jantuomi.tunkki.core.parser.ast.ASTNode; import com.jantuomi.tunkki.core.parser.datatype.Datatype; +import com.jantuomi.tunkki.exception.types.SyntaxTunkkiError; import com.jantuomi.tunkki.exception.types.TunkkiError; import java.util.List; @@ -23,13 +24,12 @@ public class Interpreter { String output = ""; Datatype data; for (ASTNode node : sequence) { - try { - data = node.evaluate(); - } - catch (NullPointerException ex) { - continue; + if (node == null) { + throw new SyntaxTunkkiError(-1, "null node"); } + data = node.evaluate(); + if (data != null) { output = data.toString(); } else { diff --git a/src/main/com/jantuomi/tunkki/core/runtime/Scope.java b/src/main/com/jantuomi/tunkki/core/runtime/Scope.java index 4bdd71b..712c97a 100644 --- a/src/main/com/jantuomi/tunkki/core/runtime/Scope.java +++ b/src/main/com/jantuomi/tunkki/core/runtime/Scope.java @@ -3,10 +3,12 @@ package com.jantuomi.tunkki.core.runtime; import com.jantuomi.tunkki.core.parser.datatype.CallableDatatype; import com.jantuomi.tunkki.core.parser.datatype.Datatype; import com.jantuomi.tunkki.exception.types.TunkkiError; +import com.jantuomi.tunkki.exception.types.UndeclaredSymbolTunkkiError; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * Created by jan on 20.6.2016. @@ -17,6 +19,14 @@ public class Scope { private Map variables = new HashMap<>(); private Map functions = new HashMap<>(); + public Set getVariableNames() { + return variables.keySet(); + } + + public Set getFunctionNames() { + return functions.keySet(); + } + public void addVariable(String symbol) { variables.put(symbol, null); } @@ -27,8 +37,7 @@ public class Scope { public Datatype resolveSymbol(String symbol, List params) throws TunkkiError { if (functions.containsKey(symbol)) { - Datatype r = functions.get(symbol).evaluate(params); - return r; + return functions.get(symbol).evaluate(params); } if (variables.containsKey(symbol)) { return variables.get(symbol); @@ -37,7 +46,7 @@ public class Scope { return parent.resolveSymbol(symbol, params); } else { - return null; + throw new UndeclaredSymbolTunkkiError(-1, symbol); } } diff --git a/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java b/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java index 519163c..ea4f7a6 100644 --- a/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java +++ b/src/main/com/jantuomi/tunkki/core/runtime/builtins/globals/IncludeBuiltinFunction.java @@ -4,6 +4,7 @@ package com.jantuomi.tunkki.core.runtime.builtins.globals; import com.jantuomi.tunkki.Tunkki; import com.jantuomi.tunkki.core.CommandLineArgumentContainer; import com.jantuomi.tunkki.core.parser.datatype.Datatype; +import com.jantuomi.tunkki.core.parser.datatype.ObjectDatatype; import com.jantuomi.tunkki.core.parser.datatype.StringDatatype; import com.jantuomi.tunkki.core.parser.datatype.VoidDatatype; import com.jantuomi.tunkki.core.runtime.State; @@ -40,8 +41,11 @@ public class IncludeBuiltinFunction extends BuiltinFunction { if (BuiltinManager.getInstance().BUILTIN_MODULES.contains(filename)) { + ObjectDatatype namespace = new ObjectDatatype(); BuiltinManager.getInstance().getFunctionsFromModule(filename) - .forEach( f -> State.getInstance().addFunctionToScope(f.getName(), f) ); + .forEach( f -> namespace.getData().addFunction(f.getName(), f) ); + State.getInstance().addSymbolToScope(filename); + State.getInstance().setSymbolValueToScope(filename, namespace); } else { diff --git a/src/main/com/jantuomi/tunkki/exception/types/NotAnObjectTunkkiError.java b/src/main/com/jantuomi/tunkki/exception/types/NotAnObjectTunkkiError.java new file mode 100644 index 0000000..c8c242f --- /dev/null +++ b/src/main/com/jantuomi/tunkki/exception/types/NotAnObjectTunkkiError.java @@ -0,0 +1,20 @@ +package com.jantuomi.tunkki.exception.types; + +/** + * Created by jan on 4.8.2016. + */ +public class NotAnObjectTunkkiError extends TunkkiError { + public NotAnObjectTunkkiError(int line, String... args) { + super(line, args); + } + + @Override + public String what() { + return "Symbol %s is not an object."; + } + + @Override + ExceptionType getType() { + return ExceptionType.NotAnObjectError; + } +} diff --git a/src/main/com/jantuomi/tunkki/exception/types/TunkkiError.java b/src/main/com/jantuomi/tunkki/exception/types/TunkkiError.java index c99e8f9..023c8a5 100644 --- a/src/main/com/jantuomi/tunkki/exception/types/TunkkiError.java +++ b/src/main/com/jantuomi/tunkki/exception/types/TunkkiError.java @@ -23,7 +23,7 @@ abstract public class TunkkiError extends Exception { CastError, DivisionByZeroError, RecursiveIncludeError, - OutOfBoundsError, FileNotFoundError, NadaError + OutOfBoundsError, FileNotFoundError, NotAnObjectError, NadaError } private int line; -- cgit v1.3