diff options
74 files changed, 582 insertions, 327 deletions
diff --git a/ast/build.gradle.kts b/ast/build.gradle.kts new file mode 100644 index 0000000..357e080 --- /dev/null +++ b/ast/build.gradle.kts | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | plugins { | ||
| 2 | java | ||
| 3 | } | ||
| 4 | |||
| 5 | dependencies { | ||
| 6 | implementation(project(":core")) | ||
| 7 | implementation(project(":utils")) | ||
| 8 | } | ||
| 9 | |||
| 10 | java { | ||
| 11 | sourceCompatibility = JavaVersion.VERSION_22 | ||
| 12 | targetCompatibility = JavaVersion.VERSION_22 | ||
| 13 | toolchain { | ||
| 14 | languageVersion = JavaLanguageVersion.of(22) | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | tasks.withType<JavaCompile> { | ||
| 19 | options.compilerArgs.add("--enable-preview") | ||
| 20 | } \ No newline at end of file | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/ArrayExpression.java b/ast/src/main/java/lv/enes/orang/ast/ArrayExpression.java new file mode 100644 index 0000000..acd1a36 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/ArrayExpression.java | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | import java.util.List; | ||
| 6 | |||
| 7 | public record ArrayExpression(List<Expression> items) implements Expression { | ||
| 8 | @Override | ||
| 9 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 10 | return visitor.visitArray(this); | ||
| 11 | } | ||
| 12 | } | ||
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/ast/src/main/java/lv/enes/orang/ast/BooleanLiteral.java b/ast/src/main/java/lv/enes/orang/ast/BooleanLiteral.java new file mode 100644 index 0000000..16bf176 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/BooleanLiteral.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record BooleanLiteral(boolean value) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitBoolean(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/CallExpression.java b/ast/src/main/java/lv/enes/orang/ast/CallExpression.java new file mode 100644 index 0000000..38ff7bd --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/CallExpression.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record CallExpression(Expression callee, Expression arg) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitCallExpression(this); | ||
| 9 | } | ||
| 10 | } | ||
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/ast/src/main/java/lv/enes/orang/ast/Definition.java b/ast/src/main/java/lv/enes/orang/ast/Definition.java new file mode 100644 index 0000000..b41cb1f --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/Definition.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record Definition(String name, Expression body) implements Statement { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(StatementVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitDefinition(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/DoExpression.java b/ast/src/main/java/lv/enes/orang/ast/DoExpression.java new file mode 100644 index 0000000..47eaddd --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/DoExpression.java | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | import java.util.List; | ||
| 6 | |||
| 7 | public record DoExpression(List<Expression> body) implements Expression { | ||
| 8 | // assert body.!isEmpty() | ||
| 9 | |||
| 10 | @Override | ||
| 11 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 12 | return visitor.visitDoExpression(this); | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/Expression.java b/ast/src/main/java/lv/enes/orang/ast/Expression.java new file mode 100644 index 0000000..a3e2acc --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/Expression.java | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public interface Expression { | ||
| 6 | <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E; | ||
| 7 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/ExpressionStatement.java b/ast/src/main/java/lv/enes/orang/ast/ExpressionStatement.java new file mode 100644 index 0000000..2a9dae1 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/ExpressionStatement.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record ExpressionStatement(Expression expr) implements Statement { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(StatementVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitExpression(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/ExpressionVisitor.java b/ast/src/main/java/lv/enes/orang/ast/ExpressionVisitor.java new file mode 100644 index 0000000..ddb1157 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/ExpressionVisitor.java | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public interface ExpressionVisitor<R, E extends OrangException> { | ||
| 6 | default R visit(Expression expression) throws E { | ||
| 7 | return expression.accept(this); | ||
| 8 | } | ||
| 9 | |||
| 10 | R visitArray(ArrayExpression array) throws E; | ||
| 11 | R visitBoolean(BooleanLiteral expr) throws E; | ||
| 12 | R visitBinaryExpression(BinaryExpression expr) throws E; | ||
| 13 | R visitCallExpression(CallExpression expr) throws E; | ||
| 14 | R visitDoExpression(DoExpression expr) throws E; | ||
| 15 | R visitFnExpression(FnExpression expr) throws E; | ||
| 16 | R visitIfElseExpression(IfElseExpression expr) throws E; | ||
| 17 | R visitIntLiteral(IntLiteral expr) throws E; | ||
| 18 | R visitLetInExpression(LetInExpression expr) throws E; | ||
| 19 | R visitStringLiteral(StringLiteral expr) throws E; | ||
| 20 | R visitUnaryExpression(UnaryExpression expr) throws E; | ||
| 21 | R visitVariable(VariableExpression expr) throws E; | ||
| 22 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/FnExpression.java b/ast/src/main/java/lv/enes/orang/ast/FnExpression.java new file mode 100644 index 0000000..68f43af --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/FnExpression.java | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.utils.NonEmptyList; | ||
| 4 | import lv.enes.orang.core.OrangException; | ||
| 5 | |||
| 6 | public record FnExpression(NonEmptyList<String> args, Expression body) implements Expression { | ||
| 7 | @Override | ||
| 8 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 9 | return visitor.visitFnExpression(this); | ||
| 10 | } | ||
| 11 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/IfElseExpression.java b/ast/src/main/java/lv/enes/orang/ast/IfElseExpression.java new file mode 100644 index 0000000..86e48d4 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/IfElseExpression.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record IfElseExpression(Expression condition, Expression trueBranch, Expression falseBranch) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitIfElseExpression(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/IntLiteral.java b/ast/src/main/java/lv/enes/orang/ast/IntLiteral.java new file mode 100644 index 0000000..12333c9 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/IntLiteral.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record IntLiteral(int value) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitIntLiteral(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/LetInExpression.java b/ast/src/main/java/lv/enes/orang/ast/LetInExpression.java new file mode 100644 index 0000000..b292f08 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/LetInExpression.java | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | import java.util.List; | ||
| 6 | |||
| 7 | public record LetInExpression(List<Binding> bindings, Expression body) implements Expression { | ||
| 8 | @Override | ||
| 9 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 10 | return visitor.visitLetInExpression(this); | ||
| 11 | } | ||
| 12 | |||
| 13 | public record Binding(String name, Expression value) {} | ||
| 14 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/Program.java b/ast/src/main/java/lv/enes/orang/ast/Program.java new file mode 100644 index 0000000..9b38f3b --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/Program.java | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | import java.util.List; | ||
| 6 | |||
| 7 | public record Program(List<Statement> statements) implements Statement { | ||
| 8 | @Override | ||
| 9 | public <R, E extends OrangException> R accept(StatementVisitor<R, E> visitor) throws E { | ||
| 10 | return visitor.visitProgram(this); | ||
| 11 | } | ||
| 12 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/Statement.java b/ast/src/main/java/lv/enes/orang/ast/Statement.java new file mode 100644 index 0000000..283fd40 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/Statement.java | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public interface Statement { | ||
| 6 | <R, E extends OrangException> R accept(StatementVisitor<R, E> visitor) throws E; | ||
| 7 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/StatementVisitor.java b/ast/src/main/java/lv/enes/orang/ast/StatementVisitor.java new file mode 100644 index 0000000..fa3b2f6 --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/StatementVisitor.java | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public interface StatementVisitor<R, E extends OrangException> { | ||
| 6 | default R visit(Statement stmt) throws E { | ||
| 7 | return stmt.accept(this); | ||
| 8 | } | ||
| 9 | |||
| 10 | R visitDefinition(Definition def) throws E; | ||
| 11 | R visitExpression(ExpressionStatement expr) throws E; | ||
| 12 | R visitProgram(Program program) throws E; | ||
| 13 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/StringLiteral.java b/ast/src/main/java/lv/enes/orang/ast/StringLiteral.java new file mode 100644 index 0000000..5c47b7e --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/StringLiteral.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record StringLiteral(String value) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitStringLiteral(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/UnaryExpression.java b/ast/src/main/java/lv/enes/orang/ast/UnaryExpression.java new file mode 100644 index 0000000..d96ae6d --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/UnaryExpression.java | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record UnaryExpression(Operator operator, Expression child) implements Expression { | ||
| 6 | public enum Operator { | ||
| 7 | PLUS, | ||
| 8 | NEGATE, | ||
| 9 | NOT, | ||
| 10 | } | ||
| 11 | |||
| 12 | @Override | ||
| 13 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 14 | return visitor.visitUnaryExpression(this); | ||
| 15 | } | ||
| 16 | } | ||
diff --git a/ast/src/main/java/lv/enes/orang/ast/VariableExpression.java b/ast/src/main/java/lv/enes/orang/ast/VariableExpression.java new file mode 100644 index 0000000..615857b --- /dev/null +++ b/ast/src/main/java/lv/enes/orang/ast/VariableExpression.java | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | package lv.enes.orang.ast; | ||
| 2 | |||
| 3 | import lv.enes.orang.core.OrangException; | ||
| 4 | |||
| 5 | public record VariableExpression(String name) implements Expression { | ||
| 6 | @Override | ||
| 7 | public <R, E extends OrangException> R accept(ExpressionVisitor<R, E> visitor) throws E { | ||
| 8 | return visitor.visitVariable(this); | ||
| 9 | } | ||
| 10 | } | ||
diff --git a/ast/src/main/java/module-info.java b/ast/src/main/java/module-info.java new file mode 100644 index 0000000..7ebe37b --- /dev/null +++ b/ast/src/main/java/module-info.java | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | module lv.enes.orang.ast { | ||
| 2 | exports lv.enes.orang.ast; | ||
| 3 | |||
| 4 | requires lv.enes.orang.core; | ||
| 5 | requires lv.enes.orang.utils; | ||
| 6 | } \ No newline at end of file | ||
diff --git a/core/build.gradle.kts b/core/build.gradle.kts new file mode 100644 index 0000000..19bbafc --- /dev/null +++ b/core/build.gradle.kts | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | plugins { | ||
| 2 | java | ||
| 3 | } | ||
| 4 | |||
| 5 | java { | ||
| 6 | sourceCompatibility = JavaVersion.VERSION_22 | ||
| 7 | targetCompatibility = JavaVersion.VERSION_22 | ||
| 8 | toolchain { | ||
| 9 | languageVersion = JavaLanguageVersion.of(22) | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | tasks.withType<JavaCompile> { | ||
| 14 | options.compilerArgs.add("--enable-preview") | ||
| 15 | } \ No newline at end of file | ||
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/core/src/main/java/module-info.java b/core/src/main/java/module-info.java new file mode 100644 index 0000000..b8b8703 --- /dev/null +++ b/core/src/main/java/module-info.java | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | module lv.enes.orang.core { | ||
| 2 | exports lv.enes.orang.core; | ||
| 3 | } \ No newline at end of file | ||
diff --git a/grammar.bnf b/grammar.bnf index 256e58a..7c18f8f 100644 --- a/grammar.bnf +++ b/grammar.bnf | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | // Comments are introduced by # and terminated by newline | ||
| 2 | |||
| 1 | program ::= (statement ';'?)*; | 3 | program ::= (statement ';'?)*; |
| 2 | statement ::= definition | expression; | 4 | statement ::= definition | expression; |
| 3 | definition ::= 'def' def-spec '=' expression; | 5 | definition ::= 'def' def-spec '=' expression; |
diff --git a/build.gradle.kts b/orang/build.gradle.kts index 212943a..f70609e 100644 --- a/build.gradle.kts +++ b/orang/build.gradle.kts | |||
| @@ -5,6 +5,7 @@ plugins { | |||
| 5 | id("org.beryx.jlink") version "3.0.1" | 5 | id("org.beryx.jlink") version "3.0.1" |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | val asmVersion = "9.7" | ||
| 8 | val slf4jVersion = "2.0.13" | 9 | val slf4jVersion = "2.0.13" |
| 9 | val jakartaAnnotationVersion = "3.0.0" | 10 | val jakartaAnnotationVersion = "3.0.0" |
| 10 | 11 | ||
| @@ -16,9 +17,14 @@ repositories { | |||
| 16 | } | 17 | } |
| 17 | 18 | ||
| 18 | dependencies { | 19 | dependencies { |
| 20 | implementation("org.ow2.asm:asm:$asmVersion") | ||
| 19 | implementation("jakarta.annotation:jakarta.annotation-api:$jakartaAnnotationVersion") | 21 | implementation("jakarta.annotation:jakarta.annotation-api:$jakartaAnnotationVersion") |
| 20 | implementation("org.slf4j:slf4j-api:$slf4jVersion") | 22 | implementation("org.slf4j:slf4j-api:$slf4jVersion") |
| 21 | implementation("org.slf4j:slf4j-simple:$slf4jVersion") | 23 | implementation("org.slf4j:slf4j-simple:$slf4jVersion") |
| 24 | |||
| 25 | implementation(project(":ast")) | ||
| 26 | implementation(project(":core")) | ||
| 27 | implementation(project(":utils")) | ||
| 22 | } | 28 | } |
| 23 | 29 | ||
| 24 | java { | 30 | java { |
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/orang/src/main/java/lv/enes/orang/Evaluator.java b/orang/src/main/java/lv/enes/orang/Evaluator.java new file mode 100644 index 0000000..e2e96ff --- /dev/null +++ b/orang/src/main/java/lv/enes/orang/Evaluator.java | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | package lv.enes.orang; | ||
| 2 | |||
| 3 | import lv.enes.orang.ast.*; | ||
| 4 | import lv.enes.orang.value.*; | ||
| 5 | |||
| 6 | import java.util.ArrayList; | ||
| 7 | import java.util.Collections; | ||
| 8 | |||
| 9 | public record Evaluator(Scope scope, Value lastResult) implements ExpressionVisitor<Value, OrangRuntimeException>, StatementVisitor<Evaluator, OrangRuntimeException> { | ||
| 10 | public Evaluator() { | ||
| 11 | this(Scope.topLevel()); | ||
| 12 | } | ||
| 13 | |||
| 14 | public Evaluator(Scope scope) { | ||
| 15 | this(scope, Undefined.INSTANCE); | ||
| 16 | } | ||
| 17 | |||
| 18 | @Override | ||
| 19 | public Value visitArray(ArrayExpression expr) throws OrangRuntimeException { | ||
| 20 | var values = new ArrayList<Value>(expr.items().size()); | ||
| 21 | for (var item : expr.items()) { | ||
| 22 | values.add(visit(item)); | ||
| 23 | } | ||
| 24 | values.trimToSize(); | ||
| 25 | return new Array(Collections.unmodifiableList(values)); | ||
| 26 | } | ||
| 27 | |||
| 28 | @Override | ||
| 29 | public Value visitBinaryExpression(BinaryExpression expr) throws OrangRuntimeException { | ||
| 30 | var lhs = visit(expr.lhs()); | ||
| 31 | var rhs = visit(expr.rhs()); | ||
| 32 | return switch (expr.operator()) { | ||
| 33 | case EQUALS -> lhs.orangEquals(rhs); | ||
| 34 | case NOT_EQUALS -> lhs.notEquals(rhs); | ||
| 35 | case GT -> lhs.greaterThan(rhs); | ||
| 36 | case GTE -> lhs.greaterThanOrEqual(rhs); | ||
| 37 | case LT -> lhs.lessThan(rhs); | ||
| 38 | case LTE -> lhs.lessThanOrEqual(rhs); | ||
| 39 | case ADD -> lhs.add(rhs); | ||
| 40 | case SUBTRACT -> lhs.subtract(rhs); | ||
| 41 | case MULTIPLY -> lhs.multiply(rhs); | ||
| 42 | case DIVIDE -> lhs.divide(rhs); | ||
| 43 | }; | ||
| 44 | } | ||
| 45 | |||
| 46 | @Override | ||
| 47 | public Value visitBoolean(BooleanLiteral expr) { | ||
| 48 | return OrangBoolean.of(expr.value()); | ||
| 49 | } | ||
| 50 | |||
| 51 | @Override | ||
| 52 | public Value visitCallExpression(CallExpression expr) throws OrangRuntimeException { | ||
| 53 | var arg = visit(expr.arg()); | ||
| 54 | return visit(expr.callee()).call(arg); | ||
| 55 | } | ||
| 56 | |||
| 57 | @Override | ||
| 58 | public Evaluator visitDefinition(Definition def) throws OrangRuntimeException { | ||
| 59 | var newScope = MutableScope.of(scope, def.name(), Undefined.INSTANCE); | ||
| 60 | var newEvaluator = new Evaluator(newScope); | ||
| 61 | newScope.setDefinition(def.name(), newEvaluator.visit(def.body())); | ||
| 62 | return newEvaluator; | ||
| 63 | } | ||
| 64 | |||
| 65 | @Override | ||
| 66 | public Value visitDoExpression(DoExpression expr) throws OrangRuntimeException { | ||
| 67 | Value value = Undefined.INSTANCE; | ||
| 68 | for (var child : expr.body()) { | ||
| 69 | value = visit(child); | ||
| 70 | } | ||
| 71 | return value; | ||
| 72 | } | ||
| 73 | |||
| 74 | @Override | ||
| 75 | public Evaluator visitExpression(ExpressionStatement expr) throws OrangRuntimeException { | ||
| 76 | return new Evaluator(this.scope(), visit(expr.expr())); | ||
| 77 | } | ||
| 78 | |||
| 79 | @Override | ||
| 80 | public Value visitFnExpression(FnExpression expr) { | ||
| 81 | return new Function(this.scope, expr.args(), expr.body()); | ||
| 82 | } | ||
| 83 | |||
| 84 | @Override | ||
| 85 | public Value visitIfElseExpression(IfElseExpression expr) throws OrangRuntimeException { | ||
| 86 | var cond = visit(expr.condition()); | ||
| 87 | if (cond instanceof OrangBoolean value) { | ||
| 88 | if (value.value()) { | ||
| 89 | return visit(expr.trueBranch()); | ||
| 90 | } else { | ||
| 91 | return visit(expr.falseBranch()); | ||
| 92 | } | ||
| 93 | } else { | ||
| 94 | throw new OrangRuntimeException(STR."Condition in an if-else statement should be a boolean not a \{cond.typeName()}"); | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | @Override | ||
| 99 | public Value visitIntLiteral(IntLiteral expr) { | ||
| 100 | return new OrangInteger(expr.value()); | ||
| 101 | } | ||
| 102 | |||
| 103 | @Override | ||
| 104 | public Value visitLetInExpression(LetInExpression expr) throws OrangRuntimeException { | ||
| 105 | var newScope = MutableScope.of(scope); | ||
| 106 | for (var binding : expr.bindings()) { | ||
| 107 | newScope.setDefinition(binding.name(), Undefined.INSTANCE); | ||
| 108 | } | ||
| 109 | var newEvaluator = new Evaluator(newScope); | ||
| 110 | for (var binding : expr.bindings()) { | ||
| 111 | newScope.setDefinition(binding.name(), newEvaluator.visit(binding.value())); | ||
| 112 | } | ||
| 113 | return newEvaluator.visit(expr.body()); | ||
| 114 | } | ||
| 115 | |||
| 116 | @Override | ||
| 117 | public Evaluator visitProgram(Program prog) throws OrangRuntimeException { | ||
| 118 | var evaluator = this; | ||
| 119 | for (var statement : prog.statements()) { | ||
| 120 | evaluator = evaluator.visit(statement); | ||
| 121 | } | ||
| 122 | return evaluator; | ||
| 123 | } | ||
| 124 | |||
| 125 | @Override | ||
| 126 | public Value visitUnaryExpression(UnaryExpression expr) throws OrangRuntimeException { | ||
| 127 | var child = visit(expr.child()); | ||
| 128 | return switch (expr.operator()) { | ||
| 129 | case PLUS -> child.plus(); | ||
| 130 | case NEGATE -> child.negate(); | ||
| 131 | case NOT -> child.not(); | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | @Override | ||
| 136 | public Value visitStringLiteral(StringLiteral expr) { | ||
| 137 | return new OrangString(expr.value()); | ||
| 138 | } | ||
| 139 | |||
| 140 | @Override | ||
| 141 | public Value visitVariable(VariableExpression expr) throws OrangRuntimeException { | ||
| 142 | return scope.getDefinition(expr.name()); | ||
| 143 | } | ||
| 144 | } | ||
diff --git a/orang/src/main/java/lv/enes/orang/ImmutableScope.java b/orang/src/main/java/lv/enes/orang/ImmutableScope.java new file mode 100644 index 0000000..9cb6138 --- /dev/null +++ b/orang/src/main/java/lv/enes/orang/ImmutableScope.java | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | package lv.enes.orang; | ||
| 2 | |||
| 3 | import lv.enes.orang.value.Value; | ||
| 4 | |||
| 5 | import java.util.HashMap; | ||
| 6 | import java.util.Map; | ||
| 7 | |||
| 8 | public class ImmutableScope extends Scope { | ||
| 9 | public static ImmutableScope of(Scope parent) { | ||
| 10 | if (parent instanceof ImmutableScope imm) { | ||
| 11 | return imm; | ||
| 12 | } | ||
| 13 | return ImmutableScope.of(parent, Map.of()); | ||
| 14 | } | ||
| 15 | |||
| 16 | public static ImmutableScope of(Scope parent, String key, Value value) { | ||
| 17 | return ImmutableScope.of(parent, Map.of(key, value)); | ||
| 18 | } | ||
| 19 | |||
| 20 | public static ImmutableScope of(Scope parent, Map<String, Value> definitions) { | ||
| 21 | return new ImmutableScope(parent, definitions).maybeFlattened(); | ||
| 22 | } | ||
| 23 | |||
| 24 | protected ImmutableScope(Scope parent, Map<String, Value> definitions) { | ||
| 25 | super(parent, Map.copyOf(definitions)); | ||
| 26 | } | ||
| 27 | |||
| 28 | public ImmutableScope maybeFlattened() { | ||
| 29 | if (depth > MAX_DEPTH) { | ||
| 30 | return flattened(); | ||
| 31 | } | ||
| 32 | return this; | ||
| 33 | } | ||
| 34 | |||
| 35 | private ImmutableScope flattened() { | ||
| 36 | if (parent instanceof ImmutableScope immParent) { | ||
| 37 | var flatParent = immParent.flattened(); | ||
| 38 | var newDefs = new HashMap<>(flatParent.definitions); | ||
| 39 | newDefs.putAll(definitions); | ||
| 40 | return new ImmutableScope(flatParent.parent, newDefs); | ||
| 41 | } | ||
| 42 | |||
| 43 | return this; | ||
| 44 | } | ||
| 45 | } | ||
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/orang/src/main/java/lv/enes/orang/MutableScope.java b/orang/src/main/java/lv/enes/orang/MutableScope.java new file mode 100644 index 0000000..8d900a4 --- /dev/null +++ b/orang/src/main/java/lv/enes/orang/MutableScope.java | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | package lv.enes.orang; | ||
| 2 | |||
| 3 | import lv.enes.orang.value.Value; | ||
| 4 | |||
| 5 | import java.util.HashMap; | ||
| 6 | import java.util.Map; | ||
| 7 | |||
| 8 | public class MutableScope extends Scope { | ||
| 9 | public static MutableScope of(Scope parent) { | ||
| 10 | return new MutableScope(parent, Map.of()); | ||
| 11 | } | ||
| 12 | |||
| 13 | public static MutableScope of(Scope parent, String name, Value value) { | ||
| 14 | return new MutableScope(parent, Map.of(name, value)); | ||
| 15 | } | ||
| 16 | |||
| 17 | protected MutableScope(Scope parent, Map<String, Value> definitions) { | ||
| 18 | super(parent, new HashMap<>(definitions)); | ||
| 19 | } | ||
| 20 | |||
| 21 | public void setDefinition(String key, Value value) { | ||
| 22 | definitions.put(key, value); | ||
| 23 | } | ||
| 24 | } | ||
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/orang/src/main/java/lv/enes/orang/Scope.java b/orang/src/main/java/lv/enes/orang/Scope.java new file mode 100644 index 0000000..7fe57c7 --- /dev/null +++ b/orang/src/main/java/lv/enes/orang/Scope.java | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | package lv.enes.orang; | ||
| 2 | |||
| 3 | import lv.enes.orang.value.Value; | ||
| 4 | |||
| 5 | import java.util.HashMap; | ||
| 6 | import java.util.Map; | ||
| 7 | |||
| 8 | public abstract class Scope { | ||
| 9 | public static final int MAX_DEPTH = 4; | ||
| 10 | |||
| 11 | protected final Scope parent; | ||
| 12 | protected final Map<String, Value> definitions; | ||
| 13 | protected final int depth; | ||
| 14 | |||
| 15 | public static MutableScope topLevel() { | ||
| 16 | return new MutableScope(null, new HashMap<>(Builtins.BUILTINS)); | ||
| 17 | } | ||
| 18 | |||
| 19 | protected Scope(Scope parent, Map<String, Value> definitions) { | ||
| 20 | this.parent = parent; | ||
| 21 | this.definitions = definitions; | ||
| 22 | this.depth = parent == null ? 0 : parent.depth + 1; | ||
| 23 | } | ||
| 24 | |||
| 25 | public Value getDefinition(String name) throws OrangRuntimeException { | ||
| 26 | if (definitions.containsKey(name)) { | ||
| 27 | return definitions.get(name); | ||
| 28 | } else if (parent != null) { | ||
| 29 | return parent.getDefinition(name); | ||
| 30 | } else { | ||
| 31 | throw new OrangRuntimeException(STR."Value named \{name} is not defined!"); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | } | ||
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/settings.gradle.kts b/settings.gradle.kts index 4c4ac7d..fc692fa 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts | |||
| @@ -1,2 +1,3 @@ | |||
| 1 | rootProject.name = "orang" | 1 | rootProject.name = "orang" |
| 2 | 2 | ||
| 3 | include("ast", "core", "orang", "utils") \ No newline at end of file | ||
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/utils/build.gradle.kts b/utils/build.gradle.kts new file mode 100644 index 0000000..04cda43 --- /dev/null +++ b/utils/build.gradle.kts | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | plugins { | ||
| 2 | java | ||
| 3 | id("io.freefair.lombok") version "8.6" | ||
| 4 | } | ||
| 5 | |||
| 6 | repositories { | ||
| 7 | mavenCentral() | ||
| 8 | } | ||
| 9 | |||
| 10 | java { | ||
| 11 | sourceCompatibility = JavaVersion.VERSION_22 | ||
| 12 | targetCompatibility = JavaVersion.VERSION_22 | ||
| 13 | toolchain { | ||
| 14 | languageVersion = JavaLanguageVersion.of(22) | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | tasks.withType<JavaCompile> { | ||
| 19 | options.compilerArgs.add("--enable-preview") | ||
| 20 | } \ No newline at end of file | ||
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 | ||
diff --git a/utils/src/main/java/module-info.java b/utils/src/main/java/module-info.java new file mode 100644 index 0000000..47e37e0 --- /dev/null +++ b/utils/src/main/java/module-info.java | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | module lv.enes.orang.utils { | ||
| 2 | exports lv.enes.orang.utils; | ||
| 3 | |||
| 4 | requires static lombok; | ||
| 5 | } \ No newline at end of file | ||