diff --git a/src/com/annimon/ownlang/Console.java b/src/com/annimon/ownlang/Console.java new file mode 100644 index 0000000..06217d6 --- /dev/null +++ b/src/com/annimon/ownlang/Console.java @@ -0,0 +1,56 @@ +package com.annimon.ownlang; + +import com.annimon.ownlang.lib.CallStack; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + +public class Console { + + public static void print(String value) { + System.out.print(value); + } + + public static void print(Object value) { + print(value.toString()); + } + + public static void println() { + System.out.println(); + } + + public static void println(String value) { + System.out.println(value); + } + + public static void println(Object value) { + println(value.toString()); + } + + public static void error(Throwable throwable) { + error(throwable.toString()); + } + + public static void error(CharSequence value) { + System.err.println(value); + } + + public static void handleException(Thread thread, Throwable throwable) { + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try(final PrintStream ps = new PrintStream(baos)) { + ps.printf("%s in %s\n", throwable.getMessage(), thread.getName()); + for (CallStack.CallInfo call : CallStack.getCalls()) { + ps.printf("\tat %s\n", call); + } + ps.println(); + throwable.printStackTrace(ps); + ps.flush(); + } + try { + error(baos.toString("UTF-8")); + } catch (UnsupportedEncodingException ex) { + error(baos.toString()); + } + } +} diff --git a/src/com/annimon/ownlang/Main.java b/src/com/annimon/ownlang/Main.java index ae1fd81..b24e929 100644 --- a/src/com/annimon/ownlang/Main.java +++ b/src/com/annimon/ownlang/Main.java @@ -1,6 +1,5 @@ package com.annimon.ownlang; -import com.annimon.ownlang.lib.CallStack; import com.annimon.ownlang.parser.Lexer; import com.annimon.ownlang.parser.Parser; import com.annimon.ownlang.parser.SourceLoader; @@ -90,7 +89,7 @@ public final class Main { measurement.start("Execution time"); program.execute(); } catch (Exception ex) { - handleException(Thread.currentThread(), ex); + Console.handleException(Thread.currentThread(), ex); } finally { if (showMeasurements) { measurement.stop("Execution time"); @@ -99,12 +98,4 @@ public final class Main { } } } - - public static void handleException(Thread thread, Throwable throwable) { - System.err.printf("%s in %s\n", throwable.getMessage(), thread.getName()); - for (CallStack.CallInfo call : CallStack.getCalls()) { - System.err.printf("\tat %s\n", call); - } - throwable.printStackTrace(); - } } diff --git a/src/com/annimon/ownlang/lib/CallStack.java b/src/com/annimon/ownlang/lib/CallStack.java index cad247c..e5b753b 100644 --- a/src/com/annimon/ownlang/lib/CallStack.java +++ b/src/com/annimon/ownlang/lib/CallStack.java @@ -7,6 +7,10 @@ public final class CallStack { private static final Deque calls = new ConcurrentLinkedDeque();; + public static synchronized void clear() { + calls.clear(); + } + public static synchronized void enter(String name, Function function) { calls.push(new CallInfo(name, function)); } diff --git a/src/com/annimon/ownlang/lib/Variables.java b/src/com/annimon/ownlang/lib/Variables.java index e11d3ff..6671cec 100644 --- a/src/com/annimon/ownlang/lib/Variables.java +++ b/src/com/annimon/ownlang/lib/Variables.java @@ -16,6 +16,12 @@ public final class Variables { static { stack = new Stack<>(); variables = new ConcurrentHashMap<>(); + Variables.clear(); + } + + public static void clear() { + stack.clear(); + variables.clear(); variables.put("true", NumberValue.ONE); variables.put("false", NumberValue.ZERO); } diff --git a/src/com/annimon/ownlang/lib/modules/functions/std_echo.java b/src/com/annimon/ownlang/lib/modules/functions/std_echo.java index 4aa15ba..6ec9eb5 100644 --- a/src/com/annimon/ownlang/lib/modules/functions/std_echo.java +++ b/src/com/annimon/ownlang/lib/modules/functions/std_echo.java @@ -1,5 +1,6 @@ package com.annimon.ownlang.lib.modules.functions; +import com.annimon.ownlang.Console; import com.annimon.ownlang.lib.Function; import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.Value; @@ -9,10 +10,10 @@ public final class std_echo implements Function { @Override public Value execute(Value... args) { for (Value arg : args) { - System.out.print(arg.asString()); - System.out.print(" "); + Console.print(arg.asString()); + Console.print(" "); } - System.out.println(); + Console.println(); return NumberValue.ZERO; } } \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/functions/std_thread.java b/src/com/annimon/ownlang/lib/modules/functions/std_thread.java index 75a50fe..e789a67 100644 --- a/src/com/annimon/ownlang/lib/modules/functions/std_thread.java +++ b/src/com/annimon/ownlang/lib/modules/functions/std_thread.java @@ -1,6 +1,6 @@ package com.annimon.ownlang.lib.modules.functions; -import com.annimon.ownlang.Main; +import com.annimon.ownlang.Console; import com.annimon.ownlang.exceptions.ArgumentsMismatchException; import com.annimon.ownlang.lib.*; @@ -26,7 +26,7 @@ public final class std_thread implements Function { } final Thread thread = new Thread(() -> body.execute(params)); - thread.setUncaughtExceptionHandler(Main::handleException); + thread.setUncaughtExceptionHandler(Console::handleException); thread.start(); return NumberValue.ZERO; } diff --git a/src/com/annimon/ownlang/parser/Parser.java b/src/com/annimon/ownlang/parser/Parser.java index 5bc70f3..f0d0627 100644 --- a/src/com/annimon/ownlang/parser/Parser.java +++ b/src/com/annimon/ownlang/parser/Parser.java @@ -48,6 +48,7 @@ public final class Parser { private final List tokens; private final int size; private final ParseErrors parseErrors; + private Statement parsedStatement; private int pos; @@ -57,6 +58,10 @@ public final class Parser { parseErrors = new ParseErrors(); } + public Statement getParsedStatement() { + return parsedStatement; + } + public ParseErrors getParseErrors() { return parseErrors; } @@ -72,6 +77,7 @@ public final class Parser { recover(); } } + parsedStatement = result; return result; } diff --git a/src/com/annimon/ownlang/parser/ast/PrintStatement.java b/src/com/annimon/ownlang/parser/ast/PrintStatement.java index e008879..8b175d6 100644 --- a/src/com/annimon/ownlang/parser/ast/PrintStatement.java +++ b/src/com/annimon/ownlang/parser/ast/PrintStatement.java @@ -1,5 +1,7 @@ package com.annimon.ownlang.parser.ast; +import com.annimon.ownlang.Console; + /** * * @author aNNiMON @@ -14,7 +16,7 @@ public final class PrintStatement implements Statement { @Override public void execute() { - System.out.print(expression.eval()); + Console.print(expression.eval()); } @Override diff --git a/src/com/annimon/ownlang/parser/ast/PrintlnStatement.java b/src/com/annimon/ownlang/parser/ast/PrintlnStatement.java index ced55fd..6f7823e 100644 --- a/src/com/annimon/ownlang/parser/ast/PrintlnStatement.java +++ b/src/com/annimon/ownlang/parser/ast/PrintlnStatement.java @@ -1,5 +1,7 @@ package com.annimon.ownlang.parser.ast; +import com.annimon.ownlang.Console; + /** * * @author aNNiMON @@ -14,7 +16,7 @@ public final class PrintlnStatement implements Statement { @Override public void execute() { - System.out.println(expression.eval()); + Console.println(expression.eval()); } @Override diff --git a/src/com/annimon/ownlang/parser/visitors/VariablePrinter.java b/src/com/annimon/ownlang/parser/visitors/VariablePrinter.java index 82a6052..4f29f3a 100644 --- a/src/com/annimon/ownlang/parser/visitors/VariablePrinter.java +++ b/src/com/annimon/ownlang/parser/visitors/VariablePrinter.java @@ -1,5 +1,6 @@ package com.annimon.ownlang.parser.visitors; +import com.annimon.ownlang.Console; import com.annimon.ownlang.parser.ast.*; /** @@ -11,18 +12,18 @@ public final class VariablePrinter extends AbstractVisitor { @Override public void visit(AssignmentExpression s) { super.visit(s); - System.out.println(s.target); + Console.println(s.target); } @Override public void visit(ContainerAccessExpression s) { super.visit(s); - System.out.println(s.variable); + Console.println(s.variable); } @Override public void visit(VariableExpression s) { super.visit(s); - System.out.println(s.name); + Console.println(s.name); } }