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);
|
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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,23 +6,18 @@ 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() {
|
||||||
super.interruptionCheck();
|
super.interruptionCheck();
|
||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
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
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,11 +37,6 @@ public final class FunctionalExpression extends InterruptableNode
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
eval();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value eval() {
|
public Value eval() {
|
||||||
super.interruptionCheck();
|
super.interruptionCheck();
|
||||||
@ -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()) {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
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);
|
||||||
|
|
||||||
<R, T> R accept(ResultVisitor<R, T> visitor, T input);
|
<R, T> R accept(ResultVisitor<R, T> visitor, T input);
|
||||||
|
@ -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()) {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,4 @@ package com.annimon.ownlang.parser.ast;
|
|||||||
*/
|
*/
|
||||||
public interface Statement extends Node {
|
public interface Statement extends Node {
|
||||||
|
|
||||||
void execute();
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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() {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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),
|
||||||
|
@ -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) {
|
||||||
|
@ -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)) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}*/
|
}*/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user