diff options
Diffstat (limited to '')
| -rw-r--r-- | ast/src/main/java/lv/enes/orang/ast/BinaryExpression.java (renamed from src/main/java/lv/enes/orang/ast/BinaryExpression.java) | 21 | ||||
| -rw-r--r-- | ast/src/main/java/lv/enes/orang/ast/DefSpec.java (renamed from src/main/java/lv/enes/orang/ast/DefSpec.java) | 0 | ||||
| -rw-r--r-- | core/src/main/java/lv/enes/orang/core/OrangException.java (renamed from src/main/java/lv/enes/orang/OrangException.java) | 2 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Builtins.java (renamed from src/main/java/lv/enes/orang/Builtins.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Codepoint.java (renamed from src/main/java/lv/enes/orang/Codepoint.java) | 4 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Lexer.java (renamed from src/main/java/lv/enes/orang/Lexer.java) | 8 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Main.java (renamed from src/main/java/lv/enes/orang/Main.java) | 14 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/OrangRuntimeException.java (renamed from src/main/java/lv/enes/orang/OrangRuntimeException.java) | 2 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Parser.java (renamed from src/main/java/lv/enes/orang/Parser.java) | 3 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/ParserException.java (renamed from src/main/java/lv/enes/orang/ParserException.java) | 2 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/PeekableStream.java (renamed from src/main/java/lv/enes/orang/PeekableStream.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/State.java (renamed from src/main/java/lv/enes/orang/State.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/Token.java (renamed from src/main/java/lv/enes/orang/Token.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/TokenType.java (renamed from src/main/java/lv/enes/orang/TokenType.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/Array.java (renamed from src/main/java/lv/enes/orang/value/Array.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/BuiltinFunction.java (renamed from src/main/java/lv/enes/orang/value/BuiltinFunction.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/Function.java (renamed from src/main/java/lv/enes/orang/value/Function.java) | 5 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/OrangBoolean.java (renamed from src/main/java/lv/enes/orang/value/OrangBoolean.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/OrangInteger.java (renamed from src/main/java/lv/enes/orang/value/OrangInteger.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/OrangString.java (renamed from src/main/java/lv/enes/orang/value/OrangString.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java (renamed from src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/PartialFunction.java (renamed from src/main/java/lv/enes/orang/value/PartialFunction.java) | 5 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/Undefined.java (renamed from src/main/java/lv/enes/orang/value/Undefined.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/lv/enes/orang/value/Value.java (renamed from src/main/java/lv/enes/orang/value/Value.java) | 0 | ||||
| -rw-r--r-- | orang/src/main/java/module-info.java (renamed from src/main/java/module-info.java) | 5 | ||||
| -rw-r--r-- | orang/src/main/resources/lv/enes/orang/prelude.orang (renamed from src/main/resources/lv/enes/orang/prelude.orang) | 8 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/Scope.java | 54 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/ArrayExpression.java | 21 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/BooleanLiteral.java | 12 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/CallExpression.java | 12 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/Definition.java | 15 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/DoExpression.java | 19 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/Expression.java | 14 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/FnExpression.java | 14 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/IfElseExpression.java | 22 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/IntLiteral.java | 12 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/LetInExpression.java | 27 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/Program.java | 17 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/Statement.java | 8 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/StringLiteral.java | 13 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/UnaryExpression.java | 23 | ||||
| -rw-r--r-- | src/main/java/lv/enes/orang/ast/VariableExpression.java | 12 | ||||
| -rw-r--r-- | utils/src/main/java/lv/enes/orang/utils/NonEmptyList.java (renamed from src/main/java/lv/enes/orang/NonEmptyList.java) | 2 |
43 files changed, 49 insertions, 327 deletions
diff --git a/src/main/java/lv/enes/orang/ast/BinaryExpression.java b/ast/src/main/java/lv/enes/orang/ast/BinaryExpression.java index c0b988c..fb8bac5 100644 --- a/src/main/java/lv/enes/orang/ast/BinaryExpression.java +++ b/ast/src/main/java/lv/enes/orang/ast/BinaryExpression.java | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | package lv.enes.orang.ast; | 1 | package lv.enes.orang.ast; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.OrangRuntimeException; | 3 | import lv.enes.orang.core.OrangException; |
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | 4 | ||
| 7 | public record BinaryExpression(Operator operator, Expression lhs, Expression rhs) implements Expression { | 5 | public record BinaryExpression(Operator operator, Expression lhs, Expression rhs) implements Expression { |
| 8 | public enum Operator { | 6 | public enum Operator { |
| @@ -34,20 +32,7 @@ public record BinaryExpression(Operator operator, Expression lhs, Expression rhs | |||
| 34 | } | 32 | } |
| 35 | 33 | ||
| 36 | @Override | 34 | @Override |
| 37 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | 35 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { |
| 38 | var lhs = lhs().evaluateExpression(scope); | 36 | return visitor.visitBinaryExpression(this); |
| 39 | var rhs = rhs().evaluateExpression(scope); | ||
| 40 | return switch (operator) { | ||
| 41 | case EQUALS -> lhs.orangEquals(rhs); | ||
| 42 | case NOT_EQUALS -> lhs.notEquals(rhs); | ||
| 43 | case GT -> lhs.greaterThan(rhs); | ||
| 44 | case GTE -> lhs.greaterThanOrEqual(rhs); | ||
| 45 | case LT -> lhs.lessThan(rhs); | ||
| 46 | case LTE -> lhs.lessThanOrEqual(rhs); | ||
| 47 | case ADD -> lhs.add(rhs); | ||
| 48 | case SUBTRACT -> lhs.subtract(rhs); | ||
| 49 | case MULTIPLY -> lhs.multiply(rhs); | ||
| 50 | case DIVIDE -> lhs.divide(rhs); | ||
| 51 | }; | ||
| 52 | } | 37 | } |
| 53 | } | 38 | } |
diff --git a/src/main/java/lv/enes/orang/ast/DefSpec.java b/ast/src/main/java/lv/enes/orang/ast/DefSpec.java index 2233d3f..2233d3f 100644 --- a/src/main/java/lv/enes/orang/ast/DefSpec.java +++ b/ast/src/main/java/lv/enes/orang/ast/DefSpec.java | |||
diff --git a/src/main/java/lv/enes/orang/OrangException.java b/core/src/main/java/lv/enes/orang/core/OrangException.java index 9308643..d634fca 100644 --- a/src/main/java/lv/enes/orang/OrangException.java +++ b/core/src/main/java/lv/enes/orang/core/OrangException.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package lv.enes.orang; | 1 | package lv.enes.orang.core; |
| 2 | 2 | ||
| 3 | public abstract class OrangException extends Exception { | 3 | public abstract class OrangException extends Exception { |
| 4 | protected OrangException(String message) { | 4 | protected OrangException(String message) { |
diff --git a/src/main/java/lv/enes/orang/Builtins.java b/orang/src/main/java/lv/enes/orang/Builtins.java index 0a76387..0a76387 100644 --- a/src/main/java/lv/enes/orang/Builtins.java +++ b/orang/src/main/java/lv/enes/orang/Builtins.java | |||
diff --git a/src/main/java/lv/enes/orang/Codepoint.java b/orang/src/main/java/lv/enes/orang/Codepoint.java index 0dfaa2b..7157062 100644 --- a/src/main/java/lv/enes/orang/Codepoint.java +++ b/orang/src/main/java/lv/enes/orang/Codepoint.java | |||
| @@ -14,6 +14,10 @@ public record Codepoint(int cp) { | |||
| 14 | return isIdentInitial() || Character.isDigit(cp); | 14 | return isIdentInitial() || Character.isDigit(cp); |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | public boolean isNewline() { | ||
| 18 | return cp == '\n'; | ||
| 19 | } | ||
| 20 | |||
| 17 | public boolean isNumeral() { | 21 | public boolean isNumeral() { |
| 18 | return Character.isDigit(cp); | 22 | return Character.isDigit(cp); |
| 19 | } | 23 | } |
diff --git a/src/main/java/lv/enes/orang/Lexer.java b/orang/src/main/java/lv/enes/orang/Lexer.java index 0ee2503..d4e1533 100644 --- a/src/main/java/lv/enes/orang/Lexer.java +++ b/orang/src/main/java/lv/enes/orang/Lexer.java | |||
| @@ -163,6 +163,12 @@ public class Lexer implements Iterator<Token> { | |||
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | private void skipWhitespace() { | 165 | private void skipWhitespace() { |
| 166 | skipWhile(Codepoint::isWhitespace); | 166 | while (true) { |
| 167 | skipWhile(Codepoint::isWhitespace); | ||
| 168 | if (input.peek().cp() != '#') { | ||
| 169 | return; | ||
| 170 | } | ||
| 171 | skipWhile(cp -> !cp.isNewline()); | ||
| 172 | } | ||
| 167 | } | 173 | } |
| 168 | } | 174 | } |
diff --git a/src/main/java/lv/enes/orang/Main.java b/orang/src/main/java/lv/enes/orang/Main.java index 9a607ed..7ca14a1 100644 --- a/src/main/java/lv/enes/orang/Main.java +++ b/orang/src/main/java/lv/enes/orang/Main.java | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | package lv.enes.orang; | 1 | package lv.enes.orang; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 3 | import java.io.FileReader; | 5 | import java.io.FileReader; |
| 4 | import java.io.IOException; | 6 | import java.io.IOException; |
| 5 | 7 | ||
| @@ -14,11 +16,11 @@ public class Main { | |||
| 14 | } | 16 | } |
| 15 | 17 | ||
| 16 | private static void repl() throws IOException { | 18 | private static void repl() throws IOException { |
| 17 | var scope = new Scope(); | 19 | var evaluator = new Evaluator(); |
| 18 | 20 | ||
| 19 | try (var stream = Main.class.getResourceAsStream("prelude.orang")) { | 21 | try (var stream = Main.class.getResourceAsStream("prelude.orang")) { |
| 20 | var prog = Parser.parseProgram(stream); | 22 | var prog = Parser.parseProgram(stream); |
| 21 | scope = prog.runStatement(scope); | 23 | evaluator = evaluator.visitProgram(prog); |
| 22 | } catch (OrangException ex) { | 24 | } catch (OrangException ex) { |
| 23 | STDOUT.println(STR."While evaluating prelude: \{ex}"); | 25 | STDOUT.println(STR."While evaluating prelude: \{ex}"); |
| 24 | throw new RuntimeException(ex); | 26 | throw new RuntimeException(ex); |
| @@ -48,7 +50,7 @@ public class Main { | |||
| 48 | var filename = line.substring(2).trim(); | 50 | var filename = line.substring(2).trim(); |
| 49 | try (var reader = new FileReader((filename))) { | 51 | try (var reader = new FileReader((filename))) { |
| 50 | var prog = Parser.parseProgram(reader); | 52 | var prog = Parser.parseProgram(reader); |
| 51 | scope = prog.runStatement(scope); | 53 | evaluator = evaluator.visitProgram(prog); |
| 52 | } catch (IOException | OrangException ex) { | 54 | } catch (IOException | OrangException ex) { |
| 53 | STDOUT.println(ex); | 55 | STDOUT.println(ex); |
| 54 | } | 56 | } |
| @@ -64,10 +66,10 @@ public class Main { | |||
| 64 | 66 | ||
| 65 | try { | 67 | try { |
| 66 | var prog = Parser.parseProgram(line); | 68 | var prog = Parser.parseProgram(line); |
| 67 | scope = prog.runStatement(scope); | 69 | evaluator = evaluator.visitProgram(prog); |
| 68 | if (scope.getLastResult() != null) { | 70 | if (evaluator.lastResult() != null) { |
| 69 | STDOUT.print("-> "); | 71 | STDOUT.print("-> "); |
| 70 | STDOUT.println(scope.getLastResult().stringify()); | 72 | STDOUT.println(evaluator.lastResult().stringify()); |
| 71 | } | 73 | } |
| 72 | } catch (OrangException ex) { | 74 | } catch (OrangException ex) { |
| 73 | STDOUT.println(ex); | 75 | STDOUT.println(ex); |
diff --git a/src/main/java/lv/enes/orang/OrangRuntimeException.java b/orang/src/main/java/lv/enes/orang/OrangRuntimeException.java index 9648c30..8a7d575 100644 --- a/src/main/java/lv/enes/orang/OrangRuntimeException.java +++ b/orang/src/main/java/lv/enes/orang/OrangRuntimeException.java | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | package lv.enes.orang; | 1 | package lv.enes.orang; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 3 | public class OrangRuntimeException extends OrangException { | 5 | public class OrangRuntimeException extends OrangException { |
| 4 | public OrangRuntimeException(String message) { | 6 | public OrangRuntimeException(String message) { |
| 5 | super(message); | 7 | super(message); |
diff --git a/src/main/java/lv/enes/orang/Parser.java b/orang/src/main/java/lv/enes/orang/Parser.java index fd4b9bb..4011bd7 100644 --- a/src/main/java/lv/enes/orang/Parser.java +++ b/orang/src/main/java/lv/enes/orang/Parser.java | |||
| @@ -3,6 +3,7 @@ package lv.enes.orang; | |||
| 3 | import lv.enes.orang.ast.*; | 3 | import lv.enes.orang.ast.*; |
| 4 | import lv.enes.orang.ast.IfElseExpression; | 4 | import lv.enes.orang.ast.IfElseExpression; |
| 5 | import lv.enes.orang.ast.Statement; | 5 | import lv.enes.orang.ast.Statement; |
| 6 | import lv.enes.orang.utils.NonEmptyList; | ||
| 6 | 7 | ||
| 7 | import java.io.InputStream; | 8 | import java.io.InputStream; |
| 8 | import java.io.Reader; | 9 | import java.io.Reader; |
| @@ -253,7 +254,7 @@ public class Parser { | |||
| 253 | if (input.peek().type() == TokenType.DEF) { | 254 | if (input.peek().type() == TokenType.DEF) { |
| 254 | return parseDefinition(); | 255 | return parseDefinition(); |
| 255 | } else { | 256 | } else { |
| 256 | return parseExpression(); | 257 | return new ExpressionStatement(parseExpression()); |
| 257 | } | 258 | } |
| 258 | } | 259 | } |
| 259 | 260 | ||
diff --git a/src/main/java/lv/enes/orang/ParserException.java b/orang/src/main/java/lv/enes/orang/ParserException.java index 9000a93..bd65e7a 100644 --- a/src/main/java/lv/enes/orang/ParserException.java +++ b/orang/src/main/java/lv/enes/orang/ParserException.java | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | package lv.enes.orang; | 1 | package lv.enes.orang; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 3 | public class ParserException extends OrangException { | 5 | public class ParserException extends OrangException { |
| 4 | public ParserException(String message) { | 6 | public ParserException(String message) { |
| 5 | super(message); | 7 | super(message); |
diff --git a/src/main/java/lv/enes/orang/PeekableStream.java b/orang/src/main/java/lv/enes/orang/PeekableStream.java index b77bab1..b77bab1 100644 --- a/src/main/java/lv/enes/orang/PeekableStream.java +++ b/orang/src/main/java/lv/enes/orang/PeekableStream.java | |||
diff --git a/src/main/java/lv/enes/orang/State.java b/orang/src/main/java/lv/enes/orang/State.java index 46b115b..46b115b 100644 --- a/src/main/java/lv/enes/orang/State.java +++ b/orang/src/main/java/lv/enes/orang/State.java | |||
diff --git a/src/main/java/lv/enes/orang/Token.java b/orang/src/main/java/lv/enes/orang/Token.java index 4456b8f..4456b8f 100644 --- a/src/main/java/lv/enes/orang/Token.java +++ b/orang/src/main/java/lv/enes/orang/Token.java | |||
diff --git a/src/main/java/lv/enes/orang/TokenType.java b/orang/src/main/java/lv/enes/orang/TokenType.java index 960435e..960435e 100644 --- a/src/main/java/lv/enes/orang/TokenType.java +++ b/orang/src/main/java/lv/enes/orang/TokenType.java | |||
diff --git a/src/main/java/lv/enes/orang/value/Array.java b/orang/src/main/java/lv/enes/orang/value/Array.java index c3b645d..c3b645d 100644 --- a/src/main/java/lv/enes/orang/value/Array.java +++ b/orang/src/main/java/lv/enes/orang/value/Array.java | |||
diff --git a/src/main/java/lv/enes/orang/value/BuiltinFunction.java b/orang/src/main/java/lv/enes/orang/value/BuiltinFunction.java index 92ccc2e..92ccc2e 100644 --- a/src/main/java/lv/enes/orang/value/BuiltinFunction.java +++ b/orang/src/main/java/lv/enes/orang/value/BuiltinFunction.java | |||
diff --git a/src/main/java/lv/enes/orang/value/Function.java b/orang/src/main/java/lv/enes/orang/value/Function.java index 1f288c6..901776e 100644 --- a/src/main/java/lv/enes/orang/value/Function.java +++ b/orang/src/main/java/lv/enes/orang/value/Function.java | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | package lv.enes.orang.value; | 1 | package lv.enes.orang.value; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.Evaluator; | ||
| 4 | import lv.enes.orang.ImmutableScope; | ||
| 3 | import lv.enes.orang.OrangRuntimeException; | 5 | import lv.enes.orang.OrangRuntimeException; |
| 4 | import lv.enes.orang.Scope; | 6 | import lv.enes.orang.Scope; |
| 5 | import lv.enes.orang.ast.Expression; | 7 | import lv.enes.orang.ast.Expression; |
| @@ -20,7 +22,8 @@ public record Function(Scope scope, List<String> args, Expression body) implemen | |||
| 20 | @Override | 22 | @Override |
| 21 | public Value call(Value param) throws OrangRuntimeException { | 23 | public Value call(Value param) throws OrangRuntimeException { |
| 22 | if (args.size() == 1) { | 24 | if (args.size() == 1) { |
| 23 | return body.evaluateExpression(scope.withDefinition(args.getFirst(), param)); | 25 | var eval = new Evaluator(ImmutableScope.of(scope, args.getFirst(), param)); |
| 26 | return eval.visit(body); | ||
| 24 | } else { | 27 | } else { |
| 25 | return new PartialFunction(scope, args, List.of(param), body); | 28 | return new PartialFunction(scope, args, List.of(param), body); |
| 26 | } | 29 | } |
diff --git a/src/main/java/lv/enes/orang/value/OrangBoolean.java b/orang/src/main/java/lv/enes/orang/value/OrangBoolean.java index 8a4776c..8a4776c 100644 --- a/src/main/java/lv/enes/orang/value/OrangBoolean.java +++ b/orang/src/main/java/lv/enes/orang/value/OrangBoolean.java | |||
diff --git a/src/main/java/lv/enes/orang/value/OrangInteger.java b/orang/src/main/java/lv/enes/orang/value/OrangInteger.java index 9b8d505..9b8d505 100644 --- a/src/main/java/lv/enes/orang/value/OrangInteger.java +++ b/orang/src/main/java/lv/enes/orang/value/OrangInteger.java | |||
diff --git a/src/main/java/lv/enes/orang/value/OrangString.java b/orang/src/main/java/lv/enes/orang/value/OrangString.java index c03f7ac..c03f7ac 100644 --- a/src/main/java/lv/enes/orang/value/OrangString.java +++ b/orang/src/main/java/lv/enes/orang/value/OrangString.java | |||
diff --git a/src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java b/orang/src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java index 37278a4..37278a4 100644 --- a/src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java +++ b/orang/src/main/java/lv/enes/orang/value/PartialBuiltinFunction.java | |||
diff --git a/src/main/java/lv/enes/orang/value/PartialFunction.java b/orang/src/main/java/lv/enes/orang/value/PartialFunction.java index 59e1466..0dbf530 100644 --- a/src/main/java/lv/enes/orang/value/PartialFunction.java +++ b/orang/src/main/java/lv/enes/orang/value/PartialFunction.java | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | package lv.enes.orang.value; | 1 | package lv.enes.orang.value; |
| 2 | 2 | ||
| 3 | import lv.enes.orang.Evaluator; | ||
| 4 | import lv.enes.orang.ImmutableScope; | ||
| 3 | import lv.enes.orang.OrangRuntimeException; | 5 | import lv.enes.orang.OrangRuntimeException; |
| 4 | import lv.enes.orang.Scope; | 6 | import lv.enes.orang.Scope; |
| 5 | import lv.enes.orang.ast.Expression; | 7 | import lv.enes.orang.ast.Expression; |
| @@ -29,7 +31,8 @@ public record PartialFunction(Scope scope, List<String> args, List<Value> params | |||
| 29 | for (var i = 0; i < args.size(); i++) { | 31 | for (var i = 0; i < args.size(); i++) { |
| 30 | newDefs.put(args.get(i), newParams.get(i)); | 32 | newDefs.put(args.get(i), newParams.get(i)); |
| 31 | } | 33 | } |
| 32 | return body.evaluateExpression(scope.withDefinitions(newDefs)); | 34 | var eval = new Evaluator(ImmutableScope.of(scope, newDefs)); |
| 35 | return eval.visit(body); | ||
| 33 | } | 36 | } |
| 34 | 37 | ||
| 35 | return new PartialFunction(scope, args, Collections.unmodifiableList(newParams), body); | 38 | return new PartialFunction(scope, args, Collections.unmodifiableList(newParams), body); |
diff --git a/src/main/java/lv/enes/orang/value/Undefined.java b/orang/src/main/java/lv/enes/orang/value/Undefined.java index a341ee8..a341ee8 100644 --- a/src/main/java/lv/enes/orang/value/Undefined.java +++ b/orang/src/main/java/lv/enes/orang/value/Undefined.java | |||
diff --git a/src/main/java/lv/enes/orang/value/Value.java b/orang/src/main/java/lv/enes/orang/value/Value.java index fa8275c..fa8275c 100644 --- a/src/main/java/lv/enes/orang/value/Value.java +++ b/orang/src/main/java/lv/enes/orang/value/Value.java | |||
diff --git a/src/main/java/module-info.java b/orang/src/main/java/module-info.java index a4bdb66..060657f 100644 --- a/src/main/java/module-info.java +++ b/orang/src/main/java/module-info.java | |||
| @@ -1,5 +1,10 @@ | |||
| 1 | module lv.enes.orang { | 1 | module lv.enes.orang { |
| 2 | exports lv.enes.orang; | 2 | exports lv.enes.orang; |
| 3 | exports lv.enes.orang.value; | ||
| 4 | |||
| 5 | requires lv.enes.orang.ast; | ||
| 6 | requires lv.enes.orang.core; | ||
| 7 | requires lv.enes.orang.utils; | ||
| 3 | 8 | ||
| 4 | requires static jakarta.annotation; | 9 | requires static jakarta.annotation; |
| 5 | requires static lombok; | 10 | requires static lombok; |
diff --git a/src/main/resources/lv/enes/orang/prelude.orang b/orang/src/main/resources/lv/enes/orang/prelude.orang index 36bf197..d29eef3 100644 --- a/src/main/resources/lv/enes/orang/prelude.orang +++ b/orang/src/main/resources/lv/enes/orang/prelude.orang | |||
| @@ -1,12 +1,16 @@ | |||
| 1 | # builtins | ||
| 1 | def isRepl = __builtin_isRepl () | 2 | def isRepl = __builtin_isRepl () |
| 2 | def len arrayOrString = __builtin_len arrayOrString | 3 | def len arrayOrString = __builtin_len arrayOrString |
| 3 | def parseInt stringOrInt = __builtin_parseInt stringOrInt | 4 | def parseInt stringOrInt = __builtin_parseInt stringOrInt |
| 4 | def print anything = __builtin_print anything | 5 | def print anything = __builtin_print anything |
| 5 | def printLn x = do print x; print "\n"; x end | ||
| 6 | def randInt min max = __builtin_randInt min max | 6 | def randInt min max = __builtin_randInt min max |
| 7 | def readInt _ = parseInt (readLn ()) | ||
| 8 | def readLn _ = __builtin_readLn () | 7 | def readLn _ = __builtin_readLn () |
| 9 | 8 | ||
| 9 | # standard library | ||
| 10 | def readInt _ = parseInt (readLn ()) | ||
| 11 | def printLn x = do print x; print "\n"; x end | ||
| 12 | |||
| 13 | # repl intro :) | ||
| 10 | def _ = | 14 | def _ = |
| 11 | if isRepl then do | 15 | if isRepl then do |
| 12 | printLn "Hello! This is the Orang Programming Language!"; | 16 | printLn "Hello! This is the Orang Programming Language!"; |
diff --git a/src/main/java/lv/enes/orang/Scope.java b/src/main/java/lv/enes/orang/Scope.java deleted file mode 100644 index 3625c69..0000000 --- a/src/main/java/lv/enes/orang/Scope.java +++ /dev/null | |||
| @@ -1,54 +0,0 @@ | |||
| 1 | package lv.enes.orang; | ||
| 2 | |||
| 3 | import jakarta.annotation.Nullable; | ||
| 4 | import lv.enes.orang.value.Value; | ||
| 5 | |||
| 6 | import java.util.HashMap; | ||
| 7 | import java.util.Map; | ||
| 8 | |||
| 9 | public class Scope { | ||
| 10 | private final Map<String, Value> definitions; | ||
| 11 | |||
| 12 | private final Value lastResult; | ||
| 13 | |||
| 14 | public Scope() { | ||
| 15 | this(new HashMap<>(Builtins.BUILTINS), null); | ||
| 16 | } | ||
| 17 | |||
| 18 | private Scope(Map<String, Value> definitions, Value lastResult) { | ||
| 19 | this.definitions = definitions; | ||
| 20 | this.lastResult = lastResult; | ||
| 21 | } | ||
| 22 | |||
| 23 | public Value getDefinition(String name) throws OrangRuntimeException { | ||
| 24 | if (definitions.containsKey(name)) { | ||
| 25 | return definitions.get(name); | ||
| 26 | } | ||
| 27 | throw new OrangRuntimeException(STR."Value named \{name} is not defined!"); | ||
| 28 | } | ||
| 29 | |||
| 30 | @Nullable | ||
| 31 | public Value getLastResult() { | ||
| 32 | return lastResult; | ||
| 33 | } | ||
| 34 | |||
| 35 | public Scope withDefinition(String key, Value value) { | ||
| 36 | var newDefs = new HashMap<>(definitions); | ||
| 37 | newDefs.put(key, value); | ||
| 38 | return new Scope(newDefs, null); | ||
| 39 | } | ||
| 40 | |||
| 41 | public Scope withDefinitions(Map<String, Value> definitions) { | ||
| 42 | var newDefs = new HashMap<>(this.definitions); | ||
| 43 | newDefs.putAll(definitions); | ||
| 44 | return new Scope(newDefs, null); | ||
| 45 | } | ||
| 46 | |||
| 47 | public void setDefinition(String key, Value value) { | ||
| 48 | definitions.put(key, value); | ||
| 49 | } | ||
| 50 | |||
| 51 | public Scope withLastResult(Value value) { | ||
| 52 | return new Scope(definitions, value); | ||
| 53 | } | ||
| 54 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/ArrayExpression.java b/src/main/java/lv/enes/orang/ast/ArrayExpression.java deleted file mode 100644 index d2437cf..0000000 --- a/src/main/java/lv/enes/orang/ast/ArrayExpression.java +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Array; | ||
| 6 | import lv.enes.orang.value.Value; | ||
| 7 | |||
| 8 | import java.util.ArrayList; | ||
| 9 | import java.util.Collections; | ||
| 10 | import java.util.List; | ||
| 11 | |||
| 12 | public record ArrayExpression(List<Expression> items) implements Expression { | ||
| 13 | @Override | ||
| 14 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 15 | var values = new ArrayList<Value>(); | ||
| 16 | for (var item : items) { | ||
| 17 | values.add(item.evaluateExpression(scope)); | ||
| 18 | } | ||
| 19 | return new Array(Collections.unmodifiableList(values)); | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/BooleanLiteral.java b/src/main/java/lv/enes/orang/ast/BooleanLiteral.java deleted file mode 100644 index 9110f67..0000000 --- a/src/main/java/lv/enes/orang/ast/BooleanLiteral.java +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.Scope; | ||
| 4 | import lv.enes.orang.value.OrangBoolean; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public record BooleanLiteral(boolean value) implements Expression { | ||
| 8 | @Override | ||
| 9 | public Value evaluateExpression(Scope scope) { | ||
| 10 | return OrangBoolean.of(value); | ||
| 11 | } | ||
| 12 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/CallExpression.java b/src/main/java/lv/enes/orang/ast/CallExpression.java deleted file mode 100644 index 8f05496..0000000 --- a/src/main/java/lv/enes/orang/ast/CallExpression.java +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public record CallExpression(Expression callee, Expression arg) implements Expression { | ||
| 8 | @Override | ||
| 9 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 10 | return callee.evaluateExpression(scope).call(arg.evaluateExpression(scope)); | ||
| 11 | } | ||
| 12 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/Definition.java b/src/main/java/lv/enes/orang/ast/Definition.java deleted file mode 100644 index 715daae..0000000 --- a/src/main/java/lv/enes/orang/ast/Definition.java +++ /dev/null | |||
| @@ -1,15 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Undefined; | ||
| 6 | |||
| 7 | public record Definition(String name, Expression body) implements Statement { | ||
| 8 | @Override | ||
| 9 | public Scope runStatement(Scope scope) throws OrangRuntimeException { | ||
| 10 | scope.setDefinition(name, Undefined.INSTANCE); | ||
| 11 | var value = body.evaluateExpression(scope); | ||
| 12 | scope.setDefinition(name, value); | ||
| 13 | return scope; | ||
| 14 | } | ||
| 15 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/DoExpression.java b/src/main/java/lv/enes/orang/ast/DoExpression.java deleted file mode 100644 index 9d69a3e..0000000 --- a/src/main/java/lv/enes/orang/ast/DoExpression.java +++ /dev/null | |||
| @@ -1,19 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | import java.util.List; | ||
| 8 | |||
| 9 | public record DoExpression(List<Expression> body) implements Expression { | ||
| 10 | // assert body.!isEmpty() | ||
| 11 | |||
| 12 | @Override | ||
| 13 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 14 | for (var i = 0; i < body.size() - 1; i++) { | ||
| 15 | body.get(i).evaluateExpression(scope); | ||
| 16 | } | ||
| 17 | return body.getLast().evaluateExpression(scope); | ||
| 18 | } | ||
| 19 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/Expression.java b/src/main/java/lv/enes/orang/ast/Expression.java deleted file mode 100644 index a0fc3af..0000000 --- a/src/main/java/lv/enes/orang/ast/Expression.java +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public interface Expression extends Statement { | ||
| 8 | Value evaluateExpression(Scope scope) throws OrangRuntimeException; | ||
| 9 | |||
| 10 | @Override | ||
| 11 | default Scope runStatement(Scope scope) throws OrangRuntimeException { | ||
| 12 | return scope.withLastResult(evaluateExpression(scope)); | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/FnExpression.java b/src/main/java/lv/enes/orang/ast/FnExpression.java deleted file mode 100644 index 3c3522f..0000000 --- a/src/main/java/lv/enes/orang/ast/FnExpression.java +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.NonEmptyList; | ||
| 4 | import lv.enes.orang.OrangRuntimeException; | ||
| 5 | import lv.enes.orang.Scope; | ||
| 6 | import lv.enes.orang.value.Function; | ||
| 7 | import lv.enes.orang.value.Value; | ||
| 8 | |||
| 9 | public record FnExpression(NonEmptyList<String> args, Expression body) implements Expression { | ||
| 10 | @Override | ||
| 11 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 12 | return new Function(scope, args, body); | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/IfElseExpression.java b/src/main/java/lv/enes/orang/ast/IfElseExpression.java deleted file mode 100644 index 9b52cc5..0000000 --- a/src/main/java/lv/enes/orang/ast/IfElseExpression.java +++ /dev/null | |||
| @@ -1,22 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.OrangBoolean; | ||
| 6 | import lv.enes.orang.value.Value; | ||
| 7 | |||
| 8 | public record IfElseExpression(Expression condition, Expression trueBranch, Expression falseBranch) implements Expression { | ||
| 9 | @Override | ||
| 10 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 11 | var condValue = condition.evaluateExpression(scope); | ||
| 12 | if (condValue instanceof OrangBoolean value) { | ||
| 13 | if (value.value()) { | ||
| 14 | return trueBranch.evaluateExpression(scope); | ||
| 15 | } else { | ||
| 16 | return falseBranch.evaluateExpression(scope); | ||
| 17 | } | ||
| 18 | } else { | ||
| 19 | throw new OrangRuntimeException(STR."Condition in an if should be a Boolean not a \{condValue.typeName()}"); | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/IntLiteral.java b/src/main/java/lv/enes/orang/ast/IntLiteral.java deleted file mode 100644 index 339ba3b..0000000 --- a/src/main/java/lv/enes/orang/ast/IntLiteral.java +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.Scope; | ||
| 4 | import lv.enes.orang.value.OrangInteger; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public record IntLiteral(int value) implements Expression { | ||
| 8 | @Override | ||
| 9 | public Value evaluateExpression(Scope scope) { | ||
| 10 | return new OrangInteger(value); | ||
| 11 | } | ||
| 12 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/LetInExpression.java b/src/main/java/lv/enes/orang/ast/LetInExpression.java deleted file mode 100644 index 2379902..0000000 --- a/src/main/java/lv/enes/orang/ast/LetInExpression.java +++ /dev/null | |||
| @@ -1,27 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Undefined; | ||
| 6 | import lv.enes.orang.value.Value; | ||
| 7 | |||
| 8 | import java.util.HashMap; | ||
| 9 | import java.util.List; | ||
| 10 | |||
| 11 | public record LetInExpression(List<Binding> bindings, Expression body) implements Expression { | ||
| 12 | @Override | ||
| 13 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 14 | var newDefs = new HashMap<String, Value>(); | ||
| 15 | for (var binding : bindings) { | ||
| 16 | newDefs.put(binding.name, Undefined.INSTANCE); | ||
| 17 | } | ||
| 18 | var newState = scope.withDefinitions(newDefs); | ||
| 19 | for (var binding : bindings) { | ||
| 20 | var value = binding.value.evaluateExpression(newState); | ||
| 21 | newState.setDefinition(binding.name, value); | ||
| 22 | } | ||
| 23 | return body.evaluateExpression(newState); | ||
| 24 | } | ||
| 25 | |||
| 26 | public record Binding(String name, Expression value) {} | ||
| 27 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/Program.java b/src/main/java/lv/enes/orang/ast/Program.java deleted file mode 100644 index ae5d31e..0000000 --- a/src/main/java/lv/enes/orang/ast/Program.java +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | |||
| 6 | import java.util.List; | ||
| 7 | |||
| 8 | public record Program(List<Statement> statements) implements Statement { | ||
| 9 | @Override | ||
| 10 | public Scope runStatement(Scope inScope) throws OrangRuntimeException { | ||
| 11 | var state = inScope; | ||
| 12 | for (var statement : statements) { | ||
| 13 | state = statement.runStatement(state); | ||
| 14 | } | ||
| 15 | return state; | ||
| 16 | } | ||
| 17 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/Statement.java b/src/main/java/lv/enes/orang/ast/Statement.java deleted file mode 100644 index 0f52fc3..0000000 --- a/src/main/java/lv/enes/orang/ast/Statement.java +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | |||
| 6 | public interface Statement { | ||
| 7 | Scope runStatement(Scope scope) throws OrangRuntimeException; | ||
| 8 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/StringLiteral.java b/src/main/java/lv/enes/orang/ast/StringLiteral.java deleted file mode 100644 index 367dff5..0000000 --- a/src/main/java/lv/enes/orang/ast/StringLiteral.java +++ /dev/null | |||
| @@ -1,13 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.OrangString; | ||
| 6 | import lv.enes.orang.value.Value; | ||
| 7 | |||
| 8 | public record StringLiteral(String value) implements Expression { | ||
| 9 | @Override | ||
| 10 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 11 | return new OrangString(value); | ||
| 12 | } | ||
| 13 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/UnaryExpression.java b/src/main/java/lv/enes/orang/ast/UnaryExpression.java deleted file mode 100644 index a0f565b..0000000 --- a/src/main/java/lv/enes/orang/ast/UnaryExpression.java +++ /dev/null | |||
| @@ -1,23 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public record UnaryExpression(Operator operator, Expression child) implements Expression { | ||
| 8 | public enum Operator { | ||
| 9 | PLUS, | ||
| 10 | NEGATE, | ||
| 11 | NOT, | ||
| 12 | } | ||
| 13 | |||
| 14 | @Override | ||
| 15 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 16 | var child = child().evaluateExpression(scope); | ||
| 17 | return switch (operator) { | ||
| 18 | case PLUS -> child.plus(); | ||
| 19 | case NEGATE -> child.negate(); | ||
| 20 | case NOT -> child.not(); | ||
| 21 | }; | ||
| 22 | } | ||
| 23 | } | ||
diff --git a/src/main/java/lv/enes/orang/ast/VariableExpression.java b/src/main/java/lv/enes/orang/ast/VariableExpression.java deleted file mode 100644 index 1f5334d..0000000 --- a/src/main/java/lv/enes/orang/ast/VariableExpression.java +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.OrangRuntimeException; | ||
| 4 | import lv.enes.orang.Scope; | ||
| 5 | import lv.enes.orang.value.Value; | ||
| 6 | |||
| 7 | public record VariableExpression(String name) implements Expression { | ||
| 8 | @Override | ||
| 9 | public Value evaluateExpression(Scope scope) throws OrangRuntimeException { | ||
| 10 | return scope.getDefinition(name); | ||
| 11 | } | ||
| 12 | } | ||
diff --git a/src/main/java/lv/enes/orang/NonEmptyList.java b/utils/src/main/java/lv/enes/orang/utils/NonEmptyList.java index 860db28..197491f 100644 --- a/src/main/java/lv/enes/orang/NonEmptyList.java +++ b/utils/src/main/java/lv/enes/orang/utils/NonEmptyList.java | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | package lv.enes.orang; | 1 | package lv.enes.orang.utils; |
| 2 | 2 | ||
| 3 | import lombok.EqualsAndHashCode; | 3 | import lombok.EqualsAndHashCode; |
| 4 | 4 | ||