mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Remove unnecessary abstraction Expression, use Statement only as marker
This commit is contained in:
parent
f6d4ff5cc9
commit
1535e86472
@ -65,7 +65,7 @@ public class UserDefinedFunction implements Function, SourceLocation {
|
||||
final Argument arg = arguments.get(i);
|
||||
ScopeHandler.defineVariableInCurrentScope(arg.name(), arg.valueExpr().eval());
|
||||
}
|
||||
body.execute();
|
||||
body.eval();
|
||||
return NumberValue.ZERO;
|
||||
} catch (ReturnStatement rt) {
|
||||
return rt.getResult();
|
||||
|
@ -20,9 +20,9 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
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 Statement program = parser.parse();
|
||||
final Node program = parser.parse();
|
||||
if (parser.getParseErrors().hasErrors()) {
|
||||
throw new OwnLangParserException(parser.getParseErrors());
|
||||
}
|
||||
@ -71,7 +71,7 @@ public final class Parser {
|
||||
return parseErrors;
|
||||
}
|
||||
|
||||
public Statement parse() {
|
||||
public Node parse() {
|
||||
parseErrors.clear();
|
||||
final BlockStatement result = new BlockStatement();
|
||||
while (!match(TokenType.EOF)) {
|
||||
@ -180,7 +180,7 @@ public final class Parser {
|
||||
if (match(TokenType.EXTRACT)) {
|
||||
return destructuringAssignment();
|
||||
}
|
||||
final Expression expression = expression();
|
||||
final Node expression = expression();
|
||||
if (expression instanceof Statement statement) {
|
||||
return statement;
|
||||
}
|
||||
@ -209,7 +209,7 @@ public final class Parser {
|
||||
}
|
||||
|
||||
private Statement ifElse() {
|
||||
final Expression condition = expression();
|
||||
final Node condition = expression();
|
||||
final Statement ifStatement = statementOrBlock();
|
||||
final Statement elseStatement;
|
||||
if (match(TokenType.ELSE)) {
|
||||
@ -221,7 +221,7 @@ public final class Parser {
|
||||
}
|
||||
|
||||
private Statement whileStatement() {
|
||||
final Expression condition = expression();
|
||||
final Node condition = expression();
|
||||
final Statement statement = statementOrBlock();
|
||||
return new WhileStatement(condition, statement);
|
||||
}
|
||||
@ -229,7 +229,7 @@ public final class Parser {
|
||||
private Statement doWhileStatement() {
|
||||
final Statement statement = statementOrBlock();
|
||||
consume(TokenType.WHILE);
|
||||
final Expression condition = expression();
|
||||
final Node condition = expression();
|
||||
return new DoWhileStatement(condition, statement);
|
||||
}
|
||||
|
||||
@ -252,7 +252,7 @@ public final class Parser {
|
||||
boolean optParentheses = match(TokenType.LPAREN);
|
||||
final Statement initialization = assignmentStatement();
|
||||
consume(TokenType.COMMA);
|
||||
final Expression termination = expression();
|
||||
final Node termination = expression();
|
||||
consume(TokenType.COMMA);
|
||||
final Statement increment = assignmentStatement();
|
||||
if (optParentheses) consume(TokenType.RPAREN); // close opt parentheses
|
||||
@ -265,7 +265,7 @@ public final class Parser {
|
||||
boolean optParentheses = match(TokenType.LPAREN);
|
||||
final String variable = consume(TokenType.WORD).text();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
final Node container = expression();
|
||||
if (optParentheses) {
|
||||
consume(TokenType.RPAREN); // close opt parentheses
|
||||
}
|
||||
@ -280,7 +280,7 @@ public final class Parser {
|
||||
consume(TokenType.COMMA);
|
||||
final String value = consume(TokenType.WORD).text();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
final Node container = expression();
|
||||
if (optParentheses) {
|
||||
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
|
||||
final Expression expr = function(qualifiedNameExpr);
|
||||
final Node expr = function(qualifiedNameExpr);
|
||||
if (lookMatch(0, TokenType.LPAREN)) {
|
||||
return functionChain(expr);
|
||||
}
|
||||
if (lookMatch(0, TokenType.DOT)) {
|
||||
final List<Expression> indices = variableSuffix();
|
||||
final List<Node> indices = variableSuffix();
|
||||
if (indices == null || indices.isEmpty()) {
|
||||
return expr;
|
||||
}
|
||||
@ -354,7 +354,7 @@ public final class Parser {
|
||||
return expr;
|
||||
}
|
||||
|
||||
private FunctionalExpression function(Expression qualifiedNameExpr) {
|
||||
private FunctionalExpression function(Node qualifiedNameExpr) {
|
||||
// function(arg1, arg2, ...)
|
||||
final var startTokenIndex = index - 1;
|
||||
consume(TokenType.LPAREN);
|
||||
@ -367,10 +367,10 @@ public final class Parser {
|
||||
return function;
|
||||
}
|
||||
|
||||
private Expression array() {
|
||||
private Node array() {
|
||||
// [value1, value2, ...]
|
||||
consume(TokenType.LBRACKET);
|
||||
final List<Expression> elements = new ArrayList<>();
|
||||
final List<Node> elements = new ArrayList<>();
|
||||
while (!match(TokenType.RBRACKET)) {
|
||||
elements.add(expression());
|
||||
match(TokenType.COMMA);
|
||||
@ -378,14 +378,14 @@ public final class Parser {
|
||||
return new ArrayExpression(elements);
|
||||
}
|
||||
|
||||
private Expression map() {
|
||||
private Node map() {
|
||||
// {key1 : value1, key2 : value2, ...}
|
||||
consume(TokenType.LBRACE);
|
||||
final Map<Expression, Expression> elements = new HashMap<>();
|
||||
final Map<Node, Node> elements = new HashMap<>();
|
||||
while (!match(TokenType.RBRACE)) {
|
||||
final Expression key = primary();
|
||||
final Node key = primary();
|
||||
consume(TokenType.COLON);
|
||||
final Expression value = expression();
|
||||
final Node value = expression();
|
||||
elements.put(key, value);
|
||||
match(TokenType.COMMA);
|
||||
}
|
||||
@ -397,7 +397,7 @@ public final class Parser {
|
||||
// case pattern1: result1
|
||||
// case pattern2 if expr: result2
|
||||
// }
|
||||
final Expression expression = expression();
|
||||
final Node expression = expression();
|
||||
consume(TokenType.LBRACE);
|
||||
final List<MatchExpression.Pattern> patterns = new ArrayList<>();
|
||||
do {
|
||||
@ -494,12 +494,12 @@ public final class Parser {
|
||||
return classDeclaration;
|
||||
}
|
||||
|
||||
private Expression expression() {
|
||||
private Node expression() {
|
||||
return assignment();
|
||||
}
|
||||
|
||||
private Expression assignment() {
|
||||
final Expression assignment = assignmentStrict();
|
||||
private Node assignment() {
|
||||
final Node assignment = assignmentStrict();
|
||||
if (assignment != null) {
|
||||
return assignment;
|
||||
}
|
||||
@ -509,7 +509,7 @@ public final class Parser {
|
||||
private AssignmentExpression assignmentStrict() {
|
||||
// x[0].prop += ...
|
||||
final int position = index;
|
||||
final Expression targetExpr = qualifiedName();
|
||||
final Node targetExpr = qualifiedName();
|
||||
if (!(targetExpr instanceof Accessible)) {
|
||||
index = position;
|
||||
return null;
|
||||
@ -523,18 +523,18 @@ public final class Parser {
|
||||
match(currentType);
|
||||
|
||||
final BinaryExpression.Operator op = ASSIGN_OPERATORS.get(currentType);
|
||||
final Expression expression = expression();
|
||||
final Node expression = expression();
|
||||
|
||||
return new AssignmentExpression(op, (Accessible) targetExpr, expression);
|
||||
}
|
||||
|
||||
private Expression ternary() {
|
||||
Expression result = nullCoalesce();
|
||||
private Node ternary() {
|
||||
Node result = nullCoalesce();
|
||||
|
||||
if (match(TokenType.QUESTION)) {
|
||||
final Expression trueExpr = expression();
|
||||
final Node trueExpr = expression();
|
||||
consume(TokenType.COLON);
|
||||
final Expression falseExpr = expression();
|
||||
final Node falseExpr = expression();
|
||||
return new TernaryExpression(result, trueExpr, falseExpr);
|
||||
}
|
||||
if (match(TokenType.QUESTIONCOLON)) {
|
||||
@ -543,8 +543,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression nullCoalesce() {
|
||||
Expression result = logicalOr();
|
||||
private Node nullCoalesce() {
|
||||
Node result = logicalOr();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.QUESTIONQUESTION)) {
|
||||
@ -557,8 +557,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression logicalOr() {
|
||||
Expression result = logicalAnd();
|
||||
private Node logicalOr() {
|
||||
Node result = logicalAnd();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.BARBAR)) {
|
||||
@ -571,8 +571,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression logicalAnd() {
|
||||
Expression result = bitwiseOr();
|
||||
private Node logicalAnd() {
|
||||
Node result = bitwiseOr();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.AMPAMP)) {
|
||||
@ -585,8 +585,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression bitwiseOr() {
|
||||
Expression expression = bitwiseXor();
|
||||
private Node bitwiseOr() {
|
||||
Node expression = bitwiseXor();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.BAR)) {
|
||||
@ -599,8 +599,8 @@ public final class Parser {
|
||||
return expression;
|
||||
}
|
||||
|
||||
private Expression bitwiseXor() {
|
||||
Expression expression = bitwiseAnd();
|
||||
private Node bitwiseXor() {
|
||||
Node expression = bitwiseAnd();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.CARET)) {
|
||||
@ -613,8 +613,8 @@ public final class Parser {
|
||||
return expression;
|
||||
}
|
||||
|
||||
private Expression bitwiseAnd() {
|
||||
Expression expression = equality();
|
||||
private Node bitwiseAnd() {
|
||||
Node expression = equality();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.AMP)) {
|
||||
@ -627,8 +627,8 @@ public final class Parser {
|
||||
return expression;
|
||||
}
|
||||
|
||||
private Expression equality() {
|
||||
Expression result = conditional();
|
||||
private Node equality() {
|
||||
Node result = conditional();
|
||||
|
||||
if (match(TokenType.EQEQ)) {
|
||||
return new ConditionalExpression(ConditionalExpression.Operator.EQUALS, result, conditional());
|
||||
@ -640,8 +640,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression conditional() {
|
||||
Expression result = shift();
|
||||
private Node conditional() {
|
||||
Node result = shift();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.LT)) {
|
||||
@ -666,8 +666,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression shift() {
|
||||
Expression expression = additive();
|
||||
private Node shift() {
|
||||
Node expression = additive();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.LTLT)) {
|
||||
@ -692,8 +692,8 @@ public final class Parser {
|
||||
return expression;
|
||||
}
|
||||
|
||||
private Expression additive() {
|
||||
Expression result = multiplicative();
|
||||
private Node additive() {
|
||||
Node result = multiplicative();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.PLUS)) {
|
||||
@ -722,8 +722,8 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression multiplicative() {
|
||||
Expression result = objectCreation();
|
||||
private Node multiplicative() {
|
||||
Node result = objectCreation();
|
||||
|
||||
while (true) {
|
||||
if (match(TokenType.STAR)) {
|
||||
@ -748,11 +748,11 @@ public final class Parser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Expression objectCreation() {
|
||||
private Node objectCreation() {
|
||||
if (match(TokenType.NEW)) {
|
||||
final var startTokenIndex = index - 1;
|
||||
final String className = consume(TokenType.WORD).text();
|
||||
final List<Expression> args = new ArrayList<>();
|
||||
final List<Node> args = new ArrayList<>();
|
||||
consume(TokenType.LPAREN);
|
||||
while (!match(TokenType.RPAREN)) {
|
||||
args.add(expression());
|
||||
@ -766,7 +766,7 @@ public final class Parser {
|
||||
return unary();
|
||||
}
|
||||
|
||||
private Expression unary() {
|
||||
private Node unary() {
|
||||
if (match(TokenType.PLUSPLUS)) {
|
||||
return new UnaryExpression(UnaryExpression.Operator.INCREMENT_PREFIX, primary());
|
||||
}
|
||||
@ -788,9 +788,9 @@ public final class Parser {
|
||||
return primary();
|
||||
}
|
||||
|
||||
private Expression primary() {
|
||||
private Node primary() {
|
||||
if (match(TokenType.LPAREN)) {
|
||||
Expression result = expression();
|
||||
Node result = expression();
|
||||
consume(TokenType.RPAREN);
|
||||
return result;
|
||||
}
|
||||
@ -813,13 +813,13 @@ public final class Parser {
|
||||
return variable();
|
||||
}
|
||||
|
||||
private Expression variable() {
|
||||
private Node variable() {
|
||||
// function(...
|
||||
if (lookMatch(0, TokenType.WORD) && lookMatch(1, TokenType.LPAREN)) {
|
||||
return functionChain(new ValueExpression(consume(TokenType.WORD).text()));
|
||||
}
|
||||
|
||||
final Expression qualifiedNameExpr = qualifiedName();
|
||||
final Node qualifiedNameExpr = qualifiedName();
|
||||
if (qualifiedNameExpr != null) {
|
||||
// variable(args) || arr["key"](args) || obj.key(args)
|
||||
if (lookMatch(0, TokenType.LPAREN)) {
|
||||
@ -844,28 +844,28 @@ public final class Parser {
|
||||
return value();
|
||||
}
|
||||
|
||||
private Expression qualifiedName() {
|
||||
private Node qualifiedName() {
|
||||
// var || var.key[index].key2
|
||||
final Token current = get(0);
|
||||
if (!match(TokenType.WORD)) return null;
|
||||
|
||||
final List<Expression> indices = variableSuffix();
|
||||
final List<Node> indices = variableSuffix();
|
||||
if (indices == null || indices.isEmpty()) {
|
||||
return new VariableExpression(current.text());
|
||||
}
|
||||
return new ContainerAccessExpression(current.text(), indices);
|
||||
}
|
||||
|
||||
private List<Expression> variableSuffix() {
|
||||
private List<Node> variableSuffix() {
|
||||
// .key1.arr1[expr1][expr2].key2
|
||||
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
|
||||
return null;
|
||||
}
|
||||
final List<Expression> indices = new ArrayList<>();
|
||||
final List<Node> indices = new ArrayList<>();
|
||||
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
||||
if (match(TokenType.DOT)) {
|
||||
final String fieldName = consume(TokenType.WORD).text();
|
||||
final Expression key = new ValueExpression(fieldName);
|
||||
final Node key = new ValueExpression(fieldName);
|
||||
indices.add(key);
|
||||
}
|
||||
if (match(TokenType.LBRACKET)) {
|
||||
@ -876,7 +876,7 @@ public final class Parser {
|
||||
return indices;
|
||||
}
|
||||
|
||||
private Expression value() {
|
||||
private Node value() {
|
||||
final Token current = get(0);
|
||||
if (match(TokenType.NUMBER)) {
|
||||
return new ValueExpression(createNumber(current.text(), 10));
|
||||
@ -898,7 +898,7 @@ public final class Parser {
|
||||
new ValueExpression(consume(TokenType.WORD).text())
|
||||
)));
|
||||
}
|
||||
final List<Expression> indices = variableSuffix();
|
||||
final List<Node> indices = variableSuffix();
|
||||
if (indices == null || indices.isEmpty()) {
|
||||
return strExpr;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
public record Argument(String name, Expression valueExpr) {
|
||||
public record Argument(String name, Node valueExpr) {
|
||||
|
||||
public Argument(String name) {
|
||||
this(name, null);
|
||||
|
@ -22,7 +22,7 @@ public final class Arguments implements Iterable<Argument>, SourceLocation {
|
||||
requiredArgumentsCount++;
|
||||
}
|
||||
|
||||
public void addOptional(String name, Expression expr) {
|
||||
public void addOptional(String name, Node expr) {
|
||||
arguments.add(new Argument(name, expr));
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,11 @@ import java.util.List;
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
|
@ -6,22 +6,17 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @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 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.target = target;
|
||||
this.expression = expr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
@ -30,8 +25,8 @@ public final class AssignmentExpression extends InterruptableNode implements Exp
|
||||
// Simple assignment
|
||||
return target.set(expression.eval());
|
||||
}
|
||||
final Expression expr1 = new ValueExpression(target.get());
|
||||
final Expression expr2 = new ValueExpression(expression.eval());
|
||||
final Node expr1 = new ValueExpression(target.get());
|
||||
final Node expr2 = new ValueExpression(expression.eval());
|
||||
return target.set(new BinaryExpression(operation, expr1, expr2).eval());
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.*;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class BinaryExpression implements Expression {
|
||||
public final class BinaryExpression implements Node {
|
||||
|
||||
public enum Operator {
|
||||
ADD("+"),
|
||||
@ -45,9 +45,9 @@ public final class BinaryExpression implements Expression {
|
||||
}
|
||||
|
||||
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.expr1 = expr1;
|
||||
this.expr2 = expr2;
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -10,22 +12,23 @@ import java.util.List;
|
||||
*/
|
||||
public final class BlockStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final List<Statement> statements;
|
||||
public final List<Node> statements;
|
||||
|
||||
public BlockStatement() {
|
||||
statements = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void add(Statement statement) {
|
||||
public void add(Node statement) {
|
||||
statements.add(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
for (Statement statement : statements) {
|
||||
statement.execute();
|
||||
for (Node statement : statements) {
|
||||
statement.eval();
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,7 +44,7 @@ public final class BlockStatement extends InterruptableNode implements Statement
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (Statement statement : statements) {
|
||||
for (Node statement : statements) {
|
||||
result.append(statement.toString()).append(Console.newline());
|
||||
}
|
||||
return result.toString();
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
@ -7,7 +9,7 @@ package com.annimon.ownlang.parser.ast;
|
||||
public final class BreakStatement extends RuntimeException implements Statement {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
throw this;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
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.List;
|
||||
|
||||
@ -25,8 +27,9 @@ public final class ClassDeclarationStatement implements Statement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
ClassDeclarations.set(name, this);
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,7 +9,7 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class ConditionalExpression implements Expression {
|
||||
public final class ConditionalExpression implements Node {
|
||||
|
||||
public enum Operator {
|
||||
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 ConditionalExpression(Operator operation, Expression expr1, Expression expr2) {
|
||||
public ConditionalExpression(Operator operation, Node expr1, Node expr2) {
|
||||
this.operation = operation;
|
||||
this.expr1 = expr1;
|
||||
this.expr2 = expr2;
|
||||
|
@ -9,20 +9,20 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* @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*\"");
|
||||
|
||||
public final Expression root;
|
||||
public final List<Expression> indices;
|
||||
public final Node root;
|
||||
public final List<Node> indices;
|
||||
private final boolean[] simpleIndices;
|
||||
private final boolean rootIsVariable;
|
||||
|
||||
public ContainerAccessExpression(String variable, List<Expression> indices) {
|
||||
public ContainerAccessExpression(String variable, List<Node> indices) {
|
||||
this(new VariableExpression(variable), indices);
|
||||
}
|
||||
|
||||
public ContainerAccessExpression(Expression root, List<Expression> indices) {
|
||||
public ContainerAccessExpression(Node root, List<Node> indices) {
|
||||
rootIsVariable = root instanceof VariableExpression;
|
||||
this.root = root;
|
||||
this.indices = indices;
|
||||
@ -33,7 +33,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
|
||||
return rootIsVariable;
|
||||
}
|
||||
|
||||
public Expression getRoot() {
|
||||
public Node getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
|
||||
private boolean[] precomputeSimpleIndices() {
|
||||
final boolean[] result = new boolean[indices.size()];
|
||||
int i = 0;
|
||||
for (Expression index : indices) {
|
||||
for (Node index : indices) {
|
||||
String indexStr = index.toString();
|
||||
result[i] = PATTERN_SIMPLE_INDEX.matcher(indexStr).matches();
|
||||
i++;
|
||||
@ -122,7 +122,7 @@ public final class ContainerAccessExpression implements Expression, Accessible {
|
||||
public String toString() {
|
||||
final var sb = new StringBuilder(root.toString());
|
||||
int i = 0;
|
||||
for (Expression index : indices) {
|
||||
for (Node index : indices) {
|
||||
String indexStr = index.toString();
|
||||
if (simpleIndices[i]) {
|
||||
sb.append('.').append(indexStr, 1, indexStr.length() - 1);
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
@ -7,7 +9,7 @@ package com.annimon.ownlang.parser.ast;
|
||||
public final class ContinueStatement extends RuntimeException implements Statement {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
throw this;
|
||||
}
|
||||
|
||||
|
@ -13,21 +13,22 @@ import java.util.Map;
|
||||
public final class DestructuringAssignmentStatement extends InterruptableNode implements Statement {
|
||||
|
||||
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.containerExpression = container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
final Value container = containerExpression.eval();
|
||||
switch (container.type()) {
|
||||
case Types.ARRAY -> execute((ArrayValue) container);
|
||||
case Types.MAP -> execute((MapValue) container);
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
private void execute(ArrayValue array) {
|
||||
|
@ -1,25 +1,28 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class DoWhileStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final Expression condition;
|
||||
public final Node condition;
|
||||
public final Statement statement;
|
||||
|
||||
public DoWhileStatement(Expression condition, Statement statement) {
|
||||
public DoWhileStatement(Node condition, Statement statement) {
|
||||
this.condition = condition;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
do {
|
||||
try {
|
||||
statement.execute();
|
||||
statement.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
@ -27,6 +30,7 @@ public final class DoWhileStatement extends InterruptableNode implements Stateme
|
||||
}
|
||||
}
|
||||
while (condition.eval().asInt() != 0);
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -7,22 +7,17 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
super.interruptionCheck();
|
||||
expr.eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
return expr.eval();
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
@ -7,11 +10,11 @@ package com.annimon.ownlang.parser.ast;
|
||||
public final class ForStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final Statement initialization;
|
||||
public final Expression termination;
|
||||
public final Node termination;
|
||||
public final Statement increment;
|
||||
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.termination = termination;
|
||||
this.increment = increment;
|
||||
@ -19,17 +22,18 @@ public final class ForStatement extends InterruptableNode implements Statement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
for (initialization.execute(); termination.eval().asInt() != 0; increment.execute()) {
|
||||
for (initialization.eval(); termination.eval().asInt() != 0; increment.eval()) {
|
||||
try {
|
||||
statement.execute();
|
||||
statement.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,17 +11,17 @@ import java.util.Map;
|
||||
public final class ForeachArrayStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final String variable;
|
||||
public final Expression container;
|
||||
public final Node container;
|
||||
public final Statement body;
|
||||
|
||||
public ForeachArrayStatement(String variable, Expression container, Statement body) {
|
||||
public ForeachArrayStatement(String variable, Node container, Statement body) {
|
||||
this.variable = variable;
|
||||
this.container = container;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
try (final var ignored = ScopeHandler.closeableScope()) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
private void iterateString(String str) {
|
||||
for (char ch : str.toCharArray()) {
|
||||
ScopeHandler.setVariable(variable, new StringValue(String.valueOf(ch)));
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
@ -51,7 +52,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
|
||||
for (Value value : containerValue) {
|
||||
ScopeHandler.setVariable(variable, value);
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
@ -67,7 +68,7 @@ public final class ForeachArrayStatement extends InterruptableNode implements St
|
||||
entry.getValue()
|
||||
}));
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
|
@ -11,10 +11,10 @@ import java.util.Map;
|
||||
public final class ForeachMapStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final String key, value;
|
||||
public final Expression container;
|
||||
public final Node container;
|
||||
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.value = value;
|
||||
this.container = container;
|
||||
@ -22,7 +22,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
try (final var ignored = ScopeHandler.closeableScope()) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
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(value, NumberValue.of(ch));
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
@ -55,7 +56,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
|
||||
ScopeHandler.setVariable(key, v);
|
||||
ScopeHandler.setVariable(value, NumberValue.of(index++));
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
@ -69,7 +70,7 @@ public final class ForeachMapStatement extends InterruptableNode implements Stat
|
||||
ScopeHandler.setVariable(key, entry.getKey());
|
||||
ScopeHandler.setVariable(value, entry.getValue());
|
||||
try {
|
||||
body.execute();
|
||||
body.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
|
@ -1,7 +1,9 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
import com.annimon.ownlang.lib.UserDefinedFunction;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.util.Range;
|
||||
import com.annimon.ownlang.util.SourceLocation;
|
||||
|
||||
@ -29,8 +31,9 @@ public final class FunctionDefineStatement implements Statement, SourceLocation
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
ScopeHandler.setFunction(name, new UserDefinedFunction(arguments, body, range));
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.*;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class FunctionReferenceExpression extends InterruptableNode implements Expression {
|
||||
public final class FunctionReferenceExpression extends InterruptableNode {
|
||||
|
||||
public final String name;
|
||||
|
||||
|
@ -13,18 +13,18 @@ import java.util.List;
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class FunctionalExpression extends InterruptableNode
|
||||
implements Expression, Statement, SourceLocation {
|
||||
implements Statement, SourceLocation {
|
||||
|
||||
public final Expression functionExpr;
|
||||
public final List<Expression> arguments;
|
||||
public final Node functionExpr;
|
||||
public final List<Node> arguments;
|
||||
private Range range;
|
||||
|
||||
public FunctionalExpression(Expression functionExpr) {
|
||||
public FunctionalExpression(Node functionExpr) {
|
||||
this.functionExpr = functionExpr;
|
||||
arguments = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addArgument(Expression arg) {
|
||||
public void addArgument(Node arg) {
|
||||
arguments.add(arg);
|
||||
}
|
||||
|
||||
@ -36,11 +36,6 @@ public final class FunctionalExpression extends InterruptableNode
|
||||
public Range getRange() {
|
||||
return range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
@ -57,7 +52,7 @@ public final class FunctionalExpression extends InterruptableNode
|
||||
return result;
|
||||
}
|
||||
|
||||
private Function consumeFunction(Expression expr) {
|
||||
private Function consumeFunction(Node expr) {
|
||||
final Value value = expr.eval();
|
||||
if (value.type() == Types.FUNCTION) {
|
||||
return ((FunctionValue) value).getValue();
|
||||
@ -96,7 +91,7 @@ public final class FunctionalExpression extends InterruptableNode
|
||||
} else {
|
||||
sb.append(functionExpr).append('(');
|
||||
}
|
||||
final Iterator<Expression> it = arguments.iterator();
|
||||
final Iterator<Node> it = arguments.iterator();
|
||||
if (it.hasNext()) {
|
||||
sb.append(it.next());
|
||||
while (it.hasNext()) {
|
||||
|
@ -1,29 +1,33 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class IfStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final Expression expression;
|
||||
public final Node expression;
|
||||
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.ifStatement = ifStatement;
|
||||
this.elseStatement = elseStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
final int result = expression.eval().asInt();
|
||||
if (result != 0) {
|
||||
ifStatement.execute();
|
||||
ifStatement.eval();
|
||||
} else if (elseStatement != null) {
|
||||
elseStatement.execute();
|
||||
elseStatement.eval();
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,6 +2,8 @@ package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.exceptions.OwnLangParserException;
|
||||
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.stages.*;
|
||||
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 Expression expression;
|
||||
public final Node expression;
|
||||
|
||||
public IncludeStatement(Expression expression) {
|
||||
public IncludeStatement(Node expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
|
||||
final var stagesData = new StagesDataMap();
|
||||
@ -37,6 +39,7 @@ public final class IncludeStatement extends InterruptableNode implements Stateme
|
||||
.perform(stagesData, ex.getParseErrors());
|
||||
throw new OwnLangRuntimeException(error, ex);
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,11 +9,11 @@ import java.util.Map;
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ public final class MapExpression implements Expression {
|
||||
public Value eval() {
|
||||
final int size = elements.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());
|
||||
}
|
||||
return map;
|
||||
@ -41,9 +41,9 @@ public final class MapExpression implements Expression {
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append('{');
|
||||
Iterator<Map.Entry<Expression, Expression>> it = elements.entrySet().iterator();
|
||||
Iterator<Map.Entry<Node, Node>> it = elements.entrySet().iterator();
|
||||
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());
|
||||
while (it.hasNext()) {
|
||||
entry = it.next();
|
||||
|
@ -11,21 +11,16 @@ import java.util.List;
|
||||
*
|
||||
* @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 MatchExpression(Expression expression, List<Pattern> patterns) {
|
||||
public MatchExpression(Node expression, List<Pattern> patterns) {
|
||||
this.expression = expression;
|
||||
this.patterns = patterns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
@ -73,7 +68,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
||||
|
||||
final int size = array.size();
|
||||
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) ) {
|
||||
return false;
|
||||
}
|
||||
@ -146,7 +141,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
||||
|
||||
private Value evalResult(Statement s) {
|
||||
try {
|
||||
s.execute();
|
||||
s.eval();
|
||||
} catch (ReturnStatement ret) {
|
||||
return ret.getResult();
|
||||
}
|
||||
@ -176,7 +171,7 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
||||
|
||||
public abstract static sealed class Pattern {
|
||||
public Statement result;
|
||||
public Expression optCondition;
|
||||
public Node optCondition;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -247,13 +242,13 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
||||
}
|
||||
|
||||
public static final class TuplePattern extends Pattern {
|
||||
public final List<Expression> values;
|
||||
public final List<Node> values;
|
||||
|
||||
public TuplePattern() {
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
public TuplePattern(List<Expression> parts) {
|
||||
public TuplePattern(List<Node> parts) {
|
||||
this.values = parts;
|
||||
}
|
||||
|
||||
@ -261,13 +256,13 @@ public final class MatchExpression extends InterruptableNode implements Expressi
|
||||
values.add(ANY);
|
||||
}
|
||||
|
||||
public void add(Expression value) {
|
||||
public void add(Node value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final Iterator<Expression> it = values.iterator();
|
||||
final Iterator<Node> it = values.iterator();
|
||||
if (it.hasNext()) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
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
|
||||
public Value eval() {
|
||||
return NumberValue.ONE;
|
||||
|
@ -1,10 +1,14 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public interface Node {
|
||||
|
||||
Value eval();
|
||||
|
||||
void accept(Visitor visitor);
|
||||
|
||||
|
@ -7,13 +7,13 @@ import com.annimon.ownlang.util.SourceLocation;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public final class ObjectCreationExpression implements Expression, SourceLocation {
|
||||
public final class ObjectCreationExpression implements Node, SourceLocation {
|
||||
|
||||
public final String className;
|
||||
public final List<Expression> constructorArguments;
|
||||
public final List<Node> constructorArguments;
|
||||
private Range range;
|
||||
|
||||
public ObjectCreationExpression(String className, List<Expression> constructorArguments) {
|
||||
public ObjectCreationExpression(String className, List<Node> constructorArguments) {
|
||||
this.className = className;
|
||||
this.constructorArguments = constructorArguments;
|
||||
}
|
||||
@ -80,7 +80,7 @@ public final class ObjectCreationExpression implements Expression, SourceLocatio
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("new ").append(className).append(' ');
|
||||
final Iterator<Expression> it = constructorArguments.iterator();
|
||||
final Iterator<Node> it = constructorArguments.iterator();
|
||||
if (it.hasNext()) {
|
||||
sb.append(it.next());
|
||||
while (it.hasNext()) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
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 Expression expression;
|
||||
public final Node expression;
|
||||
|
||||
public PrintStatement(Expression expression) {
|
||||
public PrintStatement(Node expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
Console.print(expression.eval().asString());
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,8 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
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 Expression expression;
|
||||
public final Node expression;
|
||||
|
||||
public PrintlnStatement(Expression expression) {
|
||||
public PrintlnStatement(Node expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
Console.println(expression.eval().asString());
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,10 +8,10 @@ import com.annimon.ownlang.lib.Value;
|
||||
*/
|
||||
public final class ReturnStatement extends RuntimeException implements Statement {
|
||||
|
||||
public final Expression expression;
|
||||
public final Node expression;
|
||||
private Value result;
|
||||
|
||||
public ReturnStatement(Expression expression) {
|
||||
public ReturnStatement(Node expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public final class ReturnStatement extends RuntimeException implements Statement
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
result = expression.eval();
|
||||
throw this;
|
||||
}
|
||||
|
@ -5,6 +5,5 @@ package com.annimon.ownlang.parser.ast;
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public interface Statement extends Node {
|
||||
|
||||
void execute();
|
||||
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class TernaryExpression implements Expression {
|
||||
public final class TernaryExpression implements Node {
|
||||
|
||||
public final Expression condition;
|
||||
public final Expression trueExpr, falseExpr;
|
||||
public final Node condition;
|
||||
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.trueExpr = trueExpr;
|
||||
this.falseExpr = falseExpr;
|
||||
|
@ -10,7 +10,7 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class UnaryExpression implements Expression, Statement {
|
||||
public final class UnaryExpression implements Statement {
|
||||
|
||||
public enum Operator {
|
||||
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 UnaryExpression(Operator operation, Expression expr1) {
|
||||
public UnaryExpression(Operator operation, Node expr1) {
|
||||
this.operation = operation;
|
||||
this.expr1 = expr1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
eval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value eval() {
|
||||
final Value value = expr1.eval();
|
||||
|
@ -2,6 +2,7 @@ package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Function;
|
||||
import com.annimon.ownlang.lib.ModuleLoader;
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.modules.Module;
|
||||
import java.util.Collection;
|
||||
@ -20,11 +21,12 @@ public final class UseStatement extends InterruptableNode implements Statement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
for (String module : modules) {
|
||||
ModuleLoader.loadAndUse(module);
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
public Map<String, Value> loadConstants() {
|
||||
|
@ -11,7 +11,7 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class ValueExpression extends InterruptableNode implements Expression {
|
||||
public final class ValueExpression extends InterruptableNode {
|
||||
|
||||
public final Value value;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.annimon.ownlang.lib.Value;
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class VariableExpression extends InterruptableNode implements Expression, Accessible {
|
||||
public final class VariableExpression extends InterruptableNode implements Accessible {
|
||||
|
||||
public final String name;
|
||||
|
||||
@ -24,7 +24,9 @@ public final class VariableExpression extends InterruptableNode implements Expre
|
||||
|
||||
@Override
|
||||
public Value get() {
|
||||
if (!ScopeHandler.isVariableOrConstantExists(name)) throw new VariableDoesNotExistsException(name);
|
||||
if (!ScopeHandler.isVariableOrConstantExists(name)) {
|
||||
throw new VariableDoesNotExistsException(name);
|
||||
}
|
||||
return ScopeHandler.getVariableOrConstant(name);
|
||||
}
|
||||
|
||||
|
@ -1,31 +1,35 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class WhileStatement extends InterruptableNode implements Statement {
|
||||
|
||||
public final Expression condition;
|
||||
public final Node condition;
|
||||
public final Statement statement;
|
||||
|
||||
public WhileStatement(Expression condition, Statement statement) {
|
||||
public WhileStatement(Node condition, Statement statement) {
|
||||
this.condition = condition;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public Value eval() {
|
||||
super.interruptionCheck();
|
||||
while (condition.eval().asInt() != 0) {
|
||||
try {
|
||||
statement.execute();
|
||||
statement.eval();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.annimon.ownlang.parser.linters;
|
||||
|
||||
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.visitors.AbstractVisitor;
|
||||
import com.annimon.ownlang.parser.visitors.VisitorUtils;
|
||||
@ -15,7 +15,7 @@ abstract class LintVisitor extends AbstractVisitor {
|
||||
}
|
||||
|
||||
protected void applyVisitor(IncludeStatement s, Visitor visitor) {
|
||||
final Statement program = VisitorUtils.includeProgram(s);
|
||||
final Node program = VisitorUtils.includeProgram(s);
|
||||
if (program != null) {
|
||||
program.accept(visitor);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package com.annimon.ownlang.parser.linters;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
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.stages.Stage;
|
||||
import com.annimon.ownlang.stages.StagesData;
|
||||
@ -10,10 +10,10 @@ import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class LinterStage implements Stage<Statement, Statement> {
|
||||
public class LinterStage implements Stage<Node, Node> {
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
public Node perform(StagesData stagesData, Node input) {
|
||||
final List<LinterResult> results = new ArrayList<>();
|
||||
final Visitor[] validators = new Visitor[] {
|
||||
new AssignValidator(results),
|
||||
|
@ -4,7 +4,6 @@ import com.annimon.ownlang.lib.Types;
|
||||
import com.annimon.ownlang.parser.ast.AssignmentExpression;
|
||||
import com.annimon.ownlang.parser.ast.BlockStatement;
|
||||
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.Node;
|
||||
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) {
|
||||
final BlockStatement result = new BlockStatement();
|
||||
boolean changed = false;
|
||||
for (Statement statement : s.statements) {
|
||||
for (Node statement : s.statements) {
|
||||
final Node node = statement.accept(this, t);
|
||||
if (node != statement) {
|
||||
changed = true;
|
||||
@ -135,8 +134,8 @@ public class DeadCodeElimination extends OptimizationVisitor<Map<String, Variabl
|
||||
|
||||
if (node instanceof Statement stmt) {
|
||||
result.add(stmt);
|
||||
} else if (node instanceof Expression expr) {
|
||||
result.add(new ExprStatement(expr));
|
||||
} else if (node != null) {
|
||||
result.add(new ExprStatement(node));
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
|
@ -2,11 +2,9 @@ package com.annimon.ownlang.parser.optimization;
|
||||
|
||||
import com.annimon.ownlang.Console;
|
||||
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.PrintStatement;
|
||||
import com.annimon.ownlang.parser.ast.PrintlnStatement;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||
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();
|
||||
int i;
|
||||
for (i = 1; i < size; i++) {
|
||||
Statement s1 = s.statements.get(i - 1);
|
||||
Statement s2 = s.statements.get(i);
|
||||
Node s1 = s.statements.get(i - 1);
|
||||
Node s2 = s.statements.get(i);
|
||||
Node n1 = s1.accept(this, t);
|
||||
Node n2 = s2.accept(this, t);
|
||||
if (n1 != s1 || n2 != s2) {
|
||||
@ -57,7 +55,7 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
|
||||
}
|
||||
final Node combined = tryCombine(n1, n2);
|
||||
if (combined == null) {
|
||||
result.add((Statement) n1);
|
||||
result.add(n1);
|
||||
} else {
|
||||
changed = true;
|
||||
result.add(consumeStatement(combined));
|
||||
@ -66,12 +64,12 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
|
||||
}
|
||||
if (i == size) {
|
||||
// Last node
|
||||
Statement s2 = s.statements.get(size - 1);
|
||||
Node s2 = s.statements.get(size - 1);
|
||||
Node n2 = s2.accept(this, t);
|
||||
if (n2 != s2) {
|
||||
changed = true;
|
||||
}
|
||||
result.add((Statement) n2);
|
||||
result.add(n2);
|
||||
}
|
||||
if (changed) {
|
||||
return result;
|
||||
@ -91,10 +89,10 @@ public class InstructionCombining extends OptimizationVisitor<Void> implements O
|
||||
else n2Type = 0;
|
||||
|
||||
if (n1Type != 0 && n2Type != 0) {
|
||||
final Expression e1 = (n1Type == 1)
|
||||
final Node e1 = (n1Type == 1)
|
||||
? ((PrintStatement) n1).expression
|
||||
: ((PrintlnStatement) n1).expression;
|
||||
final Expression e2 = (n2Type == 1)
|
||||
final Node e2 = (n2Type == 1)
|
||||
? ((PrintStatement) n2).expression
|
||||
: ((PrintlnStatement) n2).expression;
|
||||
if (isConstantValue(e1) && isConstantValue(e2)) {
|
||||
|
@ -1,11 +1,10 @@
|
||||
package com.annimon.ownlang.parser.optimization;
|
||||
|
||||
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.StagesData;
|
||||
|
||||
public class OptimizationStage implements Stage<Statement, Statement> {
|
||||
public class OptimizationStage implements Stage<Node, Node> {
|
||||
|
||||
public static final String TAG_OPTIMIZATION_SUMMARY = "optimizationSummary";
|
||||
|
||||
@ -30,7 +29,7 @@ public class OptimizationStage implements Stage<Statement, Statement> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
public Node perform(StagesData stagesData, Node input) {
|
||||
if (level == 0) return input;
|
||||
|
||||
Node result = input;
|
||||
@ -51,6 +50,6 @@ public class OptimizationStage implements Stage<Statement, Statement> {
|
||||
);
|
||||
}
|
||||
|
||||
return (Statement) result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,14 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
|
||||
@Override
|
||||
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;
|
||||
for (Expression expression : s.elements) {
|
||||
for (Node expression : s.elements) {
|
||||
final Node node = expression.accept(this, t);
|
||||
if (node != expression) {
|
||||
changed = true;
|
||||
}
|
||||
elements.add((Expression) node);
|
||||
elements.add(node);
|
||||
}
|
||||
if (changed) {
|
||||
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 targetNode = s.target.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -44,7 +44,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
final Node expr1 = s.expr1.accept(this, t);
|
||||
final Node expr2 = s.expr2.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -53,15 +53,13 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(BlockStatement s, T t) {
|
||||
boolean changed = false;
|
||||
final BlockStatement result = new BlockStatement();
|
||||
for (Statement statement : s.statements) {
|
||||
for (Node statement : s.statements) {
|
||||
final Node node = statement.accept(this, t);
|
||||
if (node != statement) {
|
||||
changed = true;
|
||||
}
|
||||
if (node instanceof Statement) {
|
||||
result.add((Statement) node);
|
||||
} else if (node instanceof Expression) {
|
||||
result.add(new ExprStatement((Expression) node));
|
||||
if (node != null) {
|
||||
result.add(consumeStatement(node));
|
||||
}
|
||||
}
|
||||
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 expr2 = s.expr2.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -95,16 +93,16 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
final Node root = s.root.accept(this, t);
|
||||
boolean changed = (root != s.root);
|
||||
|
||||
final List<Expression> indices = new ArrayList<>(s.indices.size());
|
||||
for (Expression expression : s.indices) {
|
||||
final List<Node> indices = new ArrayList<>(s.indices.size());
|
||||
for (Node expression : s.indices) {
|
||||
final Node node = expression.accept(this, t);
|
||||
if (node != expression) {
|
||||
changed = true;
|
||||
}
|
||||
indices.add((Expression) node);
|
||||
indices.add(node);
|
||||
}
|
||||
if (changed) {
|
||||
return new ContainerAccessExpression((Expression) root, indices);
|
||||
return new ContainerAccessExpression(root, indices);
|
||||
}
|
||||
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 statement = s.statement.accept(this, t);
|
||||
if (condition != s.condition || statement != s.statement) {
|
||||
return new DoWhileStatement((Expression) condition, consumeStatement(statement));
|
||||
return new DoWhileStatement(condition, consumeStatement(statement));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -128,7 +126,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(DestructuringAssignmentStatement s, T t) {
|
||||
final Node expr = s.containerExpression.accept(this, t);
|
||||
if (expr != s.containerExpression) {
|
||||
return new DestructuringAssignmentStatement(s.variables, (Expression) expr);
|
||||
return new DestructuringAssignmentStatement(s.variables, expr);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -142,7 +140,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
if (initialization != s.initialization || termination != s.termination
|
||||
|| increment != s.increment || statement != s.statement) {
|
||||
return new ForStatement(consumeStatement(initialization),
|
||||
(Expression) termination, consumeStatement(increment), consumeStatement(statement));
|
||||
termination, consumeStatement(increment), consumeStatement(statement));
|
||||
}
|
||||
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 body = s.body.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -162,7 +160,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
final Node container = s.container.accept(this, t);
|
||||
final Node body = s.body.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -188,7 +186,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(ExprStatement s, T t) {
|
||||
final Node expr = s.expr.accept(this, t);
|
||||
if (expr != s.expr) {
|
||||
return new ExprStatement((Expression) expr);
|
||||
return new ExprStatement(expr);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -196,14 +194,14 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
@Override
|
||||
public Node visit(FunctionalExpression s, T 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;
|
||||
for (Expression argument : s.arguments) {
|
||||
for (Node argument : s.arguments) {
|
||||
final Node expr = argument.accept(this, t);
|
||||
if (expr != argument) {
|
||||
changed = true;
|
||||
}
|
||||
result.addArgument((Expression) expr);
|
||||
result.addArgument(expr);
|
||||
}
|
||||
if (changed) {
|
||||
return result;
|
||||
@ -222,7 +220,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
elseStatement = null;
|
||||
}
|
||||
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)) );
|
||||
}
|
||||
return s;
|
||||
@ -232,22 +230,22 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(IncludeStatement s, T t) {
|
||||
final Node expression = s.expression.accept(this, t);
|
||||
if (expression != s.expression) {
|
||||
return new IncludeStatement((Expression) expression);
|
||||
return new IncludeStatement(expression);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
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 value = entry.getValue().accept(this, t);
|
||||
if (key != entry.getKey() || value != entry.getValue()) {
|
||||
changed = true;
|
||||
}
|
||||
elements.put((Expression) key, (Expression) value);
|
||||
elements.put(key, value);
|
||||
}
|
||||
if (changed) {
|
||||
return new MapExpression(elements);
|
||||
@ -268,7 +266,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
if ((node != expr) && isValue(node)) {
|
||||
changed = true;
|
||||
final Value value = ((ValueExpression) node).value;
|
||||
final Expression optCondition = pattern.optCondition;
|
||||
final Node optCondition = pattern.optCondition;
|
||||
final Statement result = pattern.result;
|
||||
pattern = new MatchExpression.ConstantPattern(value);
|
||||
pattern.optCondition = optCondition;
|
||||
@ -277,21 +275,21 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
}
|
||||
|
||||
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;
|
||||
for (Expression value : tuple.values) {
|
||||
for (Node value : tuple.values) {
|
||||
if (value != MatchExpression.ANY) {
|
||||
final Node node = value.accept(this, t);
|
||||
if (node != value) {
|
||||
valuesChanged = true;
|
||||
value = (Expression) node;
|
||||
value = node;
|
||||
}
|
||||
}
|
||||
newValues.add(value);
|
||||
}
|
||||
if (valuesChanged) {
|
||||
changed = true;
|
||||
final Expression optCondition = pattern.optCondition;
|
||||
final Node optCondition = pattern.optCondition;
|
||||
final Statement result = pattern.result;
|
||||
pattern = new MatchExpression.TuplePattern(newValues);
|
||||
pattern.optCondition = optCondition;
|
||||
@ -309,28 +307,28 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
Node optCond = pattern.optCondition.accept(this, t);
|
||||
if (optCond != pattern.optCondition) {
|
||||
changed = true;
|
||||
pattern.optCondition = (Expression) optCond;
|
||||
pattern.optCondition = optCond;
|
||||
}
|
||||
}
|
||||
|
||||
patterns.add(pattern);
|
||||
}
|
||||
if (changed) {
|
||||
return new MatchExpression((Expression) expression, patterns);
|
||||
return new MatchExpression(expression, patterns);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node visit(ObjectCreationExpression s, T t) {
|
||||
final List<Expression> args = new ArrayList<>();
|
||||
final List<Node> args = new ArrayList<>();
|
||||
boolean changed = false;
|
||||
for (Expression argument : s.constructorArguments) {
|
||||
for (Node argument : s.constructorArguments) {
|
||||
final Node expr = argument.accept(this, t);
|
||||
if (expr != argument) {
|
||||
changed = true;
|
||||
}
|
||||
args.add((Expression) expr);
|
||||
args.add(expr);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@ -343,7 +341,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(PrintStatement s, T t) {
|
||||
final Node expression = s.expression.accept(this, t);
|
||||
if (expression != s.expression) {
|
||||
return new PrintStatement((Expression) expression);
|
||||
return new PrintStatement(expression);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -352,7 +350,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(PrintlnStatement s, T t) {
|
||||
final Node expression = s.expression.accept(this, t);
|
||||
if (expression != s.expression) {
|
||||
return new PrintlnStatement((Expression) expression);
|
||||
return new PrintlnStatement(expression);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -361,7 +359,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(ReturnStatement s, T t) {
|
||||
final Node expression = s.expression.accept(this, t);
|
||||
if (expression != s.expression) {
|
||||
return new ReturnStatement((Expression) expression);
|
||||
return new ReturnStatement(expression);
|
||||
}
|
||||
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 falseExpr = s.falseExpr.accept(this, t);
|
||||
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;
|
||||
}
|
||||
@ -381,7 +379,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
public Node visit(UnaryExpression s, T t) {
|
||||
final Node expr1 = s.expr1.accept(this, t);
|
||||
if (expr1 != s.expr1) {
|
||||
return new UnaryExpression(s.operation, (Expression) expr1);
|
||||
return new UnaryExpression(s.operation, expr1);
|
||||
}
|
||||
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 statement = s.statement.accept(this, t);
|
||||
if (condition != s.condition || statement != s.statement) {
|
||||
return new WhileStatement((Expression) condition, consumeStatement(statement));
|
||||
return new WhileStatement(condition, consumeStatement(statement));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -434,7 +432,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
boolean changed = false;
|
||||
out.setRange(in.getRange());
|
||||
for (Argument argument : in) {
|
||||
final Expression valueExpr = argument.valueExpr();
|
||||
final Node valueExpr = argument.valueExpr();
|
||||
if (valueExpr == null) {
|
||||
out.addRequired(argument.name());
|
||||
} else {
|
||||
@ -442,7 +440,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
if (expr != valueExpr) {
|
||||
changed = true;
|
||||
}
|
||||
out.addOptional(argument.name(), (Expression) expr);
|
||||
out.addOptional(argument.name(), expr);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
@ -452,6 +450,6 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
if (node instanceof Statement statement) {
|
||||
return statement;
|
||||
}
|
||||
return new ExprStatement((Expression) node);
|
||||
return new ExprStatement(node);
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
final String variableName = argument.name();
|
||||
grabVariableInfo(t, variableName);
|
||||
/* No need to add value - it is optional arguments
|
||||
final Expression expr = argument.getValueExpr();
|
||||
final Node expr = argument.getValueExpr();
|
||||
if (expr != null && isValue(expr)) {
|
||||
var.value = ((ValueExpression) expr).value;
|
||||
}*/
|
||||
|
@ -12,7 +12,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
|
||||
@Override
|
||||
public void visit(ArrayExpression s) {
|
||||
for (Expression index : s.elements) {
|
||||
for (Node index : s.elements) {
|
||||
index.accept(this);
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
|
||||
@Override
|
||||
public void visit(BlockStatement s) {
|
||||
for (Statement statement : s.statements) {
|
||||
for (Node statement : s.statements) {
|
||||
statement.accept(this);
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
@Override
|
||||
public void visit(ContainerAccessExpression s) {
|
||||
s.root.accept(this);
|
||||
for (Expression index : s.indices) {
|
||||
for (Node index : s.indices) {
|
||||
index.accept(this);
|
||||
}
|
||||
}
|
||||
@ -110,7 +110,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
@Override
|
||||
public void visit(FunctionalExpression s) {
|
||||
s.functionExpr.accept(this);
|
||||
for (Expression argument : s.arguments) {
|
||||
for (Node argument : s.arguments) {
|
||||
argument.accept(this);
|
||||
}
|
||||
}
|
||||
@ -131,7 +131,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
|
||||
@Override
|
||||
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.getValue().accept(this);
|
||||
}
|
||||
@ -144,7 +144,7 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
|
||||
@Override
|
||||
public void visit(ObjectCreationExpression s) {
|
||||
for (Expression argument : s.constructorArguments) {
|
||||
for (Node argument : s.constructorArguments) {
|
||||
argument.accept(this);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,6 @@ public final class FunctionAdder extends AbstractVisitor {
|
||||
@Override
|
||||
public void visit(FunctionDefineStatement s) {
|
||||
super.visit(s);
|
||||
s.execute();
|
||||
s.eval();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package com.annimon.ownlang.parser.visitors;
|
||||
|
||||
import com.annimon.ownlang.parser.ast.ArrayExpression;
|
||||
import com.annimon.ownlang.parser.ast.Expression;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.Node;
|
||||
import com.annimon.ownlang.parser.ast.UseStatement;
|
||||
import com.annimon.ownlang.parser.ast.ValueExpression;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@ -16,7 +13,7 @@ public class ModuleDetector extends AbstractVisitor {
|
||||
modules = new HashSet<>();
|
||||
}
|
||||
|
||||
public Set<String> detect(Statement s) {
|
||||
public Set<String> detect(Node s) {
|
||||
s.accept(this);
|
||||
return modules;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
||||
@Override
|
||||
public StringBuilder visit(ArrayExpression s, StringBuilder t) {
|
||||
t.append('[');
|
||||
final Iterator<Expression> it = s.elements.iterator();
|
||||
final Iterator<Node> it = s.elements.iterator();
|
||||
if (it.hasNext()) {
|
||||
it.next().accept(this, t);
|
||||
while (it.hasNext()) {
|
||||
@ -58,7 +58,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
||||
}
|
||||
increaseIndent();
|
||||
|
||||
for (Statement statement : s.statements) {
|
||||
for (Node statement : s.statements) {
|
||||
newLine(t);
|
||||
printIndent(t);
|
||||
statement.accept(this, t);
|
||||
@ -108,7 +108,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
||||
@Override
|
||||
public StringBuilder visit(ContainerAccessExpression s, StringBuilder t) {
|
||||
s.root.accept(this, t);
|
||||
for (Expression index : s.indices) {
|
||||
for (Node index : s.indices) {
|
||||
t.append('[');
|
||||
index.accept(this, t);
|
||||
t.append(']');
|
||||
@ -266,7 +266,7 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
||||
t.append('{');
|
||||
increaseIndent();
|
||||
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;
|
||||
else t.append(",");
|
||||
newLine(t);
|
||||
@ -440,10 +440,10 @@ public class PrintVisitor implements ResultVisitor<StringBuilder, StringBuilder>
|
||||
return t;
|
||||
}
|
||||
|
||||
private void printArgs(StringBuilder t, List<Expression> args) {
|
||||
private void printArgs(StringBuilder t, List<Node> args) {
|
||||
t.append("(");
|
||||
boolean firstElement = true;
|
||||
for (Expression expr : args) {
|
||||
for (Node expr : args) {
|
||||
if (firstElement) firstElement = false;
|
||||
else t.append(", ");
|
||||
expr.accept(this, t);
|
||||
|
@ -11,7 +11,6 @@ import com.annimon.ownlang.parser.ast.BinaryExpression;
|
||||
import com.annimon.ownlang.parser.ast.ConditionalExpression;
|
||||
import com.annimon.ownlang.parser.ast.IncludeStatement;
|
||||
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.ValueExpression;
|
||||
import com.annimon.ownlang.parser.ast.VariableExpression;
|
||||
@ -32,7 +31,7 @@ public final class VisitorUtils {
|
||||
return (node instanceof VariableExpression);
|
||||
}
|
||||
|
||||
public static Statement includeProgram(IncludeStatement s) {
|
||||
public static Node includeProgram(IncludeStatement s) {
|
||||
if (!isValue(s.expression)) return null;
|
||||
try {
|
||||
final String path = s.expression.eval().asString();
|
||||
|
@ -1,12 +1,12 @@
|
||||
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
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
input.execute();
|
||||
public Node perform(StagesData stagesData, Node input) {
|
||||
input.eval();
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
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;
|
||||
|
||||
public class FunctionAddingStage implements Stage<Statement, Statement> {
|
||||
public class FunctionAddingStage implements Stage<Node, Node> {
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, Statement input) {
|
||||
public Node perform(StagesData stagesData, Node input) {
|
||||
input.accept(new FunctionAdder());
|
||||
return input;
|
||||
}
|
||||
|
@ -3,18 +3,18 @@ package com.annimon.ownlang.stages;
|
||||
import com.annimon.ownlang.exceptions.OwnLangParserException;
|
||||
import com.annimon.ownlang.parser.Parser;
|
||||
import com.annimon.ownlang.parser.Token;
|
||||
import com.annimon.ownlang.parser.ast.Statement;
|
||||
import com.annimon.ownlang.parser.ast.Node;
|
||||
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_HAS_PARSE_ERRORS = "hasParseErrors";
|
||||
|
||||
@Override
|
||||
public Statement perform(StagesData stagesData, List<Token> input) {
|
||||
public Node perform(StagesData stagesData, List<Token> input) {
|
||||
final Parser parser = new Parser(input);
|
||||
final Statement program = parser.parse();
|
||||
final Node program = parser.parse();
|
||||
final var parseErrors = parser.getParseErrors();
|
||||
stagesData.put(TAG_PROGRAM, program);
|
||||
stagesData.put(TAG_HAS_PARSE_ERRORS, parseErrors.hasErrors());
|
||||
|
@ -32,9 +32,9 @@ public class ParserTest {
|
||||
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);
|
||||
program.execute();
|
||||
program.eval();
|
||||
final Value actual = ScopeHandler.getVariable("a");
|
||||
try {
|
||||
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)));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.Test;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
@ -28,7 +28,7 @@ public class ProgramsBenchmarkTest {
|
||||
@Param({"-"})
|
||||
private String path;
|
||||
|
||||
private Statement program;
|
||||
private Node program;
|
||||
|
||||
@Setup(Level.Trial)
|
||||
public void initializeTrial() throws IOException {
|
||||
@ -41,7 +41,7 @@ public class ProgramsBenchmarkTest {
|
||||
@Benchmark
|
||||
public void programBenchmark() {
|
||||
for (int i = 0; i < iterations; i++) {
|
||||
program.execute();
|
||||
program.eval();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ import com.annimon.ownlang.lib.FunctionValue;
|
||||
import com.annimon.ownlang.lib.NumberValue;
|
||||
import com.annimon.ownlang.lib.ScopeHandler;
|
||||
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.error.ParseErrorsFormatterStage;
|
||||
import com.annimon.ownlang.parser.optimization.OptimizationStage;
|
||||
@ -26,7 +26,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ProgramsTest {
|
||||
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() {
|
||||
return scanDirectory(RES_DIR)
|
||||
|
@ -35,19 +35,19 @@ public final class ASTHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static AssignmentExpression assign(String variable, Expression expr) {
|
||||
public static AssignmentExpression assign(String variable, Node 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ public class VariableExpressionTest {
|
||||
|
||||
@Test
|
||||
public void testVariable() {
|
||||
assign("a", value(4)).execute();
|
||||
assign("b", value("ABCD")).execute();
|
||||
assign("a", value(4)).eval();
|
||||
assign("b", value("ABCD")).eval();
|
||||
|
||||
assertValue(number(4), var("a").eval());
|
||||
assertValue(string("ABCD"), var("b").eval());
|
||||
@ -30,8 +30,8 @@ public class VariableExpressionTest {
|
||||
|
||||
@Test
|
||||
public void testVariableReplace() {
|
||||
assign("a", value(4)).execute();
|
||||
assign("a", value(8)).execute();
|
||||
assign("a", value(4)).eval();
|
||||
assign("a", value(8)).eval();
|
||||
|
||||
assertValue(number(8), var("a").eval());
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import com.annimon.ownlang.exceptions.StoppedException;
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import com.annimon.ownlang.parser.*;
|
||||
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.parser.visitors.PrintVisitor;
|
||||
import com.annimon.ownlang.utils.repl.JLineConsole;
|
||||
@ -66,7 +66,7 @@ public final class Repl {
|
||||
}
|
||||
|
||||
buffer.append(line).append(Console.newline());
|
||||
Statement program = null;
|
||||
Node program = null;
|
||||
try {
|
||||
final List<Token> tokens = Lexer.tokenize(buffer.toString());
|
||||
final Parser parser = new Parser(tokens);
|
||||
@ -82,7 +82,7 @@ public final class Repl {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
program.execute();
|
||||
program.eval();
|
||||
} catch (OwnLangParserException lex) {
|
||||
continue;
|
||||
} catch (StoppedException ex) {
|
||||
|
@ -8,6 +8,7 @@ import com.annimon.ownlang.parser.Lexer;
|
||||
import com.annimon.ownlang.parser.Parser;
|
||||
import com.annimon.ownlang.parser.SourceLoader;
|
||||
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.visitors.FunctionAdder;
|
||||
import java.io.File;
|
||||
@ -31,7 +32,7 @@ public final class Sandbox {
|
||||
|
||||
final List<Token> tokens = Lexer.tokenize(input);
|
||||
final Parser parser = new Parser(tokens);
|
||||
final Statement program = parser.parse();
|
||||
final Node program = parser.parse();
|
||||
if (parser.getParseErrors().hasErrors()) {
|
||||
System.out.print(parser.getParseErrors());
|
||||
return;
|
||||
@ -40,7 +41,7 @@ public final class Sandbox {
|
||||
program.accept(new FunctionAdder());
|
||||
|
||||
try {
|
||||
program.execute();
|
||||
program.eval();
|
||||
} catch (StoppedException ex) {
|
||||
// skip
|
||||
} catch (Exception ex) {
|
||||
|
Loading…
Reference in New Issue
Block a user