Switch to Java11+ features where possible

This commit is contained in:
aNNiMON 2023-08-28 16:52:29 +03:00 committed by Victor Melnik
parent 8ed89c8a9d
commit a2549c3afe
18 changed files with 125 additions and 206 deletions

View File

@ -52,7 +52,7 @@ public class ArrayValue implements Value, Iterable<Value> {
public static StringValue joinToString(ArrayValue array, String delimiter, String prefix, String suffix) { public static StringValue joinToString(ArrayValue array, String delimiter, String prefix, String suffix) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
for (Value value : array) { for (Value value : array) {
if (sb.length() > 0) sb.append(delimiter); if (!sb.isEmpty()) sb.append(delimiter);
else sb.append(prefix); else sb.append(prefix);
sb.append(value.asString()); sb.append(value.asString());
} }
@ -100,37 +100,26 @@ public class ArrayValue implements Value, Iterable<Value> {
} }
public Value get(Value index) { public Value get(Value index) {
final String prop = index.asString(); return switch (index.asString()) {
switch (prop) {
// Properties // Properties
case "length": case "length" -> NumberValue.of(size());
return NumberValue.of(size());
// Functions // Functions
case "isEmpty": case "isEmpty" -> Converters.voidToBoolean(() -> size() == 0);
return Converters.voidToBoolean(() -> size() == 0); case "joinToString" -> new FunctionValue(this::joinToString);
case "joinToString": default -> get(index.asInt());
return new FunctionValue(this::joinToString); };
default:
return get(index.asInt());
}
} }
public Value joinToString(Value[] args) { public Value joinToString(Value[] args) {
Arguments.checkRange(0, 3, args.length); Arguments.checkRange(0, 3, args.length);
switch (args.length) { return switch (args.length) {
case 0: case 0 -> joinToString(this, "", "", "");
return joinToString(this, "", "", ""); case 1 -> joinToString(this, args[0].asString(), "", "");
case 1: case 2 -> joinToString(this, args[0].asString(), args[1].asString(), args[1].asString());
return joinToString(this, args[0].asString(), "", ""); case 3 -> joinToString(this, args[0].asString(), args[1].asString(), args[2].asString());
case 2: default -> throw new ArgumentsMismatchException("Wrong number of arguments");
return joinToString(this, args[0].asString(), args[1].asString(), args[1].asString()); };
case 3:
return joinToString(this, args[0].asString(), args[1].asString(), args[2].asString());
default:
throw new ArgumentsMismatchException("Wrong number of arguments");
}
} }
public void set(int index, Value value) { public void set(int index, Value value) {

View File

@ -25,15 +25,7 @@ public final class CallStack {
return calls; return calls;
} }
public static class CallInfo { public record CallInfo(String name, Function function) {
String name;
Function function;
public CallInfo(String name, Function function) {
this.name = name;
this.function = function;
}
@Override @Override
public String toString() { public String toString() {
return String.format("%s: %s", name, function.toString().trim()); return String.format("%s: %s", name, function.toString().trim());

View File

@ -19,56 +19,46 @@ public final class StringValue implements Value {
public Value access(Value propertyValue) { public Value access(Value propertyValue) {
final String prop = propertyValue.asString(); final String prop = propertyValue.asString();
switch (prop) { return switch (prop) {
// Properties // Properties
case "length": case "length" -> NumberValue.of(length());
return NumberValue.of(length()); case "lower" -> new StringValue(value.toLowerCase());
case "lower": case "upper" -> new StringValue(value.toUpperCase());
return new StringValue(value.toLowerCase()); case "chars" -> {
case "upper":
return new StringValue(value.toUpperCase());
case "chars": {
final Value[] chars = new Value[length()]; final Value[] chars = new Value[length()];
int i = 0; int i = 0;
for (char ch : value.toCharArray()) { for (char ch : value.toCharArray()) {
chars[i++] = NumberValue.of((int) ch); chars[i++] = NumberValue.of(ch);
} }
return new ArrayValue(chars); yield new ArrayValue(chars);
} }
// Functions // Functions
case "trim": case "trim" -> Converters.voidToString(value::trim);
return Converters.voidToString(value::trim); case "startsWith" -> new FunctionValue(args -> {
case "startsWith":
return new FunctionValue(args -> {
Arguments.checkOrOr(1, 2, args.length); Arguments.checkOrOr(1, 2, args.length);
int offset = (args.length == 2) ? args[1].asInt() : 0; int offset = (args.length == 2) ? args[1].asInt() : 0;
return NumberValue.fromBoolean(value.startsWith(args[0].asString(), offset)); return NumberValue.fromBoolean(value.startsWith(args[0].asString(), offset));
}); });
case "endsWith": case "endsWith" -> Converters.stringToBoolean(value::endsWith);
return Converters.stringToBoolean(value::endsWith); case "matches" -> Converters.stringToBoolean(value::matches);
case "matches": case "contains" -> Converters.stringToBoolean(value::contains);
return Converters.stringToBoolean(value::matches); case "equalsIgnoreCase" -> Converters.stringToBoolean(value::equalsIgnoreCase);
case "contains": case "isEmpty" -> Converters.voidToBoolean(value::isEmpty);
return Converters.stringToBoolean(value::contains);
case "equalsIgnoreCase":
return Converters.stringToBoolean(value::equalsIgnoreCase);
case "isEmpty":
return Converters.voidToBoolean(value::isEmpty);
default: default -> {
if (Functions.isExists(prop)) { if (Functions.isExists(prop)) {
final Function f = Functions.get(prop); final Function f = Functions.get(prop);
return new FunctionValue(args -> { yield new FunctionValue(args -> {
final Value[] newArgs = new Value[args.length + 1]; final Value[] newArgs = new Value[args.length + 1];
newArgs[0] = this; newArgs[0] = this;
System.arraycopy(args, 0, newArgs, 1, args.length); System.arraycopy(args, 0, newArgs, 1, args.length);
return f.execute(newArgs); return f.execute(newArgs);
}); });
} }
break; throw new UnknownPropertyException(prop);
} }
throw new UnknownPropertyException(prop); };
} }
public int length() { public int length() {

View File

@ -14,18 +14,13 @@ public final class ValueUtils {
private ValueUtils() { } private ValueUtils() { }
public static Object toObject(Value val) { public static Object toObject(Value val) {
switch (val.type()) { return switch (val.type()) {
case Types.ARRAY: case Types.ARRAY -> toObject((ArrayValue) val);
return toObject((ArrayValue) val); case Types.MAP -> toObject((MapValue) val);
case Types.MAP: case Types.NUMBER -> val.raw();
return toObject((MapValue) val); case Types.STRING -> val.asString();
case Types.NUMBER: default -> JSONObject.NULL;
return val.raw(); };
case Types.STRING:
return val.asString();
default:
return JSONObject.NULL;
}
} }
public static JSONObject toObject(MapValue map) { public static JSONObject toObject(MapValue map) {
@ -47,20 +42,20 @@ public final class ValueUtils {
} }
public static Value toValue(Object obj) { public static Value toValue(Object obj) {
if (obj instanceof JSONObject) { if (obj instanceof JSONObject jsonObj) {
return toValue((JSONObject) obj); return toValue(jsonObj);
} }
if (obj instanceof JSONArray) { if (obj instanceof JSONArray jsonArr) {
return toValue((JSONArray) obj); return toValue(jsonArr);
} }
if (obj instanceof String) { if (obj instanceof String str) {
return new StringValue((String) obj); return new StringValue(str);
} }
if (obj instanceof Number) { if (obj instanceof Number num) {
return NumberValue.of(((Number) obj)); return NumberValue.of(num);
} }
if (obj instanceof Boolean) { if (obj instanceof Boolean flag) {
return NumberValue.fromBoolean((Boolean) obj); return NumberValue.fromBoolean(flag);
} }
// NULL or other // NULL or other
return NumberValue.ZERO; return NumberValue.ZERO;
@ -119,6 +114,7 @@ public final class ValueUtils {
return ((FunctionValue) value).getValue(); return ((FunctionValue) value).getValue();
} }
@SuppressWarnings("unchecked")
public static <T extends Number> MapValue collectNumberConstants(Class<?> clazz, Class<T> type) { public static <T extends Number> MapValue collectNumberConstants(Class<?> clazz, Class<T> type) {
MapValue result = new MapValue(20); MapValue result = new MapValue(20);
for (Field field : clazz.getDeclaredFields()) { for (Field field : clazz.getDeclaredFields()) {

View File

@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
import java.io.File; import java.io.File;
public class ConsoleOutputSettings implements OutputSettings { public non-sealed class ConsoleOutputSettings implements OutputSettings {
@Override @Override
public String newline() { public String newline() {

View File

@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
import java.io.File; import java.io.File;
public interface OutputSettings { public sealed interface OutputSettings permits ConsoleOutputSettings, StringOutputSettings {
String newline(); String newline();

View File

@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
import java.io.File; import java.io.File;
public class StringOutputSettings implements OutputSettings { public non-sealed class StringOutputSettings implements OutputSettings {
private final StringBuffer out, err; private final StringBuffer out, err;

View File

@ -27,7 +27,7 @@ public class UserDefinedFunction implements Function {
public String getArgsName(int index) { public String getArgsName(int index) {
if (index < 0 || index >= getArgsCount()) return ""; if (index < 0 || index >= getArgsCount()) return "";
return arguments.get(index).getName(); return arguments.get(index).name();
} }
@Override @Override
@ -52,7 +52,7 @@ public class UserDefinedFunction implements Function {
// Optional args if exists // Optional args if exists
for (int i = size; i < totalArgsCount; i++) { for (int i = size; i < totalArgsCount; i++) {
final Argument arg = arguments.get(i); final Argument arg = arguments.get(i);
Variables.define(arg.getName(), arg.getValueExpr().eval()); Variables.define(arg.name(), arg.valueExpr().eval());
} }
body.execute(); body.execute();
return NumberValue.ZERO; return NumberValue.ZERO;
@ -65,8 +65,8 @@ public class UserDefinedFunction implements Function {
@Override @Override
public String toString() { public String toString() {
if (body instanceof ReturnStatement) { if (body instanceof ReturnStatement returnStmt) {
return String.format("def%s = %s", arguments, ((ReturnStatement)body).expression); return String.format("def%s = %s", arguments, returnStmt.expression);
} }
return String.format("def%s %s", arguments, body); return String.format("def%s %s", arguments, body);
} }

View File

@ -86,8 +86,8 @@ public final class Parser {
private int getErrorLine() { private int getErrorLine() {
if (size == 0) return 0; if (size == 0) return 0;
if (pos >= size) return tokens.get(size - 1).getRow(); if (pos >= size) return tokens.get(size - 1).row();
return tokens.get(pos).getRow(); return tokens.get(pos).row();
} }
private void recover() { private void recover() {
@ -185,7 +185,7 @@ public final class Parser {
final List<String> variables = new ArrayList<>(); final List<String> variables = new ArrayList<>();
while (!match(TokenType.RPAREN)) { while (!match(TokenType.RPAREN)) {
if (lookMatch(0, TokenType.WORD)) { if (lookMatch(0, TokenType.WORD)) {
variables.add(consume(TokenType.WORD).getText()); variables.add(consume(TokenType.WORD).text());
} else { } else {
variables.add(null); variables.add(null);
} }
@ -250,7 +250,7 @@ public final class Parser {
private ForeachArrayStatement foreachArrayStatement() { private ForeachArrayStatement foreachArrayStatement() {
// for x : arr // for x : arr
boolean optParentheses = match(TokenType.LPAREN); boolean optParentheses = match(TokenType.LPAREN);
final String variable = consume(TokenType.WORD).getText(); final String variable = consume(TokenType.WORD).text();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression container = expression(); final Expression container = expression();
if (optParentheses) { if (optParentheses) {
@ -263,9 +263,9 @@ public final class Parser {
private ForeachMapStatement foreachMapStatement() { private ForeachMapStatement foreachMapStatement() {
// for k, v : map // for k, v : map
boolean optParentheses = match(TokenType.LPAREN); boolean optParentheses = match(TokenType.LPAREN);
final String key = consume(TokenType.WORD).getText(); final String key = consume(TokenType.WORD).text();
consume(TokenType.COMMA); consume(TokenType.COMMA);
final String value = consume(TokenType.WORD).getText(); final String value = consume(TokenType.WORD).text();
consume(TokenType.COLON); consume(TokenType.COLON);
final Expression container = expression(); final Expression container = expression();
if (optParentheses) { if (optParentheses) {
@ -277,7 +277,7 @@ public final class Parser {
private FunctionDefineStatement functionDefine() { private FunctionDefineStatement functionDefine() {
// def name(arg1, arg2 = value) { ... } || def name(args) = expr // def name(arg1, arg2 = value) { ... } || def name(args) = expr
final String name = consume(TokenType.WORD).getText(); final String name = consume(TokenType.WORD).text();
final Arguments arguments = arguments(); final Arguments arguments = arguments();
final Statement body = statementBody(); final Statement body = statementBody();
return new FunctionDefineStatement(name, arguments, body); return new FunctionDefineStatement(name, arguments, body);
@ -289,7 +289,7 @@ public final class Parser {
boolean startsOptionalArgs = false; boolean startsOptionalArgs = false;
consume(TokenType.LPAREN); consume(TokenType.LPAREN);
while (!match(TokenType.RPAREN)) { while (!match(TokenType.RPAREN)) {
final String name = consume(TokenType.WORD).getText(); final String name = consume(TokenType.WORD).text();
if (match(TokenType.EQ)) { if (match(TokenType.EQ)) {
startsOptionalArgs = true; startsOptionalArgs = true;
arguments.addOptional(name, variable()); arguments.addOptional(name, variable());
@ -383,26 +383,26 @@ public final class Parser {
if (match(TokenType.NUMBER)) { if (match(TokenType.NUMBER)) {
// case 0.5: // case 0.5:
pattern = new MatchExpression.ConstantPattern( pattern = new MatchExpression.ConstantPattern(
NumberValue.of(createNumber(current.getText(), 10)) NumberValue.of(createNumber(current.text(), 10))
); );
} else if (match(TokenType.HEX_NUMBER)) { } else if (match(TokenType.HEX_NUMBER)) {
// case #FF: // case #FF:
pattern = new MatchExpression.ConstantPattern( pattern = new MatchExpression.ConstantPattern(
NumberValue.of(createNumber(current.getText(), 16)) NumberValue.of(createNumber(current.text(), 16))
); );
} else if (match(TokenType.TEXT)) { } else if (match(TokenType.TEXT)) {
// case "text": // case "text":
pattern = new MatchExpression.ConstantPattern( pattern = new MatchExpression.ConstantPattern(
new StringValue(current.getText()) new StringValue(current.text())
); );
} else if (match(TokenType.WORD)) { } else if (match(TokenType.WORD)) {
// case value: // case value:
pattern = new MatchExpression.VariablePattern(current.getText()); pattern = new MatchExpression.VariablePattern(current.text());
} else if (match(TokenType.LBRACKET)) { } else if (match(TokenType.LBRACKET)) {
// case [x :: xs]: // case [x :: xs]:
final MatchExpression.ListPattern listPattern = new MatchExpression.ListPattern(); final MatchExpression.ListPattern listPattern = new MatchExpression.ListPattern();
while (!match(TokenType.RBRACKET)) { while (!match(TokenType.RBRACKET)) {
listPattern.add(consume(TokenType.WORD).getText()); listPattern.add(consume(TokenType.WORD).text());
match(TokenType.COLONCOLON); match(TokenType.COLONCOLON);
} }
pattern = listPattern; pattern = listPattern;
@ -410,7 +410,7 @@ public final class Parser {
// case (1, 2): // case (1, 2):
final MatchExpression.TuplePattern tuplePattern = new MatchExpression.TuplePattern(); final MatchExpression.TuplePattern tuplePattern = new MatchExpression.TuplePattern();
while (!match(TokenType.RPAREN)) { while (!match(TokenType.RPAREN)) {
if ("_".equals(get(0).getText())) { if ("_".equals(get(0).text())) {
tuplePattern.addAny(); tuplePattern.addAny();
consume(TokenType.WORD); consume(TokenType.WORD);
} else { } else {
@ -447,7 +447,7 @@ public final class Parser {
// str = "" // str = ""
// def method() = str // def method() = str
// } // }
final String name = consume(TokenType.WORD).getText(); final String name = consume(TokenType.WORD).text();
final ClassDeclarationStatement classDeclaration = new ClassDeclarationStatement(name); final ClassDeclarationStatement classDeclaration = new ClassDeclarationStatement(name);
consume(TokenType.LBRACE); consume(TokenType.LBRACE);
do { do {
@ -481,12 +481,12 @@ public final class Parser {
// x[0].prop += ... // x[0].prop += ...
final int position = pos; final int position = pos;
final Expression targetExpr = qualifiedName(); final Expression targetExpr = qualifiedName();
if ((targetExpr == null) || !(targetExpr instanceof Accessible)) { if (!(targetExpr instanceof Accessible)) {
pos = position; pos = position;
return null; return null;
} }
final TokenType currentType = get(0).getType(); final TokenType currentType = get(0).type();
if (!ASSIGN_OPERATORS.containsKey(currentType)) { if (!ASSIGN_OPERATORS.containsKey(currentType)) {
pos = position; pos = position;
return null; return null;
@ -721,7 +721,7 @@ public final class Parser {
private Expression objectCreation() { private Expression objectCreation() {
if (match(TokenType.NEW)) { if (match(TokenType.NEW)) {
final String className = consume(TokenType.WORD).getText(); final String className = consume(TokenType.WORD).text();
final List<Expression> args = new ArrayList<>(); final List<Expression> args = new ArrayList<>();
consume(TokenType.LPAREN); consume(TokenType.LPAREN);
while (!match(TokenType.RPAREN)) { while (!match(TokenType.RPAREN)) {
@ -765,7 +765,7 @@ public final class Parser {
if (match(TokenType.COLONCOLON)) { if (match(TokenType.COLONCOLON)) {
// ::method reference // ::method reference
final String functionName = consume(TokenType.WORD).getText(); final String functionName = consume(TokenType.WORD).text();
return new FunctionReferenceExpression(functionName); return new FunctionReferenceExpression(functionName);
} }
if (match(TokenType.MATCH)) { if (match(TokenType.MATCH)) {
@ -783,7 +783,7 @@ public final class Parser {
private Expression variable() { private Expression 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).getText())); return functionChain(new ValueExpression(consume(TokenType.WORD).text()));
} }
final Expression qualifiedNameExpr = qualifiedName(); final Expression qualifiedNameExpr = qualifiedName();
@ -818,9 +818,9 @@ public final class Parser {
final List<Expression> indices = variableSuffix(); final List<Expression> indices = variableSuffix();
if (indices == null || indices.isEmpty()) { if (indices == null || indices.isEmpty()) {
return new VariableExpression(current.getText()); return new VariableExpression(current.text());
} }
return new ContainerAccessExpression(current.getText(), indices); return new ContainerAccessExpression(current.text(), indices);
} }
private List<Expression> variableSuffix() { private List<Expression> variableSuffix() {
@ -831,7 +831,7 @@ public final class Parser {
final List<Expression> indices = new ArrayList<>(); final List<Expression> 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).getText(); final String fieldName = consume(TokenType.WORD).text();
final Expression key = new ValueExpression(fieldName); final Expression key = new ValueExpression(fieldName);
indices.add(key); indices.add(key);
} }
@ -846,20 +846,20 @@ public final class Parser {
private Expression value() { private Expression value() {
final Token current = get(0); final Token current = get(0);
if (match(TokenType.NUMBER)) { if (match(TokenType.NUMBER)) {
return new ValueExpression(createNumber(current.getText(), 10)); return new ValueExpression(createNumber(current.text(), 10));
} }
if (match(TokenType.HEX_NUMBER)) { if (match(TokenType.HEX_NUMBER)) {
return new ValueExpression(createNumber(current.getText(), 16)); return new ValueExpression(createNumber(current.text(), 16));
} }
if (match(TokenType.TEXT)) { if (match(TokenType.TEXT)) {
final ValueExpression strExpr = new ValueExpression(current.getText()); final ValueExpression strExpr = new ValueExpression(current.text());
// "text".property || "text".func() // "text".property || "text".func()
if (lookMatch(0, TokenType.DOT)) { if (lookMatch(0, TokenType.DOT)) {
if (lookMatch(1, TokenType.WORD) && lookMatch(2, TokenType.LPAREN)) { if (lookMatch(1, TokenType.WORD) && lookMatch(2, TokenType.LPAREN)) {
match(TokenType.DOT); match(TokenType.DOT);
return functionChain(new ContainerAccessExpression( return functionChain(new ContainerAccessExpression(
strExpr, Collections.singletonList( strExpr, Collections.singletonList(
new ValueExpression(consume(TokenType.WORD).getText()) new ValueExpression(consume(TokenType.WORD).text())
))); )));
} }
final List<Expression> indices = variableSuffix(); final List<Expression> indices = variableSuffix();
@ -888,7 +888,7 @@ public final class Parser {
private Token consume(TokenType type) { private Token consume(TokenType type) {
final Token current = get(0); final Token current = get(0);
if (type != current.getType()) { if (type != current.type()) {
throw new ParseException("Token " + current + " doesn't match " + type); throw new ParseException("Token " + current + " doesn't match " + type);
} }
pos++; pos++;
@ -897,7 +897,7 @@ public final class Parser {
private boolean match(TokenType type) { private boolean match(TokenType type) {
final Token current = get(0); final Token current = get(0);
if (type != current.getType()) { if (type != current.type()) {
return false; return false;
} }
pos++; pos++;
@ -905,7 +905,7 @@ public final class Parser {
} }
private boolean lookMatch(int pos, TokenType type) { private boolean lookMatch(int pos, TokenType type) {
return get(pos).getType() == type; return get(pos).type() == type;
} }
private Token get(int relativePosition) { private Token get(int relativePosition) {

View File

@ -1,38 +1,10 @@
package com.annimon.ownlang.parser; package com.annimon.ownlang.parser;
/** /**
*
* @author aNNiMON * @author aNNiMON
*/ */
public final class Token { public record Token(TokenType type, String text, int row, int col) {
private final TokenType type;
private final String text;
private final int row, col;
public Token(TokenType type, String text, int row, int col) {
this.type = type;
this.text = text;
this.row = row;
this.col = col;
}
public TokenType getType() {
return type;
}
public String getText() {
return text;
}
public int getRow() {
return row;
}
public int getCol() {
return col;
}
public String position() { public String position() {
return "[" + row + " " + col + "]"; return "[" + row + " " + col + "]";
} }

View File

@ -1,27 +1,11 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
public final class Argument { public record Argument(String name, Expression valueExpr) {
private final String name;
private final Expression valueExpr;
public Argument(String name) { public Argument(String name) {
this(name, null); this(name, null);
} }
public Argument(String name, Expression valueExpr) {
this.name = name;
this.valueExpr = valueExpr;
}
public String getName() {
return name;
}
public Expression getValueExpr() {
return valueExpr;
}
@Override @Override
public String toString() { public String toString() {
return name + (valueExpr == null ? "" : " = " + valueExpr); return name + (valueExpr == null ? "" : " = " + valueExpr);

View File

@ -22,8 +22,8 @@ public final class ObjectCreationExpression implements Expression {
// Is Instantiable? // Is Instantiable?
if (Variables.isExists(className)) { if (Variables.isExists(className)) {
final Value variable = Variables.get(className); final Value variable = Variables.get(className);
if (variable instanceof Instantiable) { if (variable instanceof Instantiable instantiable) {
return ((Instantiable) variable).newInstance(ctorArgs()); return instantiable.newInstance(ctorArgs());
} }
} }
throw new UnknownClassException(className); throw new UnknownClassException(className);

View File

@ -13,8 +13,8 @@ public final class AssignValidator extends LintVisitor {
@Override @Override
public void visit(AssignmentExpression s) { public void visit(AssignmentExpression s) {
super.visit(s); super.visit(s);
if (s.target instanceof VariableExpression) { if (s.target instanceof VariableExpression varExpr) {
final String variable = ((VariableExpression) s.target).name; final String variable = varExpr.name;
if (Variables.isExists(variable)) { if (Variables.isExists(variable)) {
Console.error(String.format( Console.error(String.format(
"Warning: variable \"%s\" overrides constant", variable)); "Warning: variable \"%s\" overrides constant", variable));

View File

@ -50,7 +50,7 @@ public class ConstantPropagation extends OptimizationVisitor<Map<String, Value>>
public String summaryInfo() { public String summaryInfo() {
if (optimizationsCount() == 0) return ""; if (optimizationsCount() == 0) return "";
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
if (propagatedVariables.size() > 0) { if (!propagatedVariables.isEmpty()) {
sb.append("\nConstant propagations: ").append(propagatedVariables.size()); sb.append("\nConstant propagations: ").append(propagatedVariables.size());
for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) { for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) {
sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue()); sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue());

View File

@ -128,16 +128,15 @@ public class DeadCodeElimination extends OptimizationVisitor<Map<String, Variabl
if (node != statement) { if (node != statement) {
changed = true; changed = true;
} }
if (node instanceof ExprStatement if (node instanceof ExprStatement expr && isConstantValue(expr.expr)) {
&& isConstantValue( ((ExprStatement) node).expr )) {
changed = true; changed = true;
continue; continue;
} }
if (node instanceof Statement) { if (node instanceof Statement stmt) {
result.add((Statement) node); result.add(stmt);
} else if (node instanceof Expression) { } else if (node instanceof Expression expr) {
result.add(new ExprStatement((Expression) node)); result.add(new ExprStatement(expr));
} }
} }
if (changed) { if (changed) {

View File

@ -261,8 +261,8 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
boolean changed = expression != s.expression; boolean changed = expression != s.expression;
final List<MatchExpression.Pattern> patterns = new ArrayList<>(s.patterns.size()); final List<MatchExpression.Pattern> patterns = new ArrayList<>(s.patterns.size());
for (MatchExpression.Pattern pattern : s.patterns) { for (MatchExpression.Pattern pattern : s.patterns) {
if (pattern instanceof MatchExpression.VariablePattern) { if (pattern instanceof MatchExpression.VariablePattern varPattern) {
final String variable = ((MatchExpression.VariablePattern) pattern).variable; final String variable = varPattern.variable;
final VariableExpression expr = new VariableExpression(variable); final VariableExpression expr = new VariableExpression(variable);
final Node node = expr.accept(this, t); final Node node = expr.accept(this, t);
if ((node != expr) && isValue(node)) { if ((node != expr) && isValue(node)) {
@ -276,8 +276,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
} }
} }
if (pattern instanceof MatchExpression.TuplePattern) { if (pattern instanceof MatchExpression.TuplePattern tuple) {
final MatchExpression.TuplePattern tuple = (MatchExpression.TuplePattern) pattern;
final List<Expression> newValues = new ArrayList<>(tuple.values.size()); final List<Expression> newValues = new ArrayList<>(tuple.values.size());
boolean valuesChanged = false; boolean valuesChanged = false;
for (Expression value : tuple.values) { for (Expression value : tuple.values) {
@ -437,15 +436,15 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
protected boolean visit(final Arguments in, final Arguments out, T t) { protected boolean visit(final Arguments in, final Arguments out, T t) {
boolean changed = false; boolean changed = false;
for (Argument argument : in) { for (Argument argument : in) {
final Expression valueExpr = argument.getValueExpr(); final Expression valueExpr = argument.valueExpr();
if (valueExpr == null) { if (valueExpr == null) {
out.addRequired(argument.getName()); out.addRequired(argument.name());
} else { } else {
final Node expr = valueExpr.accept(this, t); final Node expr = valueExpr.accept(this, t);
if (expr != valueExpr) { if (expr != valueExpr) {
changed = true; changed = true;
} }
out.addOptional(argument.getName(), (Expression) expr); out.addOptional(argument.name(), (Expression) expr);
} }
} }
return changed; return changed;

View File

@ -32,7 +32,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
@Override @Override
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) { public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
if (!isVariable((Node)s.target)) { if (!isVariable(s.target)) {
return super.visit(s, t); return super.visit(s, t);
} }
@ -71,8 +71,8 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
@Override @Override
public Node visit(MatchExpression s, Map<String, VariableInfo> t) { public Node visit(MatchExpression s, Map<String, VariableInfo> t) {
for (MatchExpression.Pattern pattern : s.patterns) { for (MatchExpression.Pattern pattern : s.patterns) {
if (pattern instanceof MatchExpression.VariablePattern) { if (pattern instanceof MatchExpression.VariablePattern varPattern) {
final String variableName = ((MatchExpression.VariablePattern) pattern).variable; final String variableName = varPattern.variable;
t.put(variableName, variableInfo(t, variableName)); t.put(variableName, variableInfo(t, variableName));
} }
} }
@ -82,12 +82,11 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
@Override @Override
public Node visit(UnaryExpression s, Map<String, VariableInfo> t) { public Node visit(UnaryExpression s, Map<String, VariableInfo> t) {
if (s.expr1 instanceof Accessible) { if (s.expr1 instanceof Accessible) {
if (s.expr1 instanceof VariableExpression) { if (s.expr1 instanceof VariableExpression varExpr) {
final String variableName = ((VariableExpression) s.expr1).name; final String variableName = varExpr.name;
t.put(variableName, variableInfo(t, variableName)); t.put(variableName, variableInfo(t, variableName));
} }
if (s.expr1 instanceof ContainerAccessExpression) { if (s.expr1 instanceof ContainerAccessExpression conExpr) {
ContainerAccessExpression conExpr = (ContainerAccessExpression) s.expr1;
if (conExpr.rootIsVariable()) { if (conExpr.rootIsVariable()) {
final String variableName = ((VariableExpression) conExpr.root).name; final String variableName = ((VariableExpression) conExpr.root).name;
t.put(variableName, variableInfo(t, variableName)); t.put(variableName, variableInfo(t, variableName));
@ -119,8 +118,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
} }
private boolean canLoadConstants(Expression expression) { private boolean canLoadConstants(Expression expression) {
if (expression instanceof ArrayExpression) { if (expression instanceof ArrayExpression ae) {
ArrayExpression ae = (ArrayExpression) expression;
for (Expression expr : ae.elements) { for (Expression expr : ae.elements) {
if (!isValue(expr)) { if (!isValue(expr)) {
return false; return false;
@ -134,7 +132,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
@Override @Override
protected boolean visit(Arguments in, Arguments out, Map<String, VariableInfo> t) { protected boolean visit(Arguments in, Arguments out, Map<String, VariableInfo> t) {
for (Argument argument : in) { for (Argument argument : in) {
final String variableName = argument.getName(); final String variableName = argument.name();
final VariableInfo var = variableInfo(t, variableName); final VariableInfo var = variableInfo(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 Expression expr = argument.getValueExpr();

View File

@ -21,10 +21,10 @@ public class LexerTest {
List<Token> expList = list(NUMBER, NUMBER, HEX_NUMBER, HEX_NUMBER, HEX_NUMBER); List<Token> expList = list(NUMBER, NUMBER, HEX_NUMBER, HEX_NUMBER, HEX_NUMBER);
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("0", result.get(0).getText()); assertEquals("0", result.get(0).text());
assertEquals("3.1415", result.get(1).getText()); assertEquals("3.1415", result.get(1).text());
assertEquals("CAFEBABE", result.get(2).getText()); assertEquals("CAFEBABE", result.get(2).text());
assertEquals("f7d6c5", result.get(3).getText()); assertEquals("f7d6c5", result.get(3).text());
} }
@Test @Test
@ -39,7 +39,7 @@ public class LexerTest {
List<Token> expList = list(WORD, EQ, MINUS, NUMBER, PLUS, NUMBER, STAR, NUMBER, PERCENT, NUMBER, SLASH, NUMBER); List<Token> expList = list(WORD, EQ, MINUS, NUMBER, PLUS, NUMBER, STAR, NUMBER, PERCENT, NUMBER, SLASH, NUMBER);
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("x", result.get(0).getText()); assertEquals("x", result.get(0).text());
} }
@Test @Test
@ -64,7 +64,7 @@ public class LexerTest {
List<Token> expList = list(TEXT); List<Token> expList = list(TEXT);
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("1\"2", result.get(0).getText()); assertEquals("1\"2", result.get(0).text());
} }
@Test @Test
@ -73,7 +73,7 @@ public class LexerTest {
List<Token> expList = list(TEXT); List<Token> expList = list(TEXT);
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("", result.get(0).getText()); assertEquals("", result.get(0).text());
} }
@Test @Test
@ -83,7 +83,7 @@ public class LexerTest {
assertThrows(LexerException.class, () -> { assertThrows(LexerException.class, () -> {
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("1", result.get(0).getText()); assertEquals("1", result.get(0).text());
}); });
} }
@ -110,7 +110,7 @@ public class LexerTest {
List<Token> expList = list(NUMBER); List<Token> expList = list(NUMBER);
List<Token> result = Lexer.tokenize(input); List<Token> result = Lexer.tokenize(input);
assertTokens(expList, result); assertTokens(expList, result);
assertEquals("123", result.get(0).getText()); assertEquals("123", result.get(0).text());
} }
@Test @Test
@ -159,7 +159,7 @@ public class LexerTest {
final int length = expList.size(); final int length = expList.size();
assertEquals(length, result.size()); assertEquals(length, result.size());
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
assertEquals(expList.get(i).getType(), result.get(i).getType()); assertEquals(expList.get(i).type(), result.get(i).type());
} }
} }