Remove unnecessary abstraction Expression, use Statement only as marker

This commit is contained in:
aNNiMON 2023-10-14 18:47:27 +03:00 committed by Victor Melnik
parent f6d4ff5cc9
commit 1535e86472
61 changed files with 355 additions and 353 deletions

View File

@ -65,7 +65,7 @@ public class UserDefinedFunction implements Function, SourceLocation {
final Argument arg = arguments.get(i); final Argument arg = arguments.get(i);
ScopeHandler.defineVariableInCurrentScope(arg.name(), arg.valueExpr().eval()); ScopeHandler.defineVariableInCurrentScope(arg.name(), arg.valueExpr().eval());
} }
body.execute(); body.eval();
return NumberValue.ZERO; return NumberValue.ZERO;
} catch (ReturnStatement rt) { } catch (ReturnStatement rt) {
return rt.getResult(); return rt.getResult();

View File

@ -20,9 +20,9 @@ import java.util.stream.Collectors;
*/ */
public final class Parser { public final class Parser {
public static Statement parse(List<Token> tokens) { public static Node parse(List<Token> tokens) {
final Parser parser = new Parser(tokens); final Parser parser = new Parser(tokens);
final Statement program = parser.parse(); final Node program = parser.parse();
if (parser.getParseErrors().hasErrors()) { if (parser.getParseErrors().hasErrors()) {
throw new OwnLangParserException(parser.getParseErrors()); throw new OwnLangParserException(parser.getParseErrors());
} }
@ -71,7 +71,7 @@ public final class Parser {
return parseErrors; return parseErrors;
} }
public Statement parse() { public Node parse() {
parseErrors.clear(); parseErrors.clear();
final BlockStatement result = new BlockStatement(); final BlockStatement result = new BlockStatement();
while (!match(TokenType.EOF)) { while (!match(TokenType.EOF)) {
@ -180,7 +180,7 @@ public final class Parser {
if (match(TokenType.EXTRACT)) { if (match(TokenType.EXTRACT)) {
return destructuringAssignment(); return destructuringAssignment();
} }
final Expression expression = expression(); final Node expression = expression();
if (expression instanceof Statement statement) { if (expression instanceof Statement statement) {
return statement; return statement;
} }
@ -209,7 +209,7 @@ public final class Parser {
} }
private Statement ifElse() { private Statement ifElse() {
final Expression condition = expression(); final Node condition = expression();
final Statement ifStatement = statementOrBlock(); final Statement ifStatement = statementOrBlock();
final Statement elseStatement; final Statement elseStatement;
if (match(TokenType.ELSE)) { if (match(TokenType.ELSE)) {
@ -221,7 +221,7 @@ public final class Parser {
} }
private Statement whileStatement() { private Statement whileStatement() {
final Expression condition = expression(); final Node condition = expression();
final Statement statement = statementOrBlock(); final Statement statement = statementOrBlock();
return new WhileStatement(condition, statement); return new WhileStatement(condition, statement);
} }
@ -229,7 +229,7 @@ public final class Parser {
private Statement doWhileStatement() { private Statement doWhileStatement() {
final Statement statement = statementOrBlock(); final Statement statement = statementOrBlock();
consume(TokenType.WHILE); consume(TokenType.WHILE);
final Expression condition = expression(); final Node condition = expression();
return new DoWhileStatement(condition, statement); return new DoWhileStatement(condition, statement);
} }
@ -252,7 +252,7 @@ public final class Parser {
boolean optParentheses = match(TokenType.LPAREN); boolean optParentheses = match(TokenType.LPAREN);
final Statement initialization = assignmentStatement(); final Statement initialization = assignmentStatement();
consume(TokenType.COMMA); consume(TokenType.COMMA);
final Expression termination = expression(); final Node termination = expression();
consume(TokenType.COMMA); consume(TokenType.COMMA);
final Statement increment = assignmentStatement(); final Statement increment = assignmentStatement();
if (optParentheses) consume(TokenType.RPAREN); // close opt parentheses if (optParentheses) consume(TokenType.RPAREN); // close opt parentheses
@ -265,7 +265,7 @@ public final class Parser {
boolean optParentheses = match(TokenType.LPAREN); boolean optParentheses = match(TokenType.LPAREN);
final String variable = consume(TokenType.WORD).text(); final String variable = consume(TokenType.WORD).text();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression container = expression(); final Node container = expression();
if (optParentheses) { if (optParentheses) {
consume(TokenType.RPAREN); // close opt parentheses consume(TokenType.RPAREN); // close opt parentheses
} }
@ -280,7 +280,7 @@ public final class Parser {
consume(TokenType.COMMA); consume(TokenType.COMMA);
final String value = consume(TokenType.WORD).text(); final String value = consume(TokenType.WORD).text();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression container = expression(); final Node container = expression();
if (optParentheses) { if (optParentheses) {
consume(TokenType.RPAREN); // close opt parentheses consume(TokenType.RPAREN); // close opt parentheses
} }
@ -332,14 +332,14 @@ public final class Parser {
); );
} }
private Expression functionChain(Expression qualifiedNameExpr) { private Node functionChain(Node qualifiedNameExpr) {
// f1()()() || f1().f2().f3() || f1().key // f1()()() || f1().f2().f3() || f1().key
final Expression expr = function(qualifiedNameExpr); final Node expr = function(qualifiedNameExpr);
if (lookMatch(0, TokenType.LPAREN)) { if (lookMatch(0, TokenType.LPAREN)) {
return functionChain(expr); return functionChain(expr);
} }
if (lookMatch(0, TokenType.DOT)) { if (lookMatch(0, TokenType.DOT)) {
final List<Expression> indices = variableSuffix(); final List<Node> indices = variableSuffix();
if (indices == null || indices.isEmpty()) { if (indices == null || indices.isEmpty()) {
return expr; return expr;
} }
@ -354,7 +354,7 @@ public final class Parser {
return expr; return expr;
} }
private FunctionalExpression function(Expression qualifiedNameExpr) { private FunctionalExpression function(Node qualifiedNameExpr) {
// function(arg1, arg2, ...) // function(arg1, arg2, ...)
final var startTokenIndex = index - 1; final var startTokenIndex = index - 1;
consume(TokenType.LPAREN); consume(TokenType.LPAREN);
@ -367,10 +367,10 @@ public final class Parser {
return function; return function;
} }
private Expression array() { private Node array() {
// [value1, value2, ...] // [value1, value2, ...]
consume(TokenType.LBRACKET); consume(TokenType.LBRACKET);
final List<Expression> elements = new ArrayList<>(); final List<Node> elements = new ArrayList<>();
while (!match(TokenType.RBRACKET)) { while (!match(TokenType.RBRACKET)) {
elements.add(expression()); elements.add(expression());
match(TokenType.COMMA); match(TokenType.COMMA);
@ -378,14 +378,14 @@ public final class Parser {
return new ArrayExpression(elements); return new ArrayExpression(elements);
} }
private Expression map() { private Node map() {
// {key1 : value1, key2 : value2, ...} // {key1 : value1, key2 : value2, ...}
consume(TokenType.LBRACE); consume(TokenType.LBRACE);
final Map<Expression, Expression> elements = new HashMap<>(); final Map<Node, Node> elements = new HashMap<>();
while (!match(TokenType.RBRACE)) { while (!match(TokenType.RBRACE)) {
final Expression key = primary(); final Node key = primary();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression value = expression(); final Node value = expression();
elements.put(key, value); elements.put(key, value);
match(TokenType.COMMA); match(TokenType.COMMA);
} }
@ -397,7 +397,7 @@ public final class Parser {
// case pattern1: result1 // case pattern1: result1
// case pattern2 if expr: result2 // case pattern2 if expr: result2
// } // }
final Expression expression = expression(); final Node expression = expression();
consume(TokenType.LBRACE); consume(TokenType.LBRACE);
final List<MatchExpression.Pattern> patterns = new ArrayList<>(); final List<MatchExpression.Pattern> patterns = new ArrayList<>();
do { do {
@ -494,12 +494,12 @@ public final class Parser {
return classDeclaration; return classDeclaration;
} }
private Expression expression() { private Node expression() {
return assignment(); return assignment();
} }
private Expression assignment() { private Node assignment() {
final Expression assignment = assignmentStrict(); final Node assignment = assignmentStrict();
if (assignment != null) { if (assignment != null) {
return assignment; return assignment;
} }
@ -509,7 +509,7 @@ public final class Parser {
private AssignmentExpression assignmentStrict() { private AssignmentExpression assignmentStrict() {
// x[0].prop += ... // x[0].prop += ...
final int position = index; final int position = index;
final Expression targetExpr = qualifiedName(); final Node targetExpr = qualifiedName();
if (!(targetExpr instanceof Accessible)) { if (!(targetExpr instanceof Accessible)) {
index = position; index = position;
return null; return null;
@ -523,18 +523,18 @@ public final class Parser {
match(currentType); match(currentType);
final BinaryExpression.Operator op = ASSIGN_OPERATORS.get(currentType); final BinaryExpression.Operator op = ASSIGN_OPERATORS.get(currentType);
final Expression expression = expression(); final Node expression = expression();
return new AssignmentExpression(op, (Accessible) targetExpr, expression); return new AssignmentExpression(op, (Accessible) targetExpr, expression);
} }
private Expression ternary() { private Node ternary() {
Expression result = nullCoalesce(); Node result = nullCoalesce();
if (match(TokenType.QUESTION)) { if (match(TokenType.QUESTION)) {
final Expression trueExpr = expression(); final Node trueExpr = expression();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression falseExpr = expression(); final Node falseExpr = expression();
return new TernaryExpression(result, trueExpr, falseExpr); return new TernaryExpression(result, trueExpr, falseExpr);
} }
if (match(TokenType.QUESTIONCOLON)) { if (match(TokenType.QUESTIONCOLON)) {
@ -543,8 +543,8 @@ public final class Parser {
return result; return result;
} }
private Expression nullCoalesce() { private Node nullCoalesce() {
Expression result = logicalOr(); Node result = logicalOr();
while (true) { while (true) {
if (match(TokenType.QUESTIONQUESTION)) { if (match(TokenType.QUESTIONQUESTION)) {
@ -557,8 +557,8 @@ public final class Parser {
return result; return result;
} }
private Expression logicalOr() { private Node logicalOr() {
Expression result = logicalAnd(); Node result = logicalAnd();
while (true) { while (true) {
if (match(TokenType.BARBAR)) { if (match(TokenType.BARBAR)) {
@ -571,8 +571,8 @@ public final class Parser {
return result; return result;
} }
private Expression logicalAnd() { private Node logicalAnd() {
Expression result = bitwiseOr(); Node result = bitwiseOr();
while (true) { while (true) {
if (match(TokenType.AMPAMP)) { if (match(TokenType.AMPAMP)) {
@ -585,8 +585,8 @@ public final class Parser {
return result; return result;
} }
private Expression bitwiseOr() { private Node bitwiseOr() {
Expression expression = bitwiseXor(); Node expression = bitwiseXor();
while (true) { while (true) {
if (match(TokenType.BAR)) { if (match(TokenType.BAR)) {
@ -599,8 +599,8 @@ public final class Parser {
return expression; return expression;
} }
private Expression bitwiseXor() { private Node bitwiseXor() {
Expression expression = bitwiseAnd(); Node expression = bitwiseAnd();
while (true) { while (true) {
if (match(TokenType.CARET)) { if (match(TokenType.CARET)) {
@ -613,8 +613,8 @@ public final class Parser {
return expression; return expression;
} }
private Expression bitwiseAnd() { private Node bitwiseAnd() {
Expression expression = equality(); Node expression = equality();
while (true) { while (true) {
if (match(TokenType.AMP)) { if (match(TokenType.AMP)) {
@ -627,8 +627,8 @@ public final class Parser {
return expression; return expression;
} }
private Expression equality() { private Node equality() {
Expression result = conditional(); Node result = conditional();
if (match(TokenType.EQEQ)) { if (match(TokenType.EQEQ)) {
return new ConditionalExpression(ConditionalExpression.Operator.EQUALS, result, conditional()); return new ConditionalExpression(ConditionalExpression.Operator.EQUALS, result, conditional());
@ -640,8 +640,8 @@ public final class Parser {
return result; return result;
} }
private Expression conditional() { private Node conditional() {
Expression result = shift(); Node result = shift();
while (true) { while (true) {
if (match(TokenType.LT)) { if (match(TokenType.LT)) {
@ -666,8 +666,8 @@ public final class Parser {
return result; return result;
} }
private Expression shift() { private Node shift() {
Expression expression = additive(); Node expression = additive();
while (true) { while (true) {
if (match(TokenType.LTLT)) { if (match(TokenType.LTLT)) {
@ -692,8 +692,8 @@ public final class Parser {
return expression; return expression;
} }
private Expression additive() { private Node additive() {
Expression result = multiplicative(); Node result = multiplicative();
while (true) { while (true) {
if (match(TokenType.PLUS)) { if (match(TokenType.PLUS)) {
@ -722,8 +722,8 @@ public final class Parser {
return result; return result;
} }
private Expression multiplicative() { private Node multiplicative() {
Expression result = objectCreation(); Node result = objectCreation();
while (true) { while (true) {
if (match(TokenType.STAR)) { if (match(TokenType.STAR)) {
@ -748,11 +748,11 @@ public final class Parser {
return result; return result;
} }
private Expression objectCreation() { private Node objectCreation() {
if (match(TokenType.NEW)) { if (match(TokenType.NEW)) {
final var startTokenIndex = index - 1; final var startTokenIndex = index - 1;
final String className = consume(TokenType.WORD).text(); final String className = consume(TokenType.WORD).text();
final List<Expression> args = new ArrayList<>(); final List<Node> args = new ArrayList<>();
consume(TokenType.LPAREN); consume(TokenType.LPAREN);
while (!match(TokenType.RPAREN)) { while (!match(TokenType.RPAREN)) {
args.add(expression()); args.add(expression());
@ -766,7 +766,7 @@ public final class Parser {
return unary(); return unary();
} }
private Expression unary() { private Node unary() {
if (match(TokenType.PLUSPLUS)) { if (match(TokenType.PLUSPLUS)) {
return new UnaryExpression(UnaryExpression.Operator.INCREMENT_PREFIX, primary()); return new UnaryExpression(UnaryExpression.Operator.INCREMENT_PREFIX, primary());
} }
@ -788,9 +788,9 @@ public final class Parser {
return primary(); return primary();
} }
private Expression primary() { private Node primary() {
if (match(TokenType.LPAREN)) { if (match(TokenType.LPAREN)) {
Expression result = expression(); Node result = expression();
consume(TokenType.RPAREN); consume(TokenType.RPAREN);
return result; return result;
} }
@ -813,13 +813,13 @@ public final class Parser {
return variable(); return variable();
} }
private Expression variable() { private Node variable() {
// function(... // function(...
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) { if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
return functionChain(new ValueExpression(consume(TokenType.WORD).text())); return functionChain(new ValueExpression(consume(TokenType.WORD).text()));
} }
final Expression qualifiedNameExpr = qualifiedName(); final Node qualifiedNameExpr = qualifiedName();
if (qualifiedNameExpr != null) { if (qualifiedNameExpr != null) {
// variable(args) || arr["key"](args) || obj.key(args) // variable(args) || arr["key"](args) || obj.key(args)
if (lookMatch(0, TokenType.LPAREN)) { if (lookMatch(0, TokenType.LPAREN)) {
@ -844,28 +844,28 @@ public final class Parser {
return value(); return value();
} }
private Expression qualifiedName() { private Node qualifiedName() {
// var || var.key[index].key2 // var || var.key[index].key2
final Token current = get(0); final Token current = get(0);
if (!match(TokenType.WORD)) return null; if (!match(TokenType.WORD)) return null;
final List<Expression> indices = variableSuffix(); final List<Node> indices = variableSuffix();
if (indices == null || indices.isEmpty()) { if (indices == null || indices.isEmpty()) {
return new VariableExpression(current.text()); return new VariableExpression(current.text());
} }
return new ContainerAccessExpression(current.text(), indices); return new ContainerAccessExpression(current.text(), indices);
} }
private List<Expression> variableSuffix() { private List<Node> variableSuffix() {
// .key1.arr1[expr1][expr2].key2 // .key1.arr1[expr1][expr2].key2
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) { if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
return null; return null;
} }
final List<Expression> indices = new ArrayList<>(); final List<Node> indices = new ArrayList<>();
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) { while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
if (match(TokenType.DOT)) { if (match(TokenType.DOT)) {
final String fieldName = consume(TokenType.WORD).text(); final String fieldName = consume(TokenType.WORD).text();
final Expression key = new ValueExpression(fieldName); final Node key = new ValueExpression(fieldName);
indices.add(key); indices.add(key);
} }
if (match(TokenType.LBRACKET)) { if (match(TokenType.LBRACKET)) {
@ -876,7 +876,7 @@ public final class Parser {
return indices; return indices;
} }
private Expression value() { private Node value() {
final Token current = get(0); final Token current = get(0);
if (match(TokenType.NUMBER)) { if (match(TokenType.NUMBER)) {
return new ValueExpression(createNumber(current.text(), 10)); return new ValueExpression(createNumber(current.text(), 10));
@ -898,7 +898,7 @@ public final class Parser {
new ValueExpression(consume(TokenType.WORD).text()) new ValueExpression(consume(TokenType.WORD).text())
))); )));
} }
final List<Expression> indices = variableSuffix(); final List<Node> indices = variableSuffix();
if (indices == null || indices.isEmpty()) { if (indices == null || indices.isEmpty()) {
return strExpr; return strExpr;
} }

View File

@ -1,6 +1,6 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
public record Argument(String name, Expression valueExpr) { public record Argument(String name, Node valueExpr) {
public Argument(String name) { public Argument(String name) {
this(name, null); this(name, null);

View File

@ -22,7 +22,7 @@ public final class Arguments implements Iterable<Argument>, SourceLocation {
requiredArgumentsCount++; requiredArgumentsCount++;
} }
public void addOptional(String name, Expression expr) { public void addOptional(String name, Node expr) {
arguments.add(new Argument(name, expr)); arguments.add(new Argument(name, expr));
} }

View File

@ -8,11 +8,11 @@ import java.util.List;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ArrayExpression implements Expression { public final class ArrayExpression implements Node {
public final List<Expression> elements; public final List<Node> elements;
public ArrayExpression(List<Expression> arguments) { public ArrayExpression(List<Node> arguments) {
this.elements = arguments; this.elements = arguments;
} }

View File

@ -6,22 +6,17 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class AssignmentExpression extends InterruptableNode implements Expression, Statement { public final class AssignmentExpression extends InterruptableNode implements Statement {
public final Accessible target; public final Accessible target;
public final BinaryExpression.Operator operation; public final BinaryExpression.Operator operation;
public final Expression expression; public final Node expression;
public AssignmentExpression(BinaryExpression.Operator operation, Accessible target, Expression expr) { public AssignmentExpression(BinaryExpression.Operator operation, Accessible target, Node expr) {
this.operation = operation; this.operation = operation;
this.target = target; this.target = target;
this.expression = expr; this.expression = expr;
} }
@Override
public void execute() {
eval();
}
@Override @Override
public Value eval() { public Value eval() {
@ -30,8 +25,8 @@ public final class AssignmentExpression extends InterruptableNode implements Exp
// Simple assignment // Simple assignment
return target.set(expression.eval()); return target.set(expression.eval());
} }
final Expression expr1 = new ValueExpression(target.get()); final Node expr1 = new ValueExpression(target.get());
final Expression expr2 = new ValueExpression(expression.eval()); final Node expr2 = new ValueExpression(expression.eval());
return target.set(new BinaryExpression(operation, expr1, expr2).eval()); return target.set(new BinaryExpression(operation, expr1, expr2).eval());
} }

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.*;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class BinaryExpression implements Expression { public final class BinaryExpression implements Node {
public enum Operator { public enum Operator {
ADD("+"), ADD("+"),
@ -45,9 +45,9 @@ public final class BinaryExpression implements Expression {
} }
public final Operator operation; public final Operator operation;
public final Expression expr1, expr2; public final Node expr1, expr2;
public BinaryExpression(Operator operation, Expression expr1, Expression expr2) { public BinaryExpression(Operator operation, Node expr1, Node expr2) {
this.operation = operation; this.operation = operation;
this.expr1 = expr1; this.expr1 = expr1;
this.expr2 = expr2; this.expr2 = expr2;

View File

@ -1,6 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -10,22 +12,23 @@ import java.util.List;
*/ */
public final class BlockStatement extends InterruptableNode implements Statement { public final class BlockStatement extends InterruptableNode implements Statement {
public final List<Statement> statements; public final List<Node> statements;
public BlockStatement() { public BlockStatement() {
statements = new ArrayList<>(); statements = new ArrayList<>();
} }
public void add(Statement statement) { public void add(Node statement) {
statements.add(statement); statements.add(statement);
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
for (Statement statement : statements) { for (Node statement : statements) {
statement.execute(); statement.eval();
} }
return NumberValue.ZERO;
} }
@Override @Override
@ -41,7 +44,7 @@ public final class BlockStatement extends InterruptableNode implements Statement
@Override @Override
public String toString() { public String toString() {
final StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
for (Statement statement : statements) { for (Node statement : statements) {
result.append(statement.toString()).append(Console.newline()); result.append(statement.toString()).append(Console.newline());
} }
return result.toString(); return result.toString();

View File

@ -1,5 +1,7 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -7,7 +9,7 @@ package com.annimon.ownlang.parser.ast;
public final class BreakStatement extends RuntimeException implements Statement { public final class BreakStatement extends RuntimeException implements Statement {
@Override @Override
public void execute() { public Value eval() {
throw this; throw this;
} }

View File

@ -1,6 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.ClassDeclarations; import com.annimon.ownlang.lib.ClassDeclarations;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -25,8 +27,9 @@ public final class ClassDeclarationStatement implements Statement {
} }
@Override @Override
public void execute() { public Value eval() {
ClassDeclarations.set(name, this); ClassDeclarations.set(name, this);
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -9,7 +9,7 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ConditionalExpression implements Expression { public final class ConditionalExpression implements Node {
public enum Operator { public enum Operator {
EQUALS("=="), EQUALS("=="),
@ -36,10 +36,10 @@ public final class ConditionalExpression implements Expression {
} }
} }
public final Expression expr1, expr2; public final Node expr1, expr2;
public final Operator operation; public final Operator operation;
public ConditionalExpression(Operator operation, Expression expr1, Expression expr2) { public ConditionalExpression(Operator operation, Node expr1, Node expr2) {
this.operation = operation; this.operation = operation;
this.expr1 = expr1; this.expr1 = expr1;
this.expr2 = expr2; this.expr2 = expr2;

View File

@ -9,20 +9,20 @@ import java.util.regex.Pattern;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ContainerAccessExpression implements Expression, Accessible { public final class ContainerAccessExpression implements Node, Accessible {
private static final Pattern PATTERN_SIMPLE_INDEX = Pattern.compile("^\"[a-zA-Z$_]\\w*\""); private static final Pattern PATTERN_SIMPLE_INDEX = Pattern.compile("^\"[a-zA-Z$_]\\w*\"");
public final Expression root; public final Node root;
public final List<Expression> indices; public final List<Node> indices;
private final boolean[] simpleIndices; private final boolean[] simpleIndices;
private final boolean rootIsVariable; private final boolean rootIsVariable;
public ContainerAccessExpression(String variable, List<Expression> indices) { public ContainerAccessExpression(String variable, List<Node> indices) {
this(new VariableExpression(variable), indices); this(new VariableExpression(variable), indices);
} }
public ContainerAccessExpression(Expression root, List<Expression> indices) { public ContainerAccessExpression(Node root, List<Node> indices) {
rootIsVariable = root instanceof VariableExpression; rootIsVariable = root instanceof VariableExpression;
this.root = root; this.root = root;
this.indices = indices; this.indices = indices;
@ -33,7 +33,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
return rootIsVariable; return rootIsVariable;
} }
public Expression getRoot() { public Node getRoot() {
return root; return root;
} }
@ -110,7 +110,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
private boolean[] precomputeSimpleIndices() { private boolean[] precomputeSimpleIndices() {
final boolean[] result = new boolean[indices.size()]; final boolean[] result = new boolean[indices.size()];
int i = 0; int i = 0;
for (Expression index : indices) { for (Node index : indices) {
String indexStr = index.toString(); String indexStr = index.toString();
result[i] = PATTERN_SIMPLE_INDEX.matcher(indexStr).matches(); result[i] = PATTERN_SIMPLE_INDEX.matcher(indexStr).matches();
i++; i++;
@ -122,7 +122,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
public String toString() { public String toString() {
final var sb = new StringBuilder(root.toString()); final var sb = new StringBuilder(root.toString());
int i = 0; int i = 0;
for (Expression index : indices) { for (Node index : indices) {
String indexStr = index.toString(); String indexStr = index.toString();
if (simpleIndices[i]) { if (simpleIndices[i]) {
sb.append('.').append(indexStr, 1, indexStr.length() - 1); sb.append('.').append(indexStr, 1, indexStr.length() - 1);

View File

@ -1,5 +1,7 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -7,7 +9,7 @@ package com.annimon.ownlang.parser.ast;
public final class ContinueStatement extends RuntimeException implements Statement { public final class ContinueStatement extends RuntimeException implements Statement {
@Override @Override
public void execute() { public Value eval() {
throw this; throw this;
} }

View File

@ -13,21 +13,22 @@ import java.util.Map;
public final class DestructuringAssignmentStatement extends InterruptableNode implements Statement { public final class DestructuringAssignmentStatement extends InterruptableNode implements Statement {
public final List<String> variables; public final List<String> variables;
public final Expression containerExpression; public final Node containerExpression;
public DestructuringAssignmentStatement(List<String> arguments, Expression container) { public DestructuringAssignmentStatement(List<String> arguments, Node container) {
this.variables = arguments; this.variables = arguments;
this.containerExpression = container; this.containerExpression = container;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
final Value container = containerExpression.eval(); final Value container = containerExpression.eval();
switch (container.type()) { switch (container.type()) {
case Types.ARRAY -> execute((ArrayValue) container); case Types.ARRAY -> execute((ArrayValue) container);
case Types.MAP -> execute((MapValue) container); case Types.MAP -> execute((MapValue) container);
} }
return NumberValue.ZERO;
} }
private void execute(ArrayValue array) { private void execute(ArrayValue array) {

View File

@ -1,25 +1,28 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class DoWhileStatement extends InterruptableNode implements Statement { public final class DoWhileStatement extends InterruptableNode implements Statement {
public final Expression condition; public final Node condition;
public final Statement statement; public final Statement statement;
public DoWhileStatement(Expression condition, Statement statement) { public DoWhileStatement(Node condition, Statement statement) {
this.condition = condition; this.condition = condition;
this.statement = statement; this.statement = statement;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
do { do {
try { try {
statement.execute(); statement.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
@ -27,6 +30,7 @@ public final class DoWhileStatement extends InterruptableNode implements Stateme
} }
} }
while (condition.eval().asInt() != 0); while (condition.eval().asInt() != 0);
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -7,22 +7,17 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ExprStatement extends InterruptableNode implements Expression, Statement { public final class ExprStatement extends InterruptableNode implements Statement {
public final Expression expr; public final Node expr;
public ExprStatement(Expression function) { public ExprStatement(Node function) {
this.expr = function; this.expr = function;
} }
@Override
public void execute() {
super.interruptionCheck();
expr.eval();
}
@Override @Override
public Value eval() { public Value eval() {
super.interruptionCheck();
return expr.eval(); return expr.eval();
} }

View File

@ -1,12 +0,0 @@
package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Value;
/**
*
* @author aNNiMON
*/
public interface Expression extends Node {
Value eval();
}

View File

@ -1,5 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
@ -7,11 +10,11 @@ package com.annimon.ownlang.parser.ast;
public final class ForStatement extends InterruptableNode implements Statement { public final class ForStatement extends InterruptableNode implements Statement {
public final Statement initialization; public final Statement initialization;
public final Expression termination; public final Node termination;
public final Statement increment; public final Statement increment;
public final Statement statement; public final Statement statement;
public ForStatement(Statement initialization, Expression termination, Statement increment, Statement block) { public ForStatement(Statement initialization, Node termination, Statement increment, Statement block) {
this.initialization = initialization; this.initialization = initialization;
this.termination = termination; this.termination = termination;
this.increment = increment; this.increment = increment;
@ -19,17 +22,18 @@ public final class ForStatement extends InterruptableNode implements Statement {
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
for (initialization.execute(); termination.eval().asInt() != 0; increment.execute()) { for (initialization.eval(); termination.eval().asInt() != 0; increment.eval()) {
try { try {
statement.execute(); statement.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
// continue; // continue;
} }
} }
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -11,17 +11,17 @@ import java.util.Map;
public final class ForeachArrayStatement extends InterruptableNode implements Statement { public final class ForeachArrayStatement extends InterruptableNode implements Statement {
public final String variable; public final String variable;
public final Expression container; public final Node container;
public final Statement body; public final Statement body;
public ForeachArrayStatement(String variable, Expression container, Statement body) { public ForeachArrayStatement(String variable, Node container, Statement body) {
this.variable = variable; this.variable = variable;
this.container = container; this.container = container;
this.body = body; this.body = body;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
try (final var ignored = ScopeHandler.closeableScope()) { try (final var ignored = ScopeHandler.closeableScope()) {
final Value containerValue = container.eval(); final Value containerValue = container.eval();
@ -32,13 +32,14 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
default -> throw new TypeException("Cannot iterate " + Types.typeToString(containerValue.type())); default -> throw new TypeException("Cannot iterate " + Types.typeToString(containerValue.type()));
} }
} }
return NumberValue.ZERO;
} }
private void iterateString(String str) { private void iterateString(String str) {
for (char ch : str.toCharArray()) { for (char ch : str.toCharArray()) {
ScopeHandler.setVariable(variable, new StringValue(String.valueOf(ch))); ScopeHandler.setVariable(variable, new StringValue(String.valueOf(ch)));
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
@ -51,7 +52,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
for (Value value : containerValue) { for (Value value : containerValue) {
ScopeHandler.setVariable(variable, value); ScopeHandler.setVariable(variable, value);
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
@ -67,7 +68,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
entry.getValue() entry.getValue()
})); }));
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {

View File

@ -11,10 +11,10 @@ import java.util.Map;
public final class ForeachMapStatement extends InterruptableNode implements Statement { public final class ForeachMapStatement extends InterruptableNode implements Statement {
public final String key, value; public final String key, value;
public final Expression container; public final Node container;
public final Statement body; public final Statement body;
public ForeachMapStatement(String key, String value, Expression container, Statement body) { public ForeachMapStatement(String key, String value, Node container, Statement body) {
this.key = key; this.key = key;
this.value = value; this.value = value;
this.container = container; this.container = container;
@ -22,7 +22,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
try (final var ignored = ScopeHandler.closeableScope()) { try (final var ignored = ScopeHandler.closeableScope()) {
final Value containerValue = container.eval(); final Value containerValue = container.eval();
@ -33,6 +33,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
default -> throw new TypeException("Cannot iterate " + Types.typeToString(containerValue.type()) + " as key, value pair"); default -> throw new TypeException("Cannot iterate " + Types.typeToString(containerValue.type()) + " as key, value pair");
} }
} }
return NumberValue.ZERO;
} }
private void iterateString(String str) { private void iterateString(String str) {
@ -40,7 +41,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
ScopeHandler.setVariable(key, new StringValue(String.valueOf(ch))); ScopeHandler.setVariable(key, new StringValue(String.valueOf(ch)));
ScopeHandler.setVariable(value, NumberValue.of(ch)); ScopeHandler.setVariable(value, NumberValue.of(ch));
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
@ -55,7 +56,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
ScopeHandler.setVariable(key, v); ScopeHandler.setVariable(key, v);
ScopeHandler.setVariable(value, NumberValue.of(index++)); ScopeHandler.setVariable(value, NumberValue.of(index++));
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
@ -69,7 +70,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
ScopeHandler.setVariable(key, entry.getKey()); ScopeHandler.setVariable(key, entry.getKey());
ScopeHandler.setVariable(value, entry.getValue()); ScopeHandler.setVariable(value, entry.getValue());
try { try {
body.execute(); body.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {

View File

@ -1,7 +1,9 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.ScopeHandler; import com.annimon.ownlang.lib.ScopeHandler;
import com.annimon.ownlang.lib.UserDefinedFunction; import com.annimon.ownlang.lib.UserDefinedFunction;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.util.Range; import com.annimon.ownlang.util.Range;
import com.annimon.ownlang.util.SourceLocation; import com.annimon.ownlang.util.SourceLocation;
@ -29,8 +31,9 @@ public final class FunctionDefineStatement implements Statement, SourceLocation
} }
@Override @Override
public void execute() { public Value eval() {
ScopeHandler.setFunction(name, new UserDefinedFunction(arguments, body, range)); ScopeHandler.setFunction(name, new UserDefinedFunction(arguments, body, range));
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.*;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class FunctionReferenceExpression extends InterruptableNode implements Expression { public final class FunctionReferenceExpression extends InterruptableNode {
public final String name; public final String name;

View File

@ -13,18 +13,18 @@ import java.util.List;
* @author aNNiMON * @author aNNiMON
*/ */
public final class FunctionalExpression extends InterruptableNode public final class FunctionalExpression extends InterruptableNode
implements Expression, Statement, SourceLocation { implements Statement, SourceLocation {
public final Expression functionExpr; public final Node functionExpr;
public final List<Expression> arguments; public final List<Node> arguments;
private Range range; private Range range;
public FunctionalExpression(Expression functionExpr) { public FunctionalExpression(Node functionExpr) {
this.functionExpr = functionExpr; this.functionExpr = functionExpr;
arguments = new ArrayList<>(); arguments = new ArrayList<>();
} }
public void addArgument(Expression arg) { public void addArgument(Node arg) {
arguments.add(arg); arguments.add(arg);
} }
@ -36,11 +36,6 @@ public final class FunctionalExpression extends InterruptableNode
public Range getRange() { public Range getRange() {
return range; return range;
} }
@Override
public void execute() {
eval();
}
@Override @Override
public Value eval() { public Value eval() {
@ -57,7 +52,7 @@ public final class FunctionalExpression extends InterruptableNode
return result; return result;
} }
private Function consumeFunction(Expression expr) { private Function consumeFunction(Node expr) {
final Value value = expr.eval(); final Value value = expr.eval();
if (value.type() == Types.FUNCTION) { if (value.type() == Types.FUNCTION) {
return ((FunctionValue) value).getValue(); return ((FunctionValue) value).getValue();
@ -96,7 +91,7 @@ public final class FunctionalExpression extends InterruptableNode
} else { } else {
sb.append(functionExpr).append('('); sb.append(functionExpr).append('(');
} }
final Iterator<Expression> it = arguments.iterator(); final Iterator<Node> it = arguments.iterator();
if (it.hasNext()) { if (it.hasNext()) {
sb.append(it.next()); sb.append(it.next());
while (it.hasNext()) { while (it.hasNext()) {

View File

@ -1,29 +1,33 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class IfStatement extends InterruptableNode implements Statement { public final class IfStatement extends InterruptableNode implements Statement {
public final Expression expression; public final Node expression;
public final Statement ifStatement, elseStatement; public final Statement ifStatement, elseStatement;
public IfStatement(Expression expression, Statement ifStatement, Statement elseStatement) { public IfStatement(Node expression, Statement ifStatement, Statement elseStatement) {
this.expression = expression; this.expression = expression;
this.ifStatement = ifStatement; this.ifStatement = ifStatement;
this.elseStatement = elseStatement; this.elseStatement = elseStatement;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
final int result = expression.eval().asInt(); final int result = expression.eval().asInt();
if (result != 0) { if (result != 0) {
ifStatement.execute(); ifStatement.eval();
} else if (elseStatement != null) { } else if (elseStatement != null) {
elseStatement.execute(); elseStatement.eval();
} }
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -2,6 +2,8 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.exceptions.OwnLangParserException; import com.annimon.ownlang.exceptions.OwnLangParserException;
import com.annimon.ownlang.exceptions.OwnLangRuntimeException; import com.annimon.ownlang.exceptions.OwnLangRuntimeException;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage; import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage;
import com.annimon.ownlang.stages.*; import com.annimon.ownlang.stages.*;
import com.annimon.ownlang.util.input.InputSourceFile; import com.annimon.ownlang.util.input.InputSourceFile;
@ -13,14 +15,14 @@ import com.annimon.ownlang.util.input.SourceLoaderStage;
*/ */
public final class IncludeStatement extends InterruptableNode implements Statement { public final class IncludeStatement extends InterruptableNode implements Statement {
public final Expression expression; public final Node expression;
public IncludeStatement(Expression expression) { public IncludeStatement(Node expression) {
this.expression = expression; this.expression = expression;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
final var stagesData = new StagesDataMap(); final var stagesData = new StagesDataMap();
@ -37,6 +39,7 @@ public final class IncludeStatement extends InterruptableNode implements Stateme
.perform(stagesData, ex.getParseErrors()); .perform(stagesData, ex.getParseErrors());
throw new OwnLangRuntimeException(error, ex); throw new OwnLangRuntimeException(error, ex);
} }
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -9,11 +9,11 @@ import java.util.Map;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class MapExpression implements Expression { public final class MapExpression implements Node {
public final Map<Expression, Expression> elements; public final Map<Node, Node> elements;
public MapExpression(Map<Expression, Expression> arguments) { public MapExpression(Map<Node, Node> arguments) {
this.elements = arguments; this.elements = arguments;
} }
@ -21,7 +21,7 @@ public final class MapExpression implements Expression {
public Value eval() { public Value eval() {
final int size = elements.size(); final int size = elements.size();
final MapValue map = new MapValue(size); final MapValue map = new MapValue(size);
for (Map.Entry<Expression, Expression> entry : elements.entrySet()) { for (Map.Entry<Node, Node> entry : elements.entrySet()) {
map.set(entry.getKey().eval(), entry.getValue().eval()); map.set(entry.getKey().eval(), entry.getValue().eval());
} }
return map; return map;
@ -41,9 +41,9 @@ public final class MapExpression implements Expression {
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append('{'); sb.append('{');
Iterator<Map.Entry<Expression, Expression>> it = elements.entrySet().iterator(); Iterator<Map.Entry<Node, Node>> it = elements.entrySet().iterator();
if (it.hasNext()) { if (it.hasNext()) {
Map.Entry<Expression, Expression> entry = it.next(); Map.Entry<Node, Node> entry = it.next();
sb.append(entry.getKey()).append(" : ").append(entry.getValue()); sb.append(entry.getKey()).append(" : ").append(entry.getValue());
while (it.hasNext()) { while (it.hasNext()) {
entry = it.next(); entry = it.next();

View File

@ -11,21 +11,16 @@ import java.util.List;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class MatchExpression extends InterruptableNode implements Expression, Statement { public final class MatchExpression extends InterruptableNode implements Statement {
public final Expression expression; public final Node expression;
public final List<Pattern> patterns; public final List<Pattern> patterns;
public MatchExpression(Expression expression, List<Pattern> patterns) { public MatchExpression(Node expression, List<Pattern> patterns) {
this.expression = expression; this.expression = expression;
this.patterns = patterns; this.patterns = patterns;
} }
@Override
public void execute() {
eval();
}
@Override @Override
public Value eval() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
@ -73,7 +68,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
final int size = array.size(); final int size = array.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
final Expression expr = p.values.get(i); final Node expr = p.values.get(i);
if ( (expr != ANY) && (expr.eval().compareTo(array.get(i)) != 0) ) { if ( (expr != ANY) && (expr.eval().compareTo(array.get(i)) != 0) ) {
return false; return false;
} }
@ -146,7 +141,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
private Value evalResult(Statement s) { private Value evalResult(Statement s) {
try { try {
s.execute(); s.eval();
} catch (ReturnStatement ret) { } catch (ReturnStatement ret) {
return ret.getResult(); return ret.getResult();
} }
@ -176,7 +171,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
public abstract static sealed class Pattern { public abstract static sealed class Pattern {
public Statement result; public Statement result;
public Expression optCondition; public Node optCondition;
@Override @Override
public String toString() { public String toString() {
@ -247,13 +242,13 @@ public final class MatchExpression extends InterruptableNode implements Expressi
} }
public static final class TuplePattern extends Pattern { public static final class TuplePattern extends Pattern {
public final List<Expression> values; public final List<Node> values;
public TuplePattern() { public TuplePattern() {
this(new ArrayList<>()); this(new ArrayList<>());
} }
public TuplePattern(List<Expression> parts) { public TuplePattern(List<Node> parts) {
this.values = parts; this.values = parts;
} }
@ -261,13 +256,13 @@ public final class MatchExpression extends InterruptableNode implements Expressi
values.add(ANY); values.add(ANY);
} }
public void add(Expression value) { public void add(Node value) {
values.add(value); values.add(value);
} }
@Override @Override
public String toString() { public String toString() {
final Iterator<Expression> it = values.iterator(); final Iterator<Node> it = values.iterator();
if (it.hasNext()) { if (it.hasNext()) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append('(').append(it.next()); sb.append('(').append(it.next());
@ -281,7 +276,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
} }
} }
public static final Expression ANY = new Expression() { public static final Node ANY = new Node() {
@Override @Override
public Value eval() { public Value eval() {
return NumberValue.ONE; return NumberValue.ONE;

View File

@ -1,10 +1,14 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
*/ */
public interface Node { public interface Node {
Value eval();
void accept(Visitor visitor); void accept(Visitor visitor);

View File

@ -7,13 +7,13 @@ import com.annimon.ownlang.util.SourceLocation;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public final class ObjectCreationExpression implements Expression, SourceLocation { public final class ObjectCreationExpression implements Node, SourceLocation {
public final String className; public final String className;
public final List<Expression> constructorArguments; public final List<Node> constructorArguments;
private Range range; private Range range;
public ObjectCreationExpression(String className, List<Expression> constructorArguments) { public ObjectCreationExpression(String className, List<Node> constructorArguments) {
this.className = className; this.className = className;
this.constructorArguments = constructorArguments; this.constructorArguments = constructorArguments;
} }
@ -80,7 +80,7 @@ public final class ObjectCreationExpression implements Expression, SourceLocatio
public String toString() { public String toString() {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("new ").append(className).append(' '); sb.append("new ").append(className).append(' ');
final Iterator<Expression> it = constructorArguments.iterator(); final Iterator<Node> it = constructorArguments.iterator();
if (it.hasNext()) { if (it.hasNext()) {
sb.append(it.next()); sb.append(it.next());
while (it.hasNext()) { while (it.hasNext()) {

View File

@ -1,6 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
@ -8,16 +10,17 @@ import com.annimon.ownlang.Console;
*/ */
public final class PrintStatement extends InterruptableNode implements Statement { public final class PrintStatement extends InterruptableNode implements Statement {
public final Expression expression; public final Node expression;
public PrintStatement(Expression expression) { public PrintStatement(Node expression) {
this.expression = expression; this.expression = expression;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
Console.print(expression.eval().asString()); Console.print(expression.eval().asString());
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -1,6 +1,8 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
@ -8,16 +10,17 @@ import com.annimon.ownlang.Console;
*/ */
public final class PrintlnStatement extends InterruptableNode implements Statement { public final class PrintlnStatement extends InterruptableNode implements Statement {
public final Expression expression; public final Node expression;
public PrintlnStatement(Expression expression) { public PrintlnStatement(Node expression) {
this.expression = expression; this.expression = expression;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
Console.println(expression.eval().asString()); Console.println(expression.eval().asString());
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -8,10 +8,10 @@ import com.annimon.ownlang.lib.Value;
*/ */
public final class ReturnStatement extends RuntimeException implements Statement { public final class ReturnStatement extends RuntimeException implements Statement {
public final Expression expression; public final Node expression;
private Value result; private Value result;
public ReturnStatement(Expression expression) { public ReturnStatement(Node expression) {
this.expression = expression; this.expression = expression;
} }
@ -20,7 +20,7 @@ public final class ReturnStatement extends RuntimeException implements Statement
} }
@Override @Override
public void execute() { public Value eval() {
result = expression.eval(); result = expression.eval();
throw this; throw this;
} }

View File

@ -5,6 +5,5 @@ package com.annimon.ownlang.parser.ast;
* @author aNNiMON * @author aNNiMON
*/ */
public interface Statement extends Node { public interface Statement extends Node {
void execute();
} }

View File

@ -6,12 +6,12 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class TernaryExpression implements Expression { public final class TernaryExpression implements Node {
public final Expression condition; public final Node condition;
public final Expression trueExpr, falseExpr; public final Node trueExpr, falseExpr;
public TernaryExpression(Expression condition, Expression trueExpr, Expression falseExpr) { public TernaryExpression(Node condition, Node trueExpr, Node falseExpr) {
this.condition = condition; this.condition = condition;
this.trueExpr = trueExpr; this.trueExpr = trueExpr;
this.falseExpr = falseExpr; this.falseExpr = falseExpr;

View File

@ -10,7 +10,7 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class UnaryExpression implements Expression, Statement { public final class UnaryExpression implements Statement {
public enum Operator { public enum Operator {
INCREMENT_PREFIX("++"), INCREMENT_PREFIX("++"),
@ -35,19 +35,14 @@ public final class UnaryExpression implements Expression, Statement {
} }
} }
public final Expression expr1; public final Node expr1;
public final Operator operation; public final Operator operation;
public UnaryExpression(Operator operation, Expression expr1) { public UnaryExpression(Operator operation, Node expr1) {
this.operation = operation; this.operation = operation;
this.expr1 = expr1; this.expr1 = expr1;
} }
@Override
public void execute() {
eval();
}
@Override @Override
public Value eval() { public Value eval() {
final Value value = expr1.eval(); final Value value = expr1.eval();

View File

@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Function; import com.annimon.ownlang.lib.Function;
import com.annimon.ownlang.lib.ModuleLoader; import com.annimon.ownlang.lib.ModuleLoader;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value; import com.annimon.ownlang.lib.Value;
import com.annimon.ownlang.modules.Module; import com.annimon.ownlang.modules.Module;
import java.util.Collection; import java.util.Collection;
@ -20,11 +21,12 @@ public final class UseStatement extends InterruptableNode implements Statement {
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
for (String module : modules) { for (String module : modules) {
ModuleLoader.loadAndUse(module); ModuleLoader.loadAndUse(module);
} }
return NumberValue.ZERO;
} }
public Map<String, Value> loadConstants() { public Map<String, Value> loadConstants() {

View File

@ -11,7 +11,7 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ValueExpression extends InterruptableNode implements Expression { public final class ValueExpression extends InterruptableNode {
public final Value value; public final Value value;

View File

@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.Value;
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class VariableExpression extends InterruptableNode implements Expression, Accessible { public final class VariableExpression extends InterruptableNode implements Accessible {
public final String name; public final String name;
@ -24,7 +24,9 @@ public final class VariableExpression extends InterruptableNode implements Expre
@Override @Override
public Value get() { public Value get() {
if (!ScopeHandler.isVariableOrConstantExists(name)) throw new VariableDoesNotExistsException(name); if (!ScopeHandler.isVariableOrConstantExists(name)) {
throw new VariableDoesNotExistsException(name);
}
return ScopeHandler.getVariableOrConstant(name); return ScopeHandler.getVariableOrConstant(name);
} }

View File

@ -1,31 +1,35 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.Value;
/** /**
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class WhileStatement extends InterruptableNode implements Statement { public final class WhileStatement extends InterruptableNode implements Statement {
public final Expression condition; public final Node condition;
public final Statement statement; public final Statement statement;
public WhileStatement(Expression condition, Statement statement) { public WhileStatement(Node condition, Statement statement) {
this.condition = condition; this.condition = condition;
this.statement = statement; this.statement = statement;
} }
@Override @Override
public void execute() { public Value eval() {
super.interruptionCheck(); super.interruptionCheck();
while (condition.eval().asInt() != 0) { while (condition.eval().asInt() != 0) {
try { try {
statement.execute(); statement.eval();
} catch (BreakStatement bs) { } catch (BreakStatement bs) {
break; break;
} catch (ContinueStatement cs) { } catch (ContinueStatement cs) {
// continue; // continue;
} }
} }
return NumberValue.ZERO;
} }
@Override @Override

View File

@ -1,7 +1,7 @@
package com.annimon.ownlang.parser.linters; package com.annimon.ownlang.parser.linters;
import com.annimon.ownlang.parser.ast.IncludeStatement; import com.annimon.ownlang.parser.ast.IncludeStatement;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Visitor; import com.annimon.ownlang.parser.ast.Visitor;
import com.annimon.ownlang.parser.visitors.AbstractVisitor; import com.annimon.ownlang.parser.visitors.AbstractVisitor;
import com.annimon.ownlang.parser.visitors.VisitorUtils; import com.annimon.ownlang.parser.visitors.VisitorUtils;
@ -15,7 +15,7 @@ abstract class LintVisitor extends AbstractVisitor {
} }
protected void applyVisitor(IncludeStatement s, Visitor visitor) { protected void applyVisitor(IncludeStatement s, Visitor visitor) {
final Statement program = VisitorUtils.includeProgram(s); final Node program = VisitorUtils.includeProgram(s);
if (program != null) { if (program != null) {
program.accept(visitor); program.accept(visitor);
} }

View File

@ -2,7 +2,7 @@ package com.annimon.ownlang.parser.linters;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.lib.ScopeHandler; import com.annimon.ownlang.lib.ScopeHandler;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Visitor; import com.annimon.ownlang.parser.ast.Visitor;
import com.annimon.ownlang.stages.Stage; import com.annimon.ownlang.stages.Stage;
import com.annimon.ownlang.stages.StagesData; import com.annimon.ownlang.stages.StagesData;
@ -10,10 +10,10 @@ import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
public class LinterStage implements Stage<Statement, Statement> { public class LinterStage implements Stage<Node, Node> {
@Override @Override
public Statement perform(StagesData stagesData, Statement input) { public Node perform(StagesData stagesData, Node input) {
final List<LinterResult> results = new ArrayList<>(); final List<LinterResult> results = new ArrayList<>();
final Visitor[] validators = new Visitor[] { final Visitor[] validators = new Visitor[] {
new AssignValidator(results), new AssignValidator(results),

View File

@ -4,7 +4,6 @@ import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.parser.ast.AssignmentExpression; import com.annimon.ownlang.parser.ast.AssignmentExpression;
import com.annimon.ownlang.parser.ast.BlockStatement; import com.annimon.ownlang.parser.ast.BlockStatement;
import com.annimon.ownlang.parser.ast.ExprStatement; import com.annimon.ownlang.parser.ast.ExprStatement;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.IfStatement; import com.annimon.ownlang.parser.ast.IfStatement;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Statement;
@ -123,7 +122,7 @@ public class DeadCodeElimination extends OptimizationVisitor<Map<String, Variabl
public Node visit(BlockStatement s, Map<String, VariableInfo> t) { public Node visit(BlockStatement s, Map<String, VariableInfo> t) {
final BlockStatement result = new BlockStatement(); final BlockStatement result = new BlockStatement();
boolean changed = false; boolean changed = false;
for (Statement statement : s.statements) { for (Node statement : s.statements) {
final Node node = statement.accept(this, t); final Node node = statement.accept(this, t);
if (node != statement) { if (node != statement) {
changed = true; changed = true;
@ -135,8 +134,8 @@ public class DeadCodeElimination extends OptimizationVisitor<Map<String, Variabl
if (node instanceof Statement stmt) { if (node instanceof Statement stmt) {
result.add(stmt); result.add(stmt);
} else if (node instanceof Expression expr) { } else if (node != null) {
result.add(new ExprStatement(expr)); result.add(new ExprStatement(node));
} }
} }
if (changed) { if (changed) {

View File

@ -2,11 +2,9 @@ package com.annimon.ownlang.parser.optimization;
import com.annimon.ownlang.Console; import com.annimon.ownlang.Console;
import com.annimon.ownlang.parser.ast.BlockStatement; import com.annimon.ownlang.parser.ast.BlockStatement;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.PrintStatement; import com.annimon.ownlang.parser.ast.PrintStatement;
import com.annimon.ownlang.parser.ast.PrintlnStatement; import com.annimon.ownlang.parser.ast.PrintlnStatement;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.ValueExpression; import com.annimon.ownlang.parser.ast.ValueExpression;
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isConstantValue; import static com.annimon.ownlang.parser.visitors.VisitorUtils.isConstantValue;
@ -48,8 +46,8 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
final BlockStatement result = new BlockStatement(); final BlockStatement result = new BlockStatement();
int i; int i;
for (i = 1; i < size; i++) { for (i = 1; i < size; i++) {
Statement s1 = s.statements.get(i - 1); Node s1 = s.statements.get(i - 1);
Statement s2 = s.statements.get(i); Node s2 = s.statements.get(i);
Node n1 = s1.accept(this, t); Node n1 = s1.accept(this, t);
Node n2 = s2.accept(this, t); Node n2 = s2.accept(this, t);
if (n1 != s1 || n2 != s2) { if (n1 != s1 || n2 != s2) {
@ -57,7 +55,7 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
} }
final Node combined = tryCombine(n1, n2); final Node combined = tryCombine(n1, n2);
if (combined == null) { if (combined == null) {
result.add((Statement) n1); result.add(n1);
} else { } else {
changed = true; changed = true;
result.add(consumeStatement(combined)); result.add(consumeStatement(combined));
@ -66,12 +64,12 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
} }
if (i == size) { if (i == size) {
// Last node // Last node
Statement s2 = s.statements.get(size - 1); Node s2 = s.statements.get(size - 1);
Node n2 = s2.accept(this, t); Node n2 = s2.accept(this, t);
if (n2 != s2) { if (n2 != s2) {
changed = true; changed = true;
} }
result.add((Statement) n2); result.add(n2);
} }
if (changed) { if (changed) {
return result; return result;
@ -91,10 +89,10 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
else n2Type = 0; else n2Type = 0;
if (n1Type != 0 && n2Type != 0) { if (n1Type != 0 && n2Type != 0) {
final Expression e1 = (n1Type == 1) final Node e1 = (n1Type == 1)
? ((PrintStatement) n1).expression ? ((PrintStatement) n1).expression
: ((PrintlnStatement) n1).expression; : ((PrintlnStatement) n1).expression;
final Expression e2 = (n2Type == 1) final Node e2 = (n2Type == 1)
? ((PrintStatement) n2).expression ? ((PrintStatement) n2).expression
: ((PrintlnStatement) n2).expression; : ((PrintlnStatement) n2).expression;
if (isConstantValue(e1) && isConstantValue(e2)) { if (isConstantValue(e1) && isConstantValue(e2)) {

View File

@ -1,11 +1,10 @@
package com.annimon.ownlang.parser.optimization; package com.annimon.ownlang.parser.optimization;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.stages.Stage; import com.annimon.ownlang.stages.Stage;
import com.annimon.ownlang.stages.StagesData; import com.annimon.ownlang.stages.StagesData;
public class OptimizationStage implements Stage<Statement, Statement> { public class OptimizationStage implements Stage<Node, Node> {
public static final String TAG_OPTIMIZATION_SUMMARY = "optimizationSummary"; public static final String TAG_OPTIMIZATION_SUMMARY = "optimizationSummary";
@ -30,7 +29,7 @@ public class OptimizationStage implements Stage<Statement, Statement> {
} }
@Override @Override
public Statement perform(StagesData stagesData, Statement input) { public Node perform(StagesData stagesData, Node input) {
if (level == 0) return input; if (level == 0) return input;
Node result = input; Node result = input;
@ -51,6 +50,6 @@ public class OptimizationStage implements Stage<Statement, Statement> {
); );
} }
return (Statement) result; return result;
} }
} }

View File

@ -14,14 +14,14 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
@Override @Override
public Node visit(ArrayExpression s, T t) { public Node visit(ArrayExpression s, T t) {
final List<Expression> elements = new ArrayList<>(s.elements.size()); final List<Node> elements = new ArrayList<>(s.elements.size());
boolean changed = false; boolean changed = false;
for (Expression expression : s.elements) { for (Node expression : s.elements) {
final Node node = expression.accept(this, t); final Node node = expression.accept(this, t);
if (node != expression) { if (node != expression) {
changed = true; changed = true;
} }
elements.add((Expression) node); elements.add(node);
} }
if (changed) { if (changed) {
return new ArrayExpression(elements); return new ArrayExpression(elements);
@ -34,7 +34,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node exprNode = s.expression.accept(this, t); final Node exprNode = s.expression.accept(this, t);
final Node targetNode = s.target.accept(this, t); final Node targetNode = s.target.accept(this, t);
if ( (exprNode != s.expression || targetNode != s.target) && (targetNode instanceof Accessible) ) { if ( (exprNode != s.expression || targetNode != s.target) && (targetNode instanceof Accessible) ) {
return new AssignmentExpression(s.operation, (Accessible) targetNode, (Expression) exprNode); return new AssignmentExpression(s.operation, (Accessible) targetNode, exprNode);
} }
return s; return s;
} }
@ -44,7 +44,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node expr1 = s.expr1.accept(this, t); final Node expr1 = s.expr1.accept(this, t);
final Node expr2 = s.expr2.accept(this, t); final Node expr2 = s.expr2.accept(this, t);
if (expr1 != s.expr1 || expr2 != s.expr2) { if (expr1 != s.expr1 || expr2 != s.expr2) {
return new BinaryExpression(s.operation, (Expression) expr1, (Expression) expr2); return new BinaryExpression(s.operation, expr1, expr2);
} }
return s; return s;
} }
@ -53,15 +53,13 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(BlockStatement s, T t) { public Node visit(BlockStatement s, T t) {
boolean changed = false; boolean changed = false;
final BlockStatement result = new BlockStatement(); final BlockStatement result = new BlockStatement();
for (Statement statement : s.statements) { for (Node statement : s.statements) {
final Node node = statement.accept(this, t); final Node node = statement.accept(this, t);
if (node != statement) { if (node != statement) {
changed = true; changed = true;
} }
if (node instanceof Statement) { if (node != null) {
result.add((Statement) node); result.add(consumeStatement(node));
} else if (node instanceof Expression) {
result.add(new ExprStatement((Expression) node));
} }
} }
if (changed) { if (changed) {
@ -85,7 +83,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node expr1 = s.expr1.accept(this, t); final Node expr1 = s.expr1.accept(this, t);
final Node expr2 = s.expr2.accept(this, t); final Node expr2 = s.expr2.accept(this, t);
if (expr1 != s.expr1 || expr2 != s.expr2) { if (expr1 != s.expr1 || expr2 != s.expr2) {
return new ConditionalExpression(s.operation, (Expression) expr1, (Expression) expr2); return new ConditionalExpression(s.operation, expr1, expr2);
} }
return s; return s;
} }
@ -95,16 +93,16 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node root = s.root.accept(this, t); final Node root = s.root.accept(this, t);
boolean changed = (root != s.root); boolean changed = (root != s.root);
final List<Expression> indices = new ArrayList<>(s.indices.size()); final List<Node> indices = new ArrayList<>(s.indices.size());
for (Expression expression : s.indices) { for (Node expression : s.indices) {
final Node node = expression.accept(this, t); final Node node = expression.accept(this, t);
if (node != expression) { if (node != expression) {
changed = true; changed = true;
} }
indices.add((Expression) node); indices.add(node);
} }
if (changed) { if (changed) {
return new ContainerAccessExpression((Expression) root, indices); return new ContainerAccessExpression(root, indices);
} }
return s; return s;
} }
@ -119,7 +117,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node condition = s.condition.accept(this, t); final Node condition = s.condition.accept(this, t);
final Node statement = s.statement.accept(this, t); final Node statement = s.statement.accept(this, t);
if (condition != s.condition || statement != s.statement) { if (condition != s.condition || statement != s.statement) {
return new DoWhileStatement((Expression) condition, consumeStatement(statement)); return new DoWhileStatement(condition, consumeStatement(statement));
} }
return s; return s;
} }
@ -128,7 +126,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(DestructuringAssignmentStatement s, T t) { public Node visit(DestructuringAssignmentStatement s, T t) {
final Node expr = s.containerExpression.accept(this, t); final Node expr = s.containerExpression.accept(this, t);
if (expr != s.containerExpression) { if (expr != s.containerExpression) {
return new DestructuringAssignmentStatement(s.variables, (Expression) expr); return new DestructuringAssignmentStatement(s.variables, expr);
} }
return s; return s;
} }
@ -142,7 +140,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
if (initialization != s.initialization || termination != s.termination if (initialization != s.initialization || termination != s.termination
|| increment != s.increment || statement != s.statement) { || increment != s.increment || statement != s.statement) {
return new ForStatement(consumeStatement(initialization), return new ForStatement(consumeStatement(initialization),
(Expression) termination, consumeStatement(increment), consumeStatement(statement)); termination, consumeStatement(increment), consumeStatement(statement));
} }
return s; return s;
} }
@ -152,7 +150,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node container = s.container.accept(this, t); final Node container = s.container.accept(this, t);
final Node body = s.body.accept(this, t); final Node body = s.body.accept(this, t);
if (container != s.container || body != s.body) { if (container != s.container || body != s.body) {
return new ForeachArrayStatement(s.variable, (Expression) container, consumeStatement(body)); return new ForeachArrayStatement(s.variable, container, consumeStatement(body));
} }
return s; return s;
} }
@ -162,7 +160,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node container = s.container.accept(this, t); final Node container = s.container.accept(this, t);
final Node body = s.body.accept(this, t); final Node body = s.body.accept(this, t);
if (container != s.container || body != s.body) { if (container != s.container || body != s.body) {
return new ForeachMapStatement(s.key, s.value, (Expression) container, consumeStatement(body)); return new ForeachMapStatement(s.key, s.value, container, consumeStatement(body));
} }
return s; return s;
} }
@ -188,7 +186,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(ExprStatement s, T t) { public Node visit(ExprStatement s, T t) {
final Node expr = s.expr.accept(this, t); final Node expr = s.expr.accept(this, t);
if (expr != s.expr) { if (expr != s.expr) {
return new ExprStatement((Expression) expr); return new ExprStatement(expr);
} }
return s; return s;
} }
@ -196,14 +194,14 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
@Override @Override
public Node visit(FunctionalExpression s, T t) { public Node visit(FunctionalExpression s, T t) {
final Node functionExpr = s.functionExpr.accept(this, t); final Node functionExpr = s.functionExpr.accept(this, t);
final FunctionalExpression result = new FunctionalExpression((Expression) functionExpr); final FunctionalExpression result = new FunctionalExpression(functionExpr);
boolean changed = functionExpr != s.functionExpr; boolean changed = functionExpr != s.functionExpr;
for (Expression argument : s.arguments) { for (Node argument : s.arguments) {
final Node expr = argument.accept(this, t); final Node expr = argument.accept(this, t);
if (expr != argument) { if (expr != argument) {
changed = true; changed = true;
} }
result.addArgument((Expression) expr); result.addArgument(expr);
} }
if (changed) { if (changed) {
return result; return result;
@ -222,7 +220,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
elseStatement = null; elseStatement = null;
} }
if (expression != s.expression || ifStatement != s.ifStatement || elseStatement != s.elseStatement) { if (expression != s.expression || ifStatement != s.ifStatement || elseStatement != s.elseStatement) {
return new IfStatement((Expression) expression, consumeStatement(ifStatement), return new IfStatement(expression, consumeStatement(ifStatement),
(elseStatement == null ? null : consumeStatement(elseStatement)) ); (elseStatement == null ? null : consumeStatement(elseStatement)) );
} }
return s; return s;
@ -232,22 +230,22 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(IncludeStatement s, T t) { public Node visit(IncludeStatement s, T t) {
final Node expression = s.expression.accept(this, t); final Node expression = s.expression.accept(this, t);
if (expression != s.expression) { if (expression != s.expression) {
return new IncludeStatement((Expression) expression); return new IncludeStatement(expression);
} }
return s; return s;
} }
@Override @Override
public Node visit(MapExpression s, T t) { public Node visit(MapExpression s, T t) {
final Map<Expression, Expression> elements = new HashMap<>(s.elements.size()); final Map<Node, Node> elements = new HashMap<>(s.elements.size());
boolean changed = false; boolean changed = false;
for (Map.Entry<Expression, Expression> entry : s.elements.entrySet()) { for (Map.Entry<Node, Node> entry : s.elements.entrySet()) {
final Node key = entry.getKey().accept(this, t); final Node key = entry.getKey().accept(this, t);
final Node value = entry.getValue().accept(this, t); final Node value = entry.getValue().accept(this, t);
if (key != entry.getKey() || value != entry.getValue()) { if (key != entry.getKey() || value != entry.getValue()) {
changed = true; changed = true;
} }
elements.put((Expression) key, (Expression) value); elements.put(key, value);
} }
if (changed) { if (changed) {
return new MapExpression(elements); return new MapExpression(elements);
@ -268,7 +266,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
if ((node != expr) && isValue(node)) { if ((node != expr) && isValue(node)) {
changed = true; changed = true;
final Value value = ((ValueExpression) node).value; final Value value = ((ValueExpression) node).value;
final Expression optCondition = pattern.optCondition; final Node optCondition = pattern.optCondition;
final Statement result = pattern.result; final Statement result = pattern.result;
pattern = new MatchExpression.ConstantPattern(value); pattern = new MatchExpression.ConstantPattern(value);
pattern.optCondition = optCondition; pattern.optCondition = optCondition;
@ -277,21 +275,21 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
} }
if (pattern instanceof MatchExpression.TuplePattern tuple) { if (pattern instanceof MatchExpression.TuplePattern tuple) {
final List<Expression> newValues = new ArrayList<>(tuple.values.size()); final List<Node> newValues = new ArrayList<>(tuple.values.size());
boolean valuesChanged = false; boolean valuesChanged = false;
for (Expression value : tuple.values) { for (Node value : tuple.values) {
if (value != MatchExpression.ANY) { if (value != MatchExpression.ANY) {
final Node node = value.accept(this, t); final Node node = value.accept(this, t);
if (node != value) { if (node != value) {
valuesChanged = true; valuesChanged = true;
value = (Expression) node; value = node;
} }
} }
newValues.add(value); newValues.add(value);
} }
if (valuesChanged) { if (valuesChanged) {
changed = true; changed = true;
final Expression optCondition = pattern.optCondition; final Node optCondition = pattern.optCondition;
final Statement result = pattern.result; final Statement result = pattern.result;
pattern = new MatchExpression.TuplePattern(newValues); pattern = new MatchExpression.TuplePattern(newValues);
pattern.optCondition = optCondition; pattern.optCondition = optCondition;
@ -309,28 +307,28 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
Node optCond = pattern.optCondition.accept(this, t); Node optCond = pattern.optCondition.accept(this, t);
if (optCond != pattern.optCondition) { if (optCond != pattern.optCondition) {
changed = true; changed = true;
pattern.optCondition = (Expression) optCond; pattern.optCondition = optCond;
} }
} }
patterns.add(pattern); patterns.add(pattern);
} }
if (changed) { if (changed) {
return new MatchExpression((Expression) expression, patterns); return new MatchExpression(expression, patterns);
} }
return s; return s;
} }
@Override @Override
public Node visit(ObjectCreationExpression s, T t) { public Node visit(ObjectCreationExpression s, T t) {
final List<Expression> args = new ArrayList<>(); final List<Node> args = new ArrayList<>();
boolean changed = false; boolean changed = false;
for (Expression argument : s.constructorArguments) { for (Node argument : s.constructorArguments) {
final Node expr = argument.accept(this, t); final Node expr = argument.accept(this, t);
if (expr != argument) { if (expr != argument) {
changed = true; changed = true;
} }
args.add((Expression) expr); args.add(expr);
} }
if (changed) { if (changed) {
@ -343,7 +341,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(PrintStatement s, T t) { public Node visit(PrintStatement s, T t) {
final Node expression = s.expression.accept(this, t); final Node expression = s.expression.accept(this, t);
if (expression != s.expression) { if (expression != s.expression) {
return new PrintStatement((Expression) expression); return new PrintStatement(expression);
} }
return s; return s;
} }
@ -352,7 +350,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(PrintlnStatement s, T t) { public Node visit(PrintlnStatement s, T t) {
final Node expression = s.expression.accept(this, t); final Node expression = s.expression.accept(this, t);
if (expression != s.expression) { if (expression != s.expression) {
return new PrintlnStatement((Expression) expression); return new PrintlnStatement(expression);
} }
return s; return s;
} }
@ -361,7 +359,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(ReturnStatement s, T t) { public Node visit(ReturnStatement s, T t) {
final Node expression = s.expression.accept(this, t); final Node expression = s.expression.accept(this, t);
if (expression != s.expression) { if (expression != s.expression) {
return new ReturnStatement((Expression) expression); return new ReturnStatement(expression);
} }
return s; return s;
} }
@ -372,7 +370,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node trueExpr = s.trueExpr.accept(this, t); final Node trueExpr = s.trueExpr.accept(this, t);
final Node falseExpr = s.falseExpr.accept(this, t); final Node falseExpr = s.falseExpr.accept(this, t);
if (condition != s.condition || trueExpr != s.trueExpr || falseExpr != s.falseExpr) { if (condition != s.condition || trueExpr != s.trueExpr || falseExpr != s.falseExpr) {
return new TernaryExpression((Expression) condition, (Expression) trueExpr, (Expression) falseExpr); return new TernaryExpression(condition, trueExpr, falseExpr);
} }
return s; return s;
} }
@ -381,7 +379,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(UnaryExpression s, T t) { public Node visit(UnaryExpression s, T t) {
final Node expr1 = s.expr1.accept(this, t); final Node expr1 = s.expr1.accept(this, t);
if (expr1 != s.expr1) { if (expr1 != s.expr1) {
return new UnaryExpression(s.operation, (Expression) expr1); return new UnaryExpression(s.operation, expr1);
} }
return s; return s;
} }
@ -407,7 +405,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node condition = s.condition.accept(this, t); final Node condition = s.condition.accept(this, t);
final Node statement = s.statement.accept(this, t); final Node statement = s.statement.accept(this, t);
if (condition != s.condition || statement != s.statement) { if (condition != s.condition || statement != s.statement) {
return new WhileStatement((Expression) condition, consumeStatement(statement)); return new WhileStatement(condition, consumeStatement(statement));
} }
return s; return s;
} }
@ -434,7 +432,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
boolean changed = false; boolean changed = false;
out.setRange(in.getRange()); out.setRange(in.getRange());
for (Argument argument : in) { for (Argument argument : in) {
final Expression valueExpr = argument.valueExpr(); final Node valueExpr = argument.valueExpr();
if (valueExpr == null) { if (valueExpr == null) {
out.addRequired(argument.name()); out.addRequired(argument.name());
} else { } else {
@ -442,7 +440,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
if (expr != valueExpr) { if (expr != valueExpr) {
changed = true; changed = true;
} }
out.addOptional(argument.name(), (Expression) expr); out.addOptional(argument.name(), expr);
} }
} }
return changed; return changed;
@ -452,6 +450,6 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
if (node instanceof Statement statement) { if (node instanceof Statement statement) {
return statement; return statement;
} }
return new ExprStatement((Expression) node); return new ExprStatement(node);
} }
} }

View File

@ -110,7 +110,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
final String variableName = argument.name(); final String variableName = argument.name();
grabVariableInfo(t, variableName); grabVariableInfo(t, variableName);
/* No need to add value - it is optional arguments /* No need to add value - it is optional arguments
final Expression expr = argument.getValueExpr(); final Node expr = argument.getValueExpr();
if (expr != null && isValue(expr)) { if (expr != null && isValue(expr)) {
var.value = ((ValueExpression) expr).value; var.value = ((ValueExpression) expr).value;
}*/ }*/

View File

@ -12,7 +12,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(ArrayExpression s) { public void visit(ArrayExpression s) {
for (Expression index : s.elements) { for (Node index : s.elements) {
index.accept(this); index.accept(this);
} }
} }
@ -30,7 +30,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(BlockStatement s) { public void visit(BlockStatement s) {
for (Statement statement : s.statements) { for (Node statement : s.statements) {
statement.accept(this); statement.accept(this);
} }
} }
@ -53,7 +53,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(ContainerAccessExpression s) { public void visit(ContainerAccessExpression s) {
s.root.accept(this); s.root.accept(this);
for (Expression index : s.indices) { for (Node index : s.indices) {
index.accept(this); index.accept(this);
} }
} }
@ -110,7 +110,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(FunctionalExpression s) { public void visit(FunctionalExpression s) {
s.functionExpr.accept(this); s.functionExpr.accept(this);
for (Expression argument : s.arguments) { for (Node argument : s.arguments) {
argument.accept(this); argument.accept(this);
} }
} }
@ -131,7 +131,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(MapExpression s) { public void visit(MapExpression s) {
for (Map.Entry<Expression, Expression> entry : s.elements.entrySet()) { for (Map.Entry<Node, Node> entry : s.elements.entrySet()) {
entry.getKey().accept(this); entry.getKey().accept(this);
entry.getValue().accept(this); entry.getValue().accept(this);
} }
@ -144,7 +144,7 @@ public abstract class AbstractVisitor implements Visitor {
@Override @Override
public void visit(ObjectCreationExpression s) { public void visit(ObjectCreationExpression s) {
for (Expression argument : s.constructorArguments) { for (Node argument : s.constructorArguments) {
argument.accept(this); argument.accept(this);
} }
} }

View File

@ -11,6 +11,6 @@ public final class FunctionAdder extends AbstractVisitor {
@Override @Override
public void visit(FunctionDefineStatement s) { public void visit(FunctionDefineStatement s) {
super.visit(s); super.visit(s);
s.execute(); s.eval();
} }
} }

View File

@ -1,10 +1,7 @@
package com.annimon.ownlang.parser.visitors; package com.annimon.ownlang.parser.visitors;
import com.annimon.ownlang.parser.ast.ArrayExpression; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.UseStatement; import com.annimon.ownlang.parser.ast.UseStatement;
import com.annimon.ownlang.parser.ast.ValueExpression;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -16,7 +13,7 @@ public class ModuleDetector extends AbstractVisitor {
modules = new HashSet<>(); modules = new HashSet<>();
} }
public Set<String> detect(Statement s) { public Set<String> detect(Node s) {
s.accept(this); s.accept(this);
return modules; return modules;
} }

View File

@ -21,7 +21,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
@Override @Override
public StringBuilder visit(ArrayExpression s, StringBuilder t) { public StringBuilder visit(ArrayExpression s, StringBuilder t) {
t.append('['); t.append('[');
final Iterator<Expression> it = s.elements.iterator(); final Iterator<Node> it = s.elements.iterator();
if (it.hasNext()) { if (it.hasNext()) {
it.next().accept(this, t); it.next().accept(this, t);
while (it.hasNext()) { while (it.hasNext()) {
@ -58,7 +58,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
} }
increaseIndent(); increaseIndent();
for (Statement statement : s.statements) { for (Node statement : s.statements) {
newLine(t); newLine(t);
printIndent(t); printIndent(t);
statement.accept(this, t); statement.accept(this, t);
@ -108,7 +108,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
@Override @Override
public StringBuilder visit(ContainerAccessExpression s, StringBuilder t) { public StringBuilder visit(ContainerAccessExpression s, StringBuilder t) {
s.root.accept(this, t); s.root.accept(this, t);
for (Expression index : s.indices) { for (Node index : s.indices) {
t.append('['); t.append('[');
index.accept(this, t); index.accept(this, t);
t.append(']'); t.append(']');
@ -266,7 +266,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
t.append('{'); t.append('{');
increaseIndent(); increaseIndent();
boolean firstElement = true; boolean firstElement = true;
for (Map.Entry<Expression, Expression> entry : s.elements.entrySet()) { for (Map.Entry<Node, Node> entry : s.elements.entrySet()) {
if (firstElement) firstElement = false; if (firstElement) firstElement = false;
else t.append(","); else t.append(",");
newLine(t); newLine(t);
@ -440,10 +440,10 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
return t; return t;
} }
private void printArgs(StringBuilder t, List<Expression> args) { private void printArgs(StringBuilder t, List<Node> args) {
t.append("("); t.append("(");
boolean firstElement = true; boolean firstElement = true;
for (Expression expr : args) { for (Node expr : args) {
if (firstElement) firstElement = false; if (firstElement) firstElement = false;
else t.append(", "); else t.append(", ");
expr.accept(this, t); expr.accept(this, t);

View File

@ -11,7 +11,6 @@ import com.annimon.ownlang.parser.ast.BinaryExpression;
import com.annimon.ownlang.parser.ast.ConditionalExpression; import com.annimon.ownlang.parser.ast.ConditionalExpression;
import com.annimon.ownlang.parser.ast.IncludeStatement; import com.annimon.ownlang.parser.ast.IncludeStatement;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.UnaryExpression; import com.annimon.ownlang.parser.ast.UnaryExpression;
import com.annimon.ownlang.parser.ast.ValueExpression; import com.annimon.ownlang.parser.ast.ValueExpression;
import com.annimon.ownlang.parser.ast.VariableExpression; import com.annimon.ownlang.parser.ast.VariableExpression;
@ -32,7 +31,7 @@ public final class VisitorUtils {
return (node instanceof VariableExpression); return (node instanceof VariableExpression);
} }
public static Statement includeProgram(IncludeStatement s) { public static Node includeProgram(IncludeStatement s) {
if (!isValue(s.expression)) return null; if (!isValue(s.expression)) return null;
try { try {
final String path = s.expression.eval().asString(); final String path = s.expression.eval().asString();

View File

@ -1,12 +1,12 @@
package com.annimon.ownlang.stages; package com.annimon.ownlang.stages;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
public class ExecutionStage implements Stage<Statement, Statement> { public class ExecutionStage implements Stage<Node, Node> {
@Override @Override
public Statement perform(StagesData stagesData, Statement input) { public Node perform(StagesData stagesData, Node input) {
input.execute(); input.eval();
return input; return input;
} }
} }

View File

@ -1,12 +1,12 @@
package com.annimon.ownlang.stages; package com.annimon.ownlang.stages;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.visitors.FunctionAdder; import com.annimon.ownlang.parser.visitors.FunctionAdder;
public class FunctionAddingStage implements Stage<Statement, Statement> { public class FunctionAddingStage implements Stage<Node, Node> {
@Override @Override
public Statement perform(StagesData stagesData, Statement input) { public Node perform(StagesData stagesData, Node input) {
input.accept(new FunctionAdder()); input.accept(new FunctionAdder());
return input; return input;
} }

View File

@ -3,18 +3,18 @@ package com.annimon.ownlang.stages;
import com.annimon.ownlang.exceptions.OwnLangParserException; import com.annimon.ownlang.exceptions.OwnLangParserException;
import com.annimon.ownlang.parser.Parser; import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.Token; import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import java.util.List; import java.util.List;
public class ParserStage implements Stage<List<Token>, Statement> { public class ParserStage implements Stage<List<Token>, Node> {
public static final String TAG_PROGRAM = "program"; public static final String TAG_PROGRAM = "program";
public static final String TAG_HAS_PARSE_ERRORS = "hasParseErrors"; public static final String TAG_HAS_PARSE_ERRORS = "hasParseErrors";
@Override @Override
public Statement perform(StagesData stagesData, List<Token> input) { public Node perform(StagesData stagesData, List<Token> input) {
final Parser parser = new Parser(input); final Parser parser = new Parser(input);
final Statement program = parser.parse(); final Node program = parser.parse();
final var parseErrors = parser.getParseErrors(); final var parseErrors = parser.getParseErrors();
stagesData.put(TAG_PROGRAM, program); stagesData.put(TAG_PROGRAM, program);
stagesData.put(TAG_HAS_PARSE_ERRORS, parseErrors.hasErrors()); stagesData.put(TAG_HAS_PARSE_ERRORS, parseErrors.hasErrors());

View File

@ -32,9 +32,9 @@ public class ParserTest {
assertEval( number(2), "12 % 5", operator(BinaryExpression.Operator.REMAINDER, value(12), value(5)) ); assertEval( number(2), "12 % 5", operator(BinaryExpression.Operator.REMAINDER, value(12), value(5)) );
} }
private static void assertEval(Value expectedValue, String input, Expression expected) { private static void assertEval(Value expectedValue, String input, Node expected) {
BlockStatement program = assertExpression(input, expected); BlockStatement program = assertExpression(input, expected);
program.execute(); program.eval();
final Value actual = ScopeHandler.getVariable("a"); final Value actual = ScopeHandler.getVariable("a");
try { try {
assertEquals(expectedValue.asNumber(), actual.asNumber(), 0.001); assertEquals(expectedValue.asNumber(), actual.asNumber(), 0.001);
@ -43,7 +43,7 @@ public class ParserTest {
} }
} }
private static BlockStatement assertExpression(String input, Expression expected) { private static BlockStatement assertExpression(String input, Node expected) {
return assertProgram("a = " + input, block(assign("a", expected))); return assertProgram("a = " + input, block(assign("a", expected)));
} }
@ -60,7 +60,7 @@ public class ParserTest {
} }
} }
private static Statement parse(String input) { private static Node parse(String input) {
return Parser.parse(Lexer.tokenize(input)); return Parser.parse(Lexer.tokenize(input));
} }
} }

View File

@ -1,6 +1,6 @@
package com.annimon.ownlang.parser; package com.annimon.ownlang.parser;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.annotations.*;
@ -28,7 +28,7 @@ public class ProgramsBenchmarkTest {
@Param({"-"}) @Param({"-"})
private String path; private String path;
private Statement program; private Node program;
@Setup(Level.Trial) @Setup(Level.Trial)
public void initializeTrial() throws IOException { public void initializeTrial() throws IOException {
@ -41,7 +41,7 @@ public class ProgramsBenchmarkTest {
@Benchmark @Benchmark
public void programBenchmark() { public void programBenchmark() {
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
program.execute(); program.eval();
} }
} }

View File

@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.FunctionValue;
import com.annimon.ownlang.lib.NumberValue; import com.annimon.ownlang.lib.NumberValue;
import com.annimon.ownlang.lib.ScopeHandler; import com.annimon.ownlang.lib.ScopeHandler;
import com.annimon.ownlang.parser.ast.FunctionDefineStatement; import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Visitor; import com.annimon.ownlang.parser.ast.Visitor;
import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage; import com.annimon.ownlang.parser.error.ParseErrorsFormatterStage;
import com.annimon.ownlang.parser.optimization.OptimizationStage; import com.annimon.ownlang.parser.optimization.OptimizationStage;
@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.*;
public class ProgramsTest { public class ProgramsTest {
private static final String RES_DIR = "src/test/resources"; private static final String RES_DIR = "src/test/resources";
private static Stage<InputSource, Statement> testPipeline; private static Stage<InputSource, Node> testPipeline;
public static Stream<InputSource> data() { public static Stream<InputSource> data() {
return scanDirectory(RES_DIR) return scanDirectory(RES_DIR)

View File

@ -35,19 +35,19 @@ public final class ASTHelper {
return result; return result;
} }
public static AssignmentExpression assign(String variable, Expression expr) { public static AssignmentExpression assign(String variable, Node expr) {
return assign(var(variable), expr); return assign(var(variable), expr);
} }
public static AssignmentExpression assign(Accessible accessible, Expression expr) { public static AssignmentExpression assign(Accessible accessible, Node expr) {
return assign(null, accessible, expr); return assign(null, accessible, expr);
} }
public static AssignmentExpression assign(BinaryExpression.Operator op, Accessible accessible, Expression expr) { public static AssignmentExpression assign(BinaryExpression.Operator op, Accessible accessible, Node expr) {
return new AssignmentExpression(op, accessible, expr); return new AssignmentExpression(op, accessible, expr);
} }
public static BinaryExpression operator(BinaryExpression.Operator op, Expression left, Expression right) { public static BinaryExpression operator(BinaryExpression.Operator op, Node left, Node right) {
return new BinaryExpression(op, left, right); return new BinaryExpression(op, left, right);
} }

View File

@ -21,8 +21,8 @@ public class VariableExpressionTest {
@Test @Test
public void testVariable() { public void testVariable() {
assign("a", value(4)).execute(); assign("a", value(4)).eval();
assign("b", value("ABCD")).execute(); assign("b", value("ABCD")).eval();
assertValue(number(4), var("a").eval()); assertValue(number(4), var("a").eval());
assertValue(string("ABCD"), var("b").eval()); assertValue(string("ABCD"), var("b").eval());
@ -30,8 +30,8 @@ public class VariableExpressionTest {
@Test @Test
public void testVariableReplace() { public void testVariableReplace() {
assign("a", value(4)).execute(); assign("a", value(4)).eval();
assign("a", value(8)).execute(); assign("a", value(8)).eval();
assertValue(number(8), var("a").eval()); assertValue(number(8), var("a").eval());
} }

View File

@ -7,7 +7,7 @@ import com.annimon.ownlang.exceptions.StoppedException;
import com.annimon.ownlang.lib.*; import com.annimon.ownlang.lib.*;
import com.annimon.ownlang.parser.*; import com.annimon.ownlang.parser.*;
import com.annimon.ownlang.parser.ast.BlockStatement; import com.annimon.ownlang.parser.ast.BlockStatement;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.util.Pos; import com.annimon.ownlang.util.Pos;
import com.annimon.ownlang.parser.visitors.PrintVisitor; import com.annimon.ownlang.parser.visitors.PrintVisitor;
import com.annimon.ownlang.utils.repl.JLineConsole; import com.annimon.ownlang.utils.repl.JLineConsole;
@ -66,7 +66,7 @@ public final class Repl {
} }
buffer.append(line).append(Console.newline()); buffer.append(line).append(Console.newline());
Statement program = null; Node program = null;
try { try {
final List<Token> tokens = Lexer.tokenize(buffer.toString()); final List<Token> tokens = Lexer.tokenize(buffer.toString());
final Parser parser = new Parser(tokens); final Parser parser = new Parser(tokens);
@ -82,7 +82,7 @@ public final class Repl {
continue; continue;
} }
} }
program.execute(); program.eval();
} catch (OwnLangParserException lex) { } catch (OwnLangParserException lex) {
continue; continue;
} catch (StoppedException ex) { } catch (StoppedException ex) {

View File

@ -8,6 +8,7 @@ import com.annimon.ownlang.parser.Lexer;
import com.annimon.ownlang.parser.Parser; import com.annimon.ownlang.parser.Parser;
import com.annimon.ownlang.parser.SourceLoader; import com.annimon.ownlang.parser.SourceLoader;
import com.annimon.ownlang.parser.Token; import com.annimon.ownlang.parser.Token;
import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.visitors.FunctionAdder; import com.annimon.ownlang.parser.visitors.FunctionAdder;
import java.io.File; import java.io.File;
@ -31,7 +32,7 @@ public final class Sandbox {
final List<Token> tokens = Lexer.tokenize(input); final List<Token> tokens = Lexer.tokenize(input);
final Parser parser = new Parser(tokens); final Parser parser = new Parser(tokens);
final Statement program = parser.parse(); final Node program = parser.parse();
if (parser.getParseErrors().hasErrors()) { if (parser.getParseErrors().hasErrors()) {
System.out.print(parser.getParseErrors()); System.out.print(parser.getParseErrors());
return; return;
@ -40,7 +41,7 @@ public final class Sandbox {
program.accept(new FunctionAdder()); program.accept(new FunctionAdder());
try { try {
program.execute(); program.eval();
} catch (StoppedException ex) { } catch (StoppedException ex) {
// skip // skip
} catch (Exception ex) { } catch (Exception ex) {