mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Switch to Java11+ features where possible
This commit is contained in:
parent
8ed89c8a9d
commit
a2549c3afe
@ -52,7 +52,7 @@ public class ArrayValue implements Value, Iterable<Value> {
|
||||
public static StringValue joinToString(ArrayValue array, String delimiter, String prefix, String suffix) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (Value value : array) {
|
||||
if (sb.length() > 0) sb.append(delimiter);
|
||||
if (!sb.isEmpty()) sb.append(delimiter);
|
||||
else sb.append(prefix);
|
||||
sb.append(value.asString());
|
||||
}
|
||||
@ -100,37 +100,26 @@ public class ArrayValue implements Value, Iterable<Value> {
|
||||
}
|
||||
|
||||
public Value get(Value index) {
|
||||
final String prop = index.asString();
|
||||
switch (prop) {
|
||||
return switch (index.asString()) {
|
||||
// Properties
|
||||
case "length":
|
||||
return NumberValue.of(size());
|
||||
case "length" -> NumberValue.of(size());
|
||||
|
||||
// Functions
|
||||
case "isEmpty":
|
||||
return Converters.voidToBoolean(() -> size() == 0);
|
||||
case "joinToString":
|
||||
return new FunctionValue(this::joinToString);
|
||||
|
||||
default:
|
||||
return get(index.asInt());
|
||||
}
|
||||
case "isEmpty" -> Converters.voidToBoolean(() -> size() == 0);
|
||||
case "joinToString" -> new FunctionValue(this::joinToString);
|
||||
default -> get(index.asInt());
|
||||
};
|
||||
}
|
||||
|
||||
public Value joinToString(Value[] args) {
|
||||
Arguments.checkRange(0, 3, args.length);
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
return joinToString(this, "", "", "");
|
||||
case 1:
|
||||
return joinToString(this, args[0].asString(), "", "");
|
||||
case 2:
|
||||
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");
|
||||
}
|
||||
return switch (args.length) {
|
||||
case 0 -> joinToString(this, "", "", "");
|
||||
case 1 -> joinToString(this, args[0].asString(), "", "");
|
||||
case 2 -> joinToString(this, args[0].asString(), args[1].asString(), args[1].asString());
|
||||
case 3 -> 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) {
|
||||
|
@ -25,15 +25,7 @@ public final class CallStack {
|
||||
return calls;
|
||||
}
|
||||
|
||||
public static class CallInfo {
|
||||
String name;
|
||||
Function function;
|
||||
|
||||
public CallInfo(String name, Function function) {
|
||||
this.name = name;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
public record CallInfo(String name, Function function) {
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s: %s", name, function.toString().trim());
|
||||
|
@ -19,56 +19,46 @@ public final class StringValue implements Value {
|
||||
|
||||
public Value access(Value propertyValue) {
|
||||
final String prop = propertyValue.asString();
|
||||
switch (prop) {
|
||||
return switch (prop) {
|
||||
// Properties
|
||||
case "length":
|
||||
return NumberValue.of(length());
|
||||
case "lower":
|
||||
return new StringValue(value.toLowerCase());
|
||||
case "upper":
|
||||
return new StringValue(value.toUpperCase());
|
||||
case "chars": {
|
||||
case "length" -> NumberValue.of(length());
|
||||
case "lower" -> new StringValue(value.toLowerCase());
|
||||
case "upper" -> new StringValue(value.toUpperCase());
|
||||
case "chars" -> {
|
||||
final Value[] chars = new Value[length()];
|
||||
int i = 0;
|
||||
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
|
||||
case "trim":
|
||||
return Converters.voidToString(value::trim);
|
||||
case "startsWith":
|
||||
return new FunctionValue(args -> {
|
||||
case "trim" -> Converters.voidToString(value::trim);
|
||||
case "startsWith" -> new FunctionValue(args -> {
|
||||
Arguments.checkOrOr(1, 2, args.length);
|
||||
int offset = (args.length == 2) ? args[1].asInt() : 0;
|
||||
return NumberValue.fromBoolean(value.startsWith(args[0].asString(), offset));
|
||||
});
|
||||
case "endsWith":
|
||||
return Converters.stringToBoolean(value::endsWith);
|
||||
case "matches":
|
||||
return Converters.stringToBoolean(value::matches);
|
||||
case "contains":
|
||||
return Converters.stringToBoolean(value::contains);
|
||||
case "equalsIgnoreCase":
|
||||
return Converters.stringToBoolean(value::equalsIgnoreCase);
|
||||
case "isEmpty":
|
||||
return Converters.voidToBoolean(value::isEmpty);
|
||||
case "endsWith" -> Converters.stringToBoolean(value::endsWith);
|
||||
case "matches" -> Converters.stringToBoolean(value::matches);
|
||||
case "contains" -> Converters.stringToBoolean(value::contains);
|
||||
case "equalsIgnoreCase" -> Converters.stringToBoolean(value::equalsIgnoreCase);
|
||||
case "isEmpty" -> Converters.voidToBoolean(value::isEmpty);
|
||||
|
||||
default:
|
||||
default -> {
|
||||
if (Functions.isExists(prop)) {
|
||||
final Function f = Functions.get(prop);
|
||||
return new FunctionValue(args -> {
|
||||
yield new FunctionValue(args -> {
|
||||
final Value[] newArgs = new Value[args.length + 1];
|
||||
newArgs[0] = this;
|
||||
System.arraycopy(args, 0, newArgs, 1, args.length);
|
||||
return f.execute(newArgs);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
throw new UnknownPropertyException(prop);
|
||||
throw new UnknownPropertyException(prop);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int length() {
|
||||
|
@ -14,18 +14,13 @@ public final class ValueUtils {
|
||||
private ValueUtils() { }
|
||||
|
||||
public static Object toObject(Value val) {
|
||||
switch (val.type()) {
|
||||
case Types.ARRAY:
|
||||
return toObject((ArrayValue) val);
|
||||
case Types.MAP:
|
||||
return toObject((MapValue) val);
|
||||
case Types.NUMBER:
|
||||
return val.raw();
|
||||
case Types.STRING:
|
||||
return val.asString();
|
||||
default:
|
||||
return JSONObject.NULL;
|
||||
}
|
||||
return switch (val.type()) {
|
||||
case Types.ARRAY -> toObject((ArrayValue) val);
|
||||
case Types.MAP -> toObject((MapValue) val);
|
||||
case Types.NUMBER -> val.raw();
|
||||
case Types.STRING -> val.asString();
|
||||
default -> JSONObject.NULL;
|
||||
};
|
||||
}
|
||||
|
||||
public static JSONObject toObject(MapValue map) {
|
||||
@ -47,20 +42,20 @@ public final class ValueUtils {
|
||||
}
|
||||
|
||||
public static Value toValue(Object obj) {
|
||||
if (obj instanceof JSONObject) {
|
||||
return toValue((JSONObject) obj);
|
||||
if (obj instanceof JSONObject jsonObj) {
|
||||
return toValue(jsonObj);
|
||||
}
|
||||
if (obj instanceof JSONArray) {
|
||||
return toValue((JSONArray) obj);
|
||||
if (obj instanceof JSONArray jsonArr) {
|
||||
return toValue(jsonArr);
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
return new StringValue((String) obj);
|
||||
if (obj instanceof String str) {
|
||||
return new StringValue(str);
|
||||
}
|
||||
if (obj instanceof Number) {
|
||||
return NumberValue.of(((Number) obj));
|
||||
if (obj instanceof Number num) {
|
||||
return NumberValue.of(num);
|
||||
}
|
||||
if (obj instanceof Boolean) {
|
||||
return NumberValue.fromBoolean((Boolean) obj);
|
||||
if (obj instanceof Boolean flag) {
|
||||
return NumberValue.fromBoolean(flag);
|
||||
}
|
||||
// NULL or other
|
||||
return NumberValue.ZERO;
|
||||
@ -119,6 +114,7 @@ public final class ValueUtils {
|
||||
return ((FunctionValue) value).getValue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Number> MapValue collectNumberConstants(Class<?> clazz, Class<T> type) {
|
||||
MapValue result = new MapValue(20);
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
|
@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ConsoleOutputSettings implements OutputSettings {
|
||||
public non-sealed class ConsoleOutputSettings implements OutputSettings {
|
||||
|
||||
@Override
|
||||
public String newline() {
|
||||
|
@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface OutputSettings {
|
||||
public sealed interface OutputSettings permits ConsoleOutputSettings, StringOutputSettings {
|
||||
|
||||
String newline();
|
||||
|
||||
|
@ -2,7 +2,7 @@ package com.annimon.ownlang.outputsettings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class StringOutputSettings implements OutputSettings {
|
||||
public non-sealed class StringOutputSettings implements OutputSettings {
|
||||
|
||||
private final StringBuffer out, err;
|
||||
|
||||
|
@ -27,7 +27,7 @@ public class UserDefinedFunction implements Function {
|
||||
|
||||
public String getArgsName(int index) {
|
||||
if (index < 0 || index >= getArgsCount()) return "";
|
||||
return arguments.get(index).getName();
|
||||
return arguments.get(index).name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -52,7 +52,7 @@ public class UserDefinedFunction implements Function {
|
||||
// Optional args if exists
|
||||
for (int i = size; i < totalArgsCount; i++) {
|
||||
final Argument arg = arguments.get(i);
|
||||
Variables.define(arg.getName(), arg.getValueExpr().eval());
|
||||
Variables.define(arg.name(), arg.valueExpr().eval());
|
||||
}
|
||||
body.execute();
|
||||
return NumberValue.ZERO;
|
||||
@ -65,8 +65,8 @@ public class UserDefinedFunction implements Function {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (body instanceof ReturnStatement) {
|
||||
return String.format("def%s = %s", arguments, ((ReturnStatement)body).expression);
|
||||
if (body instanceof ReturnStatement returnStmt) {
|
||||
return String.format("def%s = %s", arguments, returnStmt.expression);
|
||||
}
|
||||
return String.format("def%s %s", arguments, body);
|
||||
}
|
||||
|
@ -86,8 +86,8 @@ public final class Parser {
|
||||
|
||||
private int getErrorLine() {
|
||||
if (size == 0) return 0;
|
||||
if (pos >= size) return tokens.get(size - 1).getRow();
|
||||
return tokens.get(pos).getRow();
|
||||
if (pos >= size) return tokens.get(size - 1).row();
|
||||
return tokens.get(pos).row();
|
||||
}
|
||||
|
||||
private void recover() {
|
||||
@ -185,7 +185,7 @@ public final class Parser {
|
||||
final List<String> variables = new ArrayList<>();
|
||||
while (!match(TokenType.RPAREN)) {
|
||||
if (lookMatch(0, TokenType.WORD)) {
|
||||
variables.add(consume(TokenType.WORD).getText());
|
||||
variables.add(consume(TokenType.WORD).text());
|
||||
} else {
|
||||
variables.add(null);
|
||||
}
|
||||
@ -250,7 +250,7 @@ public final class Parser {
|
||||
private ForeachArrayStatement foreachArrayStatement() {
|
||||
// for x : arr
|
||||
boolean optParentheses = match(TokenType.LPAREN);
|
||||
final String variable = consume(TokenType.WORD).getText();
|
||||
final String variable = consume(TokenType.WORD).text();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
if (optParentheses) {
|
||||
@ -263,9 +263,9 @@ public final class Parser {
|
||||
private ForeachMapStatement foreachMapStatement() {
|
||||
// for k, v : map
|
||||
boolean optParentheses = match(TokenType.LPAREN);
|
||||
final String key = consume(TokenType.WORD).getText();
|
||||
final String key = consume(TokenType.WORD).text();
|
||||
consume(TokenType.COMMA);
|
||||
final String value = consume(TokenType.WORD).getText();
|
||||
final String value = consume(TokenType.WORD).text();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
if (optParentheses) {
|
||||
@ -277,7 +277,7 @@ public final class Parser {
|
||||
|
||||
private FunctionDefineStatement functionDefine() {
|
||||
// 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 Statement body = statementBody();
|
||||
return new FunctionDefineStatement(name, arguments, body);
|
||||
@ -289,7 +289,7 @@ public final class Parser {
|
||||
boolean startsOptionalArgs = false;
|
||||
consume(TokenType.LPAREN);
|
||||
while (!match(TokenType.RPAREN)) {
|
||||
final String name = consume(TokenType.WORD).getText();
|
||||
final String name = consume(TokenType.WORD).text();
|
||||
if (match(TokenType.EQ)) {
|
||||
startsOptionalArgs = true;
|
||||
arguments.addOptional(name, variable());
|
||||
@ -383,26 +383,26 @@ public final class Parser {
|
||||
if (match(TokenType.NUMBER)) {
|
||||
// case 0.5:
|
||||
pattern = new MatchExpression.ConstantPattern(
|
||||
NumberValue.of(createNumber(current.getText(), 10))
|
||||
NumberValue.of(createNumber(current.text(), 10))
|
||||
);
|
||||
} else if (match(TokenType.HEX_NUMBER)) {
|
||||
// case #FF:
|
||||
pattern = new MatchExpression.ConstantPattern(
|
||||
NumberValue.of(createNumber(current.getText(), 16))
|
||||
NumberValue.of(createNumber(current.text(), 16))
|
||||
);
|
||||
} else if (match(TokenType.TEXT)) {
|
||||
// case "text":
|
||||
pattern = new MatchExpression.ConstantPattern(
|
||||
new StringValue(current.getText())
|
||||
new StringValue(current.text())
|
||||
);
|
||||
} else if (match(TokenType.WORD)) {
|
||||
// case value:
|
||||
pattern = new MatchExpression.VariablePattern(current.getText());
|
||||
pattern = new MatchExpression.VariablePattern(current.text());
|
||||
} else if (match(TokenType.LBRACKET)) {
|
||||
// case [x :: xs]:
|
||||
final MatchExpression.ListPattern listPattern = new MatchExpression.ListPattern();
|
||||
while (!match(TokenType.RBRACKET)) {
|
||||
listPattern.add(consume(TokenType.WORD).getText());
|
||||
listPattern.add(consume(TokenType.WORD).text());
|
||||
match(TokenType.COLONCOLON);
|
||||
}
|
||||
pattern = listPattern;
|
||||
@ -410,7 +410,7 @@ public final class Parser {
|
||||
// case (1, 2):
|
||||
final MatchExpression.TuplePattern tuplePattern = new MatchExpression.TuplePattern();
|
||||
while (!match(TokenType.RPAREN)) {
|
||||
if ("_".equals(get(0).getText())) {
|
||||
if ("_".equals(get(0).text())) {
|
||||
tuplePattern.addAny();
|
||||
consume(TokenType.WORD);
|
||||
} else {
|
||||
@ -447,7 +447,7 @@ public final class Parser {
|
||||
// str = ""
|
||||
// def method() = str
|
||||
// }
|
||||
final String name = consume(TokenType.WORD).getText();
|
||||
final String name = consume(TokenType.WORD).text();
|
||||
final ClassDeclarationStatement classDeclaration = new ClassDeclarationStatement(name);
|
||||
consume(TokenType.LBRACE);
|
||||
do {
|
||||
@ -481,12 +481,12 @@ public final class Parser {
|
||||
// x[0].prop += ...
|
||||
final int position = pos;
|
||||
final Expression targetExpr = qualifiedName();
|
||||
if ((targetExpr == null) || !(targetExpr instanceof Accessible)) {
|
||||
if (!(targetExpr instanceof Accessible)) {
|
||||
pos = position;
|
||||
return null;
|
||||
}
|
||||
|
||||
final TokenType currentType = get(0).getType();
|
||||
final TokenType currentType = get(0).type();
|
||||
if (!ASSIGN_OPERATORS.containsKey(currentType)) {
|
||||
pos = position;
|
||||
return null;
|
||||
@ -721,7 +721,7 @@ public final class Parser {
|
||||
|
||||
private Expression objectCreation() {
|
||||
if (match(TokenType.NEW)) {
|
||||
final String className = consume(TokenType.WORD).getText();
|
||||
final String className = consume(TokenType.WORD).text();
|
||||
final List<Expression> args = new ArrayList<>();
|
||||
consume(TokenType.LPAREN);
|
||||
while (!match(TokenType.RPAREN)) {
|
||||
@ -765,7 +765,7 @@ public final class Parser {
|
||||
|
||||
if (match(TokenType.COLONCOLON)) {
|
||||
// ::method reference
|
||||
final String functionName = consume(TokenType.WORD).getText();
|
||||
final String functionName = consume(TokenType.WORD).text();
|
||||
return new FunctionReferenceExpression(functionName);
|
||||
}
|
||||
if (match(TokenType.MATCH)) {
|
||||
@ -783,7 +783,7 @@ public final class Parser {
|
||||
private Expression variable() {
|
||||
// function(...
|
||||
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();
|
||||
@ -818,9 +818,9 @@ public final class Parser {
|
||||
|
||||
final List<Expression> indices = variableSuffix();
|
||||
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() {
|
||||
@ -831,7 +831,7 @@ public final class Parser {
|
||||
final List<Expression> indices = new ArrayList<>();
|
||||
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
||||
if (match(TokenType.DOT)) {
|
||||
final String fieldName = consume(TokenType.WORD).getText();
|
||||
final String fieldName = consume(TokenType.WORD).text();
|
||||
final Expression key = new ValueExpression(fieldName);
|
||||
indices.add(key);
|
||||
}
|
||||
@ -846,20 +846,20 @@ public final class Parser {
|
||||
private Expression value() {
|
||||
final Token current = get(0);
|
||||
if (match(TokenType.NUMBER)) {
|
||||
return new ValueExpression(createNumber(current.getText(), 10));
|
||||
return new ValueExpression(createNumber(current.text(), 10));
|
||||
}
|
||||
if (match(TokenType.HEX_NUMBER)) {
|
||||
return new ValueExpression(createNumber(current.getText(), 16));
|
||||
return new ValueExpression(createNumber(current.text(), 16));
|
||||
}
|
||||
if (match(TokenType.TEXT)) {
|
||||
final ValueExpression strExpr = new ValueExpression(current.getText());
|
||||
final ValueExpression strExpr = new ValueExpression(current.text());
|
||||
// "text".property || "text".func()
|
||||
if (lookMatch(0, TokenType.DOT)) {
|
||||
if (lookMatch(1, TokenType.WORD) && lookMatch(2, TokenType.LPAREN)) {
|
||||
match(TokenType.DOT);
|
||||
return functionChain(new ContainerAccessExpression(
|
||||
strExpr, Collections.singletonList(
|
||||
new ValueExpression(consume(TokenType.WORD).getText())
|
||||
new ValueExpression(consume(TokenType.WORD).text())
|
||||
)));
|
||||
}
|
||||
final List<Expression> indices = variableSuffix();
|
||||
@ -888,7 +888,7 @@ public final class Parser {
|
||||
|
||||
private Token consume(TokenType type) {
|
||||
final Token current = get(0);
|
||||
if (type != current.getType()) {
|
||||
if (type != current.type()) {
|
||||
throw new ParseException("Token " + current + " doesn't match " + type);
|
||||
}
|
||||
pos++;
|
||||
@ -897,7 +897,7 @@ public final class Parser {
|
||||
|
||||
private boolean match(TokenType type) {
|
||||
final Token current = get(0);
|
||||
if (type != current.getType()) {
|
||||
if (type != current.type()) {
|
||||
return false;
|
||||
}
|
||||
pos++;
|
||||
@ -905,7 +905,7 @@ public final class Parser {
|
||||
}
|
||||
|
||||
private boolean lookMatch(int pos, TokenType type) {
|
||||
return get(pos).getType() == type;
|
||||
return get(pos).type() == type;
|
||||
}
|
||||
|
||||
private Token get(int relativePosition) {
|
||||
|
@ -1,38 +1,10 @@
|
||||
package com.annimon.ownlang.parser;
|
||||
|
||||
/**
|
||||
*
|
||||
* @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() {
|
||||
return "[" + row + " " + col + "]";
|
||||
}
|
||||
|
@ -1,27 +1,11 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
public final class Argument {
|
||||
|
||||
private final String name;
|
||||
private final Expression valueExpr;
|
||||
public record Argument(String name, Expression valueExpr) {
|
||||
|
||||
public Argument(String name) {
|
||||
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
|
||||
public String toString() {
|
||||
return name + (valueExpr == null ? "" : " = " + valueExpr);
|
||||
|
@ -22,8 +22,8 @@ public final class ObjectCreationExpression implements Expression {
|
||||
// Is Instantiable?
|
||||
if (Variables.isExists(className)) {
|
||||
final Value variable = Variables.get(className);
|
||||
if (variable instanceof Instantiable) {
|
||||
return ((Instantiable) variable).newInstance(ctorArgs());
|
||||
if (variable instanceof Instantiable instantiable) {
|
||||
return instantiable.newInstance(ctorArgs());
|
||||
}
|
||||
}
|
||||
throw new UnknownClassException(className);
|
||||
|
@ -13,8 +13,8 @@ public final class AssignValidator extends LintVisitor {
|
||||
@Override
|
||||
public void visit(AssignmentExpression s) {
|
||||
super.visit(s);
|
||||
if (s.target instanceof VariableExpression) {
|
||||
final String variable = ((VariableExpression) s.target).name;
|
||||
if (s.target instanceof VariableExpression varExpr) {
|
||||
final String variable = varExpr.name;
|
||||
if (Variables.isExists(variable)) {
|
||||
Console.error(String.format(
|
||||
"Warning: variable \"%s\" overrides constant", variable));
|
||||
|
@ -50,7 +50,7 @@ public class ConstantPropagation extends OptimizationVisitor<Map<String, Value>>
|
||||
public String summaryInfo() {
|
||||
if (optimizationsCount() == 0) return "";
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
if (propagatedVariables.size() > 0) {
|
||||
if (!propagatedVariables.isEmpty()) {
|
||||
sb.append("\nConstant propagations: ").append(propagatedVariables.size());
|
||||
for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) {
|
||||
sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue());
|
||||
|
@ -128,16 +128,15 @@ public class DeadCodeElimination extends OptimizationVisitor<Map<String, Variabl
|
||||
if (node != statement) {
|
||||
changed = true;
|
||||
}
|
||||
if (node instanceof ExprStatement
|
||||
&& isConstantValue( ((ExprStatement) node).expr )) {
|
||||
if (node instanceof ExprStatement expr && isConstantValue(expr.expr)) {
|
||||
changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node instanceof Statement) {
|
||||
result.add((Statement) node);
|
||||
} else if (node instanceof Expression) {
|
||||
result.add(new ExprStatement((Expression) node));
|
||||
if (node instanceof Statement stmt) {
|
||||
result.add(stmt);
|
||||
} else if (node instanceof Expression expr) {
|
||||
result.add(new ExprStatement(expr));
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
|
@ -261,8 +261,8 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
boolean changed = expression != s.expression;
|
||||
final List<MatchExpression.Pattern> patterns = new ArrayList<>(s.patterns.size());
|
||||
for (MatchExpression.Pattern pattern : s.patterns) {
|
||||
if (pattern instanceof MatchExpression.VariablePattern) {
|
||||
final String variable = ((MatchExpression.VariablePattern) pattern).variable;
|
||||
if (pattern instanceof MatchExpression.VariablePattern varPattern) {
|
||||
final String variable = varPattern.variable;
|
||||
final VariableExpression expr = new VariableExpression(variable);
|
||||
final Node node = expr.accept(this, t);
|
||||
if ((node != expr) && isValue(node)) {
|
||||
@ -276,8 +276,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
|
||||
}
|
||||
}
|
||||
|
||||
if (pattern instanceof MatchExpression.TuplePattern) {
|
||||
final MatchExpression.TuplePattern tuple = (MatchExpression.TuplePattern) pattern;
|
||||
if (pattern instanceof MatchExpression.TuplePattern tuple) {
|
||||
final List<Expression> newValues = new ArrayList<>(tuple.values.size());
|
||||
boolean valuesChanged = false;
|
||||
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) {
|
||||
boolean changed = false;
|
||||
for (Argument argument : in) {
|
||||
final Expression valueExpr = argument.getValueExpr();
|
||||
final Expression valueExpr = argument.valueExpr();
|
||||
if (valueExpr == null) {
|
||||
out.addRequired(argument.getName());
|
||||
out.addRequired(argument.name());
|
||||
} else {
|
||||
final Node expr = valueExpr.accept(this, t);
|
||||
if (expr != valueExpr) {
|
||||
changed = true;
|
||||
}
|
||||
out.addOptional(argument.getName(), (Expression) expr);
|
||||
out.addOptional(argument.name(), (Expression) expr);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
|
@ -32,7 +32,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
|
||||
@Override
|
||||
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
|
||||
if (!isVariable((Node)s.target)) {
|
||||
if (!isVariable(s.target)) {
|
||||
return super.visit(s, t);
|
||||
}
|
||||
|
||||
@ -71,8 +71,8 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
@Override
|
||||
public Node visit(MatchExpression s, Map<String, VariableInfo> t) {
|
||||
for (MatchExpression.Pattern pattern : s.patterns) {
|
||||
if (pattern instanceof MatchExpression.VariablePattern) {
|
||||
final String variableName = ((MatchExpression.VariablePattern) pattern).variable;
|
||||
if (pattern instanceof MatchExpression.VariablePattern varPattern) {
|
||||
final String variableName = varPattern.variable;
|
||||
t.put(variableName, variableInfo(t, variableName));
|
||||
}
|
||||
}
|
||||
@ -82,12 +82,11 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
@Override
|
||||
public Node visit(UnaryExpression s, Map<String, VariableInfo> t) {
|
||||
if (s.expr1 instanceof Accessible) {
|
||||
if (s.expr1 instanceof VariableExpression) {
|
||||
final String variableName = ((VariableExpression) s.expr1).name;
|
||||
if (s.expr1 instanceof VariableExpression varExpr) {
|
||||
final String variableName = varExpr.name;
|
||||
t.put(variableName, variableInfo(t, variableName));
|
||||
}
|
||||
if (s.expr1 instanceof ContainerAccessExpression) {
|
||||
ContainerAccessExpression conExpr = (ContainerAccessExpression) s.expr1;
|
||||
if (s.expr1 instanceof ContainerAccessExpression conExpr) {
|
||||
if (conExpr.rootIsVariable()) {
|
||||
final String variableName = ((VariableExpression) conExpr.root).name;
|
||||
t.put(variableName, variableInfo(t, variableName));
|
||||
@ -119,8 +118,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
}
|
||||
|
||||
private boolean canLoadConstants(Expression expression) {
|
||||
if (expression instanceof ArrayExpression) {
|
||||
ArrayExpression ae = (ArrayExpression) expression;
|
||||
if (expression instanceof ArrayExpression ae) {
|
||||
for (Expression expr : ae.elements) {
|
||||
if (!isValue(expr)) {
|
||||
return false;
|
||||
@ -134,7 +132,7 @@ public class VariablesGrabber extends OptimizationVisitor<Map<String, VariableIn
|
||||
@Override
|
||||
protected boolean visit(Arguments in, Arguments out, Map<String, VariableInfo> t) {
|
||||
for (Argument argument : in) {
|
||||
final String variableName = argument.getName();
|
||||
final String variableName = argument.name();
|
||||
final VariableInfo var = variableInfo(t, variableName);
|
||||
/* No need to add value - it is optional arguments
|
||||
final Expression expr = argument.getValueExpr();
|
||||
|
@ -21,10 +21,10 @@ public class LexerTest {
|
||||
List<Token> expList = list(NUMBER, NUMBER, HEX_NUMBER, HEX_NUMBER, HEX_NUMBER);
|
||||
List<Token> result = Lexer.tokenize(input);
|
||||
assertTokens(expList, result);
|
||||
assertEquals("0", result.get(0).getText());
|
||||
assertEquals("3.1415", result.get(1).getText());
|
||||
assertEquals("CAFEBABE", result.get(2).getText());
|
||||
assertEquals("f7d6c5", result.get(3).getText());
|
||||
assertEquals("0", result.get(0).text());
|
||||
assertEquals("3.1415", result.get(1).text());
|
||||
assertEquals("CAFEBABE", result.get(2).text());
|
||||
assertEquals("f7d6c5", result.get(3).text());
|
||||
}
|
||||
|
||||
@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> result = Lexer.tokenize(input);
|
||||
assertTokens(expList, result);
|
||||
assertEquals("x", result.get(0).getText());
|
||||
assertEquals("x", result.get(0).text());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -64,7 +64,7 @@ public class LexerTest {
|
||||
List<Token> expList = list(TEXT);
|
||||
List<Token> result = Lexer.tokenize(input);
|
||||
assertTokens(expList, result);
|
||||
assertEquals("1\"2", result.get(0).getText());
|
||||
assertEquals("1\"2", result.get(0).text());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -73,7 +73,7 @@ public class LexerTest {
|
||||
List<Token> expList = list(TEXT);
|
||||
List<Token> result = Lexer.tokenize(input);
|
||||
assertTokens(expList, result);
|
||||
assertEquals("", result.get(0).getText());
|
||||
assertEquals("", result.get(0).text());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -83,7 +83,7 @@ public class LexerTest {
|
||||
assertThrows(LexerException.class, () -> {
|
||||
List<Token> result = Lexer.tokenize(input);
|
||||
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> result = Lexer.tokenize(input);
|
||||
assertTokens(expList, result);
|
||||
assertEquals("123", result.get(0).getText());
|
||||
assertEquals("123", result.get(0).text());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -159,7 +159,7 @@ public class LexerTest {
|
||||
final int length = expList.size();
|
||||
assertEquals(length, result.size());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user