mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-03 22:36:10 +00:00
More refactoring
This commit is contained in:
@@ -16,8 +16,6 @@ import java.util.Map;
|
||||
import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Block;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Executable;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Statement;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Keyword;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Expression;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder;
|
||||
@@ -96,51 +94,35 @@ public class Parser {
|
||||
return new Executable(parseBlock(new Tokenizer(source), false, scopeBuilder), scopeBuilder);
|
||||
}
|
||||
|
||||
private Keyword<?> parseLoopLike(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) throws ParseException {
|
||||
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
|
||||
|
||||
return switch(identifier.getType()) {
|
||||
case FOR_LOOP -> parseForLoop(tokens, identifier.getPosition(), scopeBuilder);
|
||||
case IF_STATEMENT -> parseIfStatement(tokens, identifier.getPosition(), loop, scopeBuilder);
|
||||
case WHILE_LOOP -> parseWhileLoop(tokens, identifier.getPosition(), scopeBuilder);
|
||||
default -> throw new UnsupportedOperationException(
|
||||
"Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
};
|
||||
}
|
||||
|
||||
private WhileKeyword parseWhileLoop(Tokenizer tokens, SourcePosition start, ScopeBuilder scopeBuilder) {
|
||||
Expression<?> first = parseExpression(tokens, true, scopeBuilder);
|
||||
private WhileKeyword parseWhileLoop(Tokenizer tokenizer, SourcePosition start, ScopeBuilder scopeBuilder) {
|
||||
Expression<?> first = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(first, Expression.ReturnType.BOOLEAN);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_END);
|
||||
|
||||
return new WhileKeyword(parseStatementBlock(tokens, true, scopeBuilder), (Expression<Boolean>) first, start); // While loop
|
||||
return new WhileKeyword(parseStatementBlock(tokenizer, true, scopeBuilder), (Expression<Boolean>) first, start); // While loop
|
||||
}
|
||||
|
||||
private IfKeyword parseIfStatement(Tokenizer tokens, SourcePosition start, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
Expression<?> condition = parseExpression(tokens, true, scopeBuilder);
|
||||
private IfKeyword parseIfStatement(Tokenizer tokenizer, SourcePosition start, boolean controlStructure, ScopeBuilder scopeBuilder) {
|
||||
Expression<?> condition = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(condition, Expression.ReturnType.BOOLEAN);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_END);
|
||||
|
||||
Block elseBlock = null;
|
||||
Block statement = parseStatementBlock(tokens, loop, scopeBuilder);
|
||||
Block statement = parseStatementBlock(tokenizer, controlStructure, scopeBuilder);
|
||||
|
||||
List<Pair<Expression<Boolean>, Block>> elseIf = new ArrayList<>();
|
||||
|
||||
while(tokens.hasNext() && tokens.current().getType().equals(Token.Type.ELSE)) {
|
||||
tokens.consume(); // Consume else.
|
||||
if(tokens.current().getType().equals(Token.Type.IF_STATEMENT)) {
|
||||
tokens.consume(); // Consume if.
|
||||
Expression<?> elseCondition = parseExpression(tokens, true, scopeBuilder);
|
||||
while(tokenizer.hasNext() && tokenizer.current().isType(Token.Type.ELSE)) {
|
||||
tokenizer.consume(); // Consume else.
|
||||
if(tokenizer.current().isType(Token.Type.IF_STATEMENT)) {
|
||||
tokenizer.consume(); // Consume if.
|
||||
Expression<?> elseCondition = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(elseCondition, Expression.ReturnType.BOOLEAN);
|
||||
elseIf.add(Pair.of((Expression<Boolean>) elseCondition, parseStatementBlock(tokens, loop, scopeBuilder)));
|
||||
elseIf.add(Pair.of((Expression<Boolean>) elseCondition, parseStatementBlock(tokenizer, controlStructure, scopeBuilder)));
|
||||
} else {
|
||||
elseBlock = parseStatementBlock(tokens, loop, scopeBuilder);
|
||||
elseBlock = parseStatementBlock(tokenizer, controlStructure, scopeBuilder);
|
||||
break; // Else must be last.
|
||||
}
|
||||
}
|
||||
@@ -148,75 +130,75 @@ public class Parser {
|
||||
return new IfKeyword(statement, (Expression<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
||||
}
|
||||
|
||||
private Block parseStatementBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
private Block parseStatementBlock(Tokenizer tokenizer, boolean controlStructure, ScopeBuilder scopeBuilder) {
|
||||
|
||||
if(tokens.current().getType().equals(Token.Type.BLOCK_BEGIN)) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
|
||||
Block block = parseBlock(tokens, loop, scopeBuilder);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END);
|
||||
if(tokenizer.current().isType(Token.Type.BLOCK_BEGIN)) {
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.BLOCK_BEGIN);
|
||||
Block block = parseBlock(tokenizer, controlStructure, scopeBuilder);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.BLOCK_END);
|
||||
return block;
|
||||
} else {
|
||||
SourcePosition position = tokens.current().getPosition();
|
||||
Block block = new Block(Collections.singletonList(parseStatement(tokens, loop, scopeBuilder)), position);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
SourcePosition position = tokenizer.current().getPosition();
|
||||
Block block = new Block(Collections.singletonList(parseExpression(tokenizer, controlStructure, scopeBuilder)), position);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.STATEMENT_END);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
private ForKeyword parseForLoop(Tokenizer tokens, SourcePosition start, ScopeBuilder scopeBuilder) {
|
||||
private ForKeyword parseForLoop(Tokenizer tokenizer, SourcePosition start, ScopeBuilder scopeBuilder) {
|
||||
scopeBuilder = scopeBuilder.sub(); // new scope
|
||||
Token f = tokens.current();
|
||||
ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER);
|
||||
Statement<?> initializer;
|
||||
Token f = tokenizer.current();
|
||||
ParserUtil.ensureType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER);
|
||||
Expression<?> initializer;
|
||||
if(f.isVariableDeclaration()) {
|
||||
VariableAssignmentNode<?> forVar = parseVariableDeclaration(tokens, scopeBuilder);
|
||||
Token name = tokens.current();
|
||||
VariableAssignmentNode<?> forVar = parseVariableDeclaration(tokenizer, scopeBuilder);
|
||||
Token name = tokenizer.current();
|
||||
if(functions.containsKey(name.getContent()) || scopeBuilder.contains(name.getContent()))
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
||||
initializer = forVar;
|
||||
} else initializer = parseExpression(tokens, true, scopeBuilder);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
Expression<?> conditional = parseExpression(tokens, true, scopeBuilder);
|
||||
} else initializer = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.STATEMENT_END);
|
||||
Expression<?> conditional = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(conditional, Expression.ReturnType.BOOLEAN);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.STATEMENT_END);
|
||||
|
||||
Statement<?> incrementer;
|
||||
Token token = tokens.current();
|
||||
Expression<?> incrementer;
|
||||
Token token = tokenizer.current();
|
||||
if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment
|
||||
incrementer = parseAssignment(tokens, scopeBuilder);
|
||||
} else incrementer = parseFunction(tokens, true, scopeBuilder);
|
||||
incrementer = parseAssignment(tokenizer, scopeBuilder);
|
||||
} else incrementer = parseFunction(tokenizer, true, scopeBuilder);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_END);
|
||||
|
||||
return new ForKeyword(parseStatementBlock(tokens, true, scopeBuilder), initializer, (Expression<Boolean>) conditional, incrementer,
|
||||
return new ForKeyword(parseStatementBlock(tokenizer, true, scopeBuilder), initializer, (Expression<Boolean>) conditional, incrementer,
|
||||
start);
|
||||
}
|
||||
|
||||
private Expression<?> parseExpression(Tokenizer tokens, boolean full, ScopeBuilder scopeBuilder) {
|
||||
private Expression<?> parseLogicMathExpression(Tokenizer tokenizer, boolean full, ScopeBuilder scopeBuilder) {
|
||||
boolean booleanInverted = false; // Check for boolean not operator
|
||||
boolean negate = false;
|
||||
if(tokens.current().getType().equals(Token.Type.BOOLEAN_NOT)) {
|
||||
if(tokenizer.current().isType(Token.Type.BOOLEAN_NOT)) {
|
||||
booleanInverted = true;
|
||||
tokens.consume();
|
||||
} else if(tokens.current().getType().equals(Token.Type.SUBTRACTION_OPERATOR)) {
|
||||
tokenizer.consume();
|
||||
} else if(tokenizer.current().isType(Token.Type.SUBTRACTION_OPERATOR)) {
|
||||
negate = true;
|
||||
tokens.consume();
|
||||
tokenizer.consume();
|
||||
}
|
||||
|
||||
Token id = tokens.current();
|
||||
Token id = tokenizer.current();
|
||||
|
||||
ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN);
|
||||
ParserUtil.ensureType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN);
|
||||
|
||||
Expression<?> expression;
|
||||
if(id.isConstant()) {
|
||||
expression = parseConstantExpression(tokens);
|
||||
} else if(id.getType().equals(Token.Type.GROUP_BEGIN)) { // Parse grouped expression
|
||||
expression = parseGroup(tokens, scopeBuilder);
|
||||
expression = parseConstantExpression(tokenizer);
|
||||
} else if(id.isType(Token.Type.GROUP_BEGIN)) { // Parse grouped expression
|
||||
expression = parseGroup(tokenizer, scopeBuilder);
|
||||
} else {
|
||||
if(functions.containsKey(id.getContent()))
|
||||
expression = parseFunction(tokens, false, scopeBuilder);
|
||||
expression = parseFunction(tokenizer, false, scopeBuilder);
|
||||
else if(scopeBuilder.contains(id.getContent())) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.IDENTIFIER);
|
||||
String varId = id.getContent();
|
||||
ReturnType varType = scopeBuilder.getType(varId);
|
||||
expression = switch(varType) {
|
||||
@@ -237,14 +219,14 @@ public class Parser {
|
||||
expression = new NegationOperation((Expression<Number>) expression, expression.getPosition());
|
||||
}
|
||||
|
||||
if(full && tokens.current().isBinaryOperator()) { // Parse binary operations
|
||||
return parseBinaryOperation(expression, tokens, scopeBuilder);
|
||||
if(full && tokenizer.current().isBinaryOperator()) { // Parse binary operations
|
||||
return parseBinaryOperation(expression, tokenizer, scopeBuilder);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
private ConstantExpression<?> parseConstantExpression(Tokenizer tokens) {
|
||||
Token constantToken = tokens.consume();
|
||||
private ConstantExpression<?> parseConstantExpression(Tokenizer tokenizer) {
|
||||
Token constantToken = tokenizer.consume();
|
||||
SourcePosition position = constantToken.getPosition();
|
||||
switch(constantToken.getType()) {
|
||||
case NUMBER:
|
||||
@@ -260,25 +242,25 @@ public class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
private Expression<?> parseGroup(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
|
||||
Expression<?> expression = parseExpression(tokens, true, scopeBuilder); // Parse inside of group as a separate expression
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
private Expression<?> parseGroup(Tokenizer tokenizer, ScopeBuilder scopeBuilder) {
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_BEGIN);
|
||||
Expression<?> expression = parseLogicMathExpression(tokenizer, true, scopeBuilder); // Parse inside of group as a separate expression
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_END);
|
||||
return expression;
|
||||
}
|
||||
|
||||
private BinaryOperation<?, ?> parseBinaryOperation(Expression<?> left, Tokenizer tokens,
|
||||
private BinaryOperation<?, ?> parseBinaryOperation(Expression<?> left, Tokenizer tokenizer,
|
||||
ScopeBuilder scopeBuilder) {
|
||||
Token binaryOperator = tokens.consume();
|
||||
Token binaryOperator = tokenizer.consume();
|
||||
ParserUtil.checkBinaryOperator(binaryOperator);
|
||||
|
||||
Expression<?> right = parseExpression(tokens, false, scopeBuilder);
|
||||
Expression<?> right = parseLogicMathExpression(tokenizer, false, scopeBuilder);
|
||||
|
||||
Token other = tokens.current();
|
||||
Token other = tokenizer.current();
|
||||
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) {
|
||||
return assemble(left, parseBinaryOperation(right, tokens, scopeBuilder), binaryOperator);
|
||||
return assemble(left, parseBinaryOperation(right, tokenizer, scopeBuilder), binaryOperator);
|
||||
} else if(other.isBinaryOperator()) {
|
||||
return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, scopeBuilder);
|
||||
return parseBinaryOperation(assemble(left, right, binaryOperator), tokenizer, scopeBuilder);
|
||||
}
|
||||
return assemble(left, right, binaryOperator);
|
||||
}
|
||||
@@ -323,20 +305,20 @@ public class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
private VariableAssignmentNode<?> parseVariableDeclaration(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
Token type = tokens.consume();
|
||||
ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
||||
private VariableAssignmentNode<?> parseVariableDeclaration(Tokenizer tokenizer, ScopeBuilder scopeBuilder) {
|
||||
Token type = tokenizer.consume();
|
||||
ParserUtil.ensureType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
||||
|
||||
Expression.ReturnType returnType = ParserUtil.getVariableReturnType(type);
|
||||
|
||||
ParserUtil.checkVarType(type, returnType); // Check for type mismatch
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
|
||||
Token identifier = tokenizer.consume();
|
||||
ParserUtil.ensureType(identifier, Token.Type.IDENTIFIER);
|
||||
if(functions.containsKey(identifier.getContent()) || scopeBuilder.contains(identifier.getContent()))
|
||||
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.ASSIGNMENT);
|
||||
|
||||
Expression<?> value = parseExpression(tokens, true, scopeBuilder);
|
||||
Expression<?> value = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(value, returnType);
|
||||
|
||||
String id = identifier.getContent();
|
||||
@@ -349,57 +331,67 @@ public class Parser {
|
||||
};
|
||||
}
|
||||
|
||||
private Block parseBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
List<Statement<?>> statements = new ArrayList<>();
|
||||
private Block parseBlock(Tokenizer tokenizer, boolean controlStructure, ScopeBuilder scopeBuilder) {
|
||||
List<Expression<?>> expressions = new ArrayList<>();
|
||||
|
||||
scopeBuilder = scopeBuilder.sub();
|
||||
|
||||
Token first = tokens.current();
|
||||
Token first = tokenizer.current();
|
||||
|
||||
while(tokens.hasNext()) {
|
||||
Token token = tokens.current();
|
||||
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||
Statement<?> statement = parseStatement(tokens, loop, scopeBuilder);
|
||||
if(statement != Function.NULL) {
|
||||
statements.add(statement);
|
||||
while(tokenizer.hasNext()) {
|
||||
Token token = tokenizer.current();
|
||||
if(token.isType(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||
Expression<?> expression = parseExpression(tokenizer, controlStructure, scopeBuilder);
|
||||
if(expression != Function.NULL) {
|
||||
expressions.add(expression);
|
||||
}
|
||||
if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
if(tokenizer.hasNext() && !token.isControlStructure()) ParserUtil.ensureType(tokenizer.consume(), Token.Type.STATEMENT_END);
|
||||
}
|
||||
return new Block(statements, first.getPosition());
|
||||
return new Block(expressions, first.getPosition());
|
||||
}
|
||||
|
||||
private Statement<?> parseStatement(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
Token token = tokens.current();
|
||||
if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE,
|
||||
Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
|
||||
else ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN,
|
||||
Token.Type.FAIL);
|
||||
private Expression<?> parseExpression(Tokenizer tokenizer, boolean controlStructure, ScopeBuilder scopeBuilder) {
|
||||
Token token = tokenizer.current();
|
||||
if(controlStructure) ParserUtil.ensureType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE,
|
||||
Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
|
||||
else ParserUtil.ensureType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN,
|
||||
Token.Type.FAIL);
|
||||
|
||||
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
|
||||
return parseLoopLike(tokens, loop, scopeBuilder);
|
||||
} else if(token.isIdentifier()) { // Parse identifiers
|
||||
if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment
|
||||
return parseAssignment(tokens, scopeBuilder);
|
||||
} else return parseFunction(tokens, true, scopeBuilder);
|
||||
} else if(token.isVariableDeclaration()) {
|
||||
return parseVariableDeclaration(tokens, scopeBuilder);
|
||||
} else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.FAIL)) return new FailKeyword(tokens.consume().getPosition());
|
||||
else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
|
||||
Expression<?> expression = switch(token.getType()) {
|
||||
case FOR_LOOP, IF_STATEMENT, WHILE_LOOP -> {
|
||||
Token identifier = tokenizer.consume();
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_BEGIN);
|
||||
yield switch(identifier.getType()) {
|
||||
case FOR_LOOP -> parseForLoop(tokenizer, identifier.getPosition(), scopeBuilder);
|
||||
case IF_STATEMENT -> parseIfStatement(tokenizer, identifier.getPosition(), controlStructure, scopeBuilder);
|
||||
case WHILE_LOOP -> parseWhileLoop(tokenizer, identifier.getPosition(), scopeBuilder);
|
||||
default -> throw new UnsupportedOperationException("Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
};
|
||||
}
|
||||
case IDENTIFIER -> {
|
||||
if(scopeBuilder.contains(token.getContent())) yield parseAssignment(tokenizer, scopeBuilder); // Assume variable assignment
|
||||
else yield parseFunction(tokenizer, true, scopeBuilder);
|
||||
}
|
||||
case NUMBER_VARIABLE, STRING_VARIABLE, BOOLEAN_VARIABLE -> parseVariableDeclaration(tokenizer, scopeBuilder);
|
||||
case RETURN -> new ReturnKeyword(tokenizer.consume().getPosition());
|
||||
case BREAK -> new BreakKeyword(tokenizer.consume().getPosition());
|
||||
case CONTINUE -> new ContinueKeyword(tokenizer.consume().getPosition());
|
||||
case FAIL -> new FailKeyword(tokenizer.consume().getPosition());
|
||||
default -> throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
|
||||
};
|
||||
return expression;
|
||||
}
|
||||
|
||||
private VariableAssignmentNode<?> parseAssignment(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokens.consume();
|
||||
private VariableAssignmentNode<?> parseAssignment(Tokenizer tokenizer, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokenizer.consume();
|
||||
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
|
||||
ParserUtil.ensureType(identifier, Token.Type.IDENTIFIER);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.ASSIGNMENT);
|
||||
|
||||
Expression<?> value = parseExpression(tokens, true, scopeBuilder);
|
||||
Expression<?> value = parseLogicMathExpression(tokenizer, true, scopeBuilder);
|
||||
|
||||
String id = identifier.getContent();
|
||||
|
||||
@@ -415,21 +407,20 @@ public class Parser {
|
||||
};
|
||||
}
|
||||
|
||||
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
||||
private Function<?> parseFunction(Tokenizer tokenizer, boolean fullStatement, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokenizer.consume();
|
||||
ParserUtil.ensureType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
||||
|
||||
if(!functions.containsKey(identifier.getContent()))
|
||||
throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition());
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_BEGIN); // Second is body begin
|
||||
|
||||
List<Expression<?>> args = getFunctionArgs(tokenizer, scopeBuilder); // Extract arguments, consume the rest.
|
||||
|
||||
List<Expression<?>> args = getArgs(tokens, scopeBuilder); // Extract arguments, consume the rest.
|
||||
ParserUtil.ensureType(tokenizer.consume(), Token.Type.GROUP_END); // Remove body end
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end
|
||||
|
||||
if(fullStatement) ParserUtil.checkType(tokens.current(), Token.Type.STATEMENT_END);
|
||||
if(fullStatement) ParserUtil.ensureType(tokenizer.current(), Token.Type.STATEMENT_END);
|
||||
|
||||
if(ignoredFunctions.contains(identifier.getContent())) {
|
||||
return Function.NULL;
|
||||
@@ -453,13 +444,13 @@ public class Parser {
|
||||
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
||||
}
|
||||
|
||||
private List<Expression<?>> getArgs(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
private List<Expression<?>> getFunctionArgs(Tokenizer tokenizer, ScopeBuilder scopeBuilder) {
|
||||
List<Expression<?>> args = new ArrayList<>();
|
||||
|
||||
while(!tokens.current().getType().equals(Token.Type.GROUP_END)) {
|
||||
args.add(parseExpression(tokens, true, scopeBuilder));
|
||||
ParserUtil.checkType(tokens.current(), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
||||
if(tokens.current().getType().equals(Token.Type.SEPARATOR)) tokens.consume();
|
||||
while(!tokenizer.current().isType(Token.Type.GROUP_END)) {
|
||||
args.add(parseLogicMathExpression(tokenizer, true, scopeBuilder));
|
||||
ParserUtil.ensureType(tokenizer.current(), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
||||
if(tokenizer.current().isType(Token.Type.SEPARATOR)) tokenizer.consume();
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ParserUtil {
|
||||
PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps);
|
||||
}
|
||||
|
||||
public static void checkType(Token token, Token.Type... expected) {
|
||||
public static void ensureType(Token token, Token.Type... expected) {
|
||||
for(Token.Type type : expected) if(token.getType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
@@ -13,19 +13,24 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Block.ReturnInfo;
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.SourcePosition;
|
||||
|
||||
|
||||
public class Block implements Statement<ReturnInfo<?>> {
|
||||
private final List<Statement<?>> items;
|
||||
public class Block implements Expression<ReturnInfo<?>> {
|
||||
private final List<Expression<?>> items;
|
||||
private final SourcePosition position;
|
||||
|
||||
public Block(List<Statement<?>> items, SourcePosition position) {
|
||||
public Block(List<Expression<?>> items, SourcePosition position) {
|
||||
this.items = items;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(Statement<?> item : items) {
|
||||
Object result = item.invoke(implementationArguments, scope);
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(Expression<?> item : items) {
|
||||
Object result = item.evaluate(implementationArguments, scope);
|
||||
if(result instanceof ReturnInfo<?> level) {
|
||||
if(!level.getLevel().equals(ReturnLevel.NONE)) return level;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ public class Executable {
|
||||
}
|
||||
|
||||
public boolean execute(ImplementationArguments arguments) {
|
||||
return script.invoke(arguments, scope.get()).getLevel() != Block.ReturnLevel.FAIL;
|
||||
return script.evaluate(arguments, scope.get()).getLevel() != Block.ReturnLevel.FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,24 @@
|
||||
|
||||
package com.dfsek.terra.addons.terrascript.parser.lang;
|
||||
|
||||
public interface Expression<T> extends Statement<T> {
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.SourcePosition;
|
||||
|
||||
|
||||
public interface Expression<T> {
|
||||
ReturnType returnType();
|
||||
|
||||
T evaluate(ImplementationArguments implementationArguments, Scope scope);
|
||||
|
||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
||||
}
|
||||
|
||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
||||
}
|
||||
|
||||
SourcePosition getPosition();
|
||||
|
||||
enum ReturnType {
|
||||
NUMBER(true),
|
||||
STRING(true),
|
||||
|
||||
@@ -7,19 +7,9 @@
|
||||
|
||||
package com.dfsek.terra.addons.terrascript.parser.lang;
|
||||
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.SourcePosition;
|
||||
|
||||
|
||||
public interface Statement<T> {
|
||||
T invoke(ImplementationArguments implementationArguments, Scope scope);
|
||||
|
||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
||||
public interface Statement extends Expression<Void> {
|
||||
@Override
|
||||
default ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
||||
}
|
||||
|
||||
SourcePosition getPosition();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public abstract class ConstantExpression<T> implements Expression<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public T evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface Function<T> extends Expression<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Object evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ public interface Function<T> extends Expression<T> {
|
||||
|
||||
@Override
|
||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((Number) invoke(implementationArguments, scope)).doubleValue();
|
||||
return ((Number) evaluate(implementationArguments, scope)).doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return (Boolean) invoke(implementationArguments, scope);
|
||||
return (Boolean) evaluate(implementationArguments, scope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@ import com.dfsek.terra.addons.terrascript.tokenizer.SourcePosition;
|
||||
|
||||
public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Block conditional;
|
||||
private final Statement<?> initializer;
|
||||
private final Expression<?> initializer;
|
||||
private final Expression<Boolean> statement;
|
||||
private final Statement<?> incrementer;
|
||||
private final Expression<?> incrementer;
|
||||
private final SourcePosition position;
|
||||
|
||||
public ForKeyword(Block conditional, Statement<?> initializer, Expression<Boolean> statement, Statement<?> incrementer, SourcePosition position) {
|
||||
public ForKeyword(Block conditional, Expression<?> initializer, Expression<Boolean> statement, Expression<?> incrementer, SourcePosition position) {
|
||||
this.conditional = conditional;
|
||||
this.initializer = initializer;
|
||||
this.statement = statement;
|
||||
@@ -32,11 +32,11 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(initializer.invoke(implementationArguments, scope);
|
||||
statement.invoke(implementationArguments, scope);
|
||||
incrementer.invoke(implementationArguments, scope)) {
|
||||
Block.ReturnInfo<?> level = conditional.invoke(implementationArguments, scope);
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(initializer.evaluate(implementationArguments, scope);
|
||||
statement.evaluate(implementationArguments, scope);
|
||||
incrementer.evaluate(implementationArguments, scope)) {
|
||||
Block.ReturnInfo<?> level = conditional.evaluate(implementationArguments, scope);
|
||||
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
|
||||
if(level.getLevel().isReturnFast()) return level;
|
||||
}
|
||||
|
||||
@@ -37,15 +37,15 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
if(statement.invoke(implementationArguments, scope)) return conditional.invoke(implementationArguments, scope);
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
if(statement.evaluate(implementationArguments, scope)) return conditional.evaluate(implementationArguments, scope);
|
||||
else {
|
||||
for(Pair<Expression<Boolean>, Block> pair : elseIf) {
|
||||
if(pair.getLeft().invoke(implementationArguments, scope)) {
|
||||
return pair.getRight().invoke(implementationArguments, scope);
|
||||
if(pair.getLeft().evaluate(implementationArguments, scope)) {
|
||||
return pair.getRight().evaluate(implementationArguments, scope);
|
||||
}
|
||||
}
|
||||
if(elseBlock != null) return elseBlock.invoke(implementationArguments, scope);
|
||||
if(elseBlock != null) return elseBlock.evaluate(implementationArguments, scope);
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
while(statement.invoke(implementationArguments, scope)) {
|
||||
Block.ReturnInfo<?> level = conditional.invoke(implementationArguments, scope);
|
||||
public Block.ReturnInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
while(statement.evaluate(implementationArguments, scope)) {
|
||||
Block.ReturnInfo<?> level = conditional.evaluate(implementationArguments, scope);
|
||||
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
|
||||
if(level.getLevel().isReturnFast()) return level;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class BooleanAndOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class BooleanNotOperation extends UnaryOperation<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class BooleanOrOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ConcatenationOperation extends BinaryOperation<Object, Object> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return toString(left.invoke(implementationArguments, scope)) + toString(right.invoke(implementationArguments, scope));
|
||||
public Object evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return toString(left.evaluate(implementationArguments, scope)) + toString(right.evaluate(implementationArguments, scope));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class DivisionOperation extends BinaryOperation<Number, Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ModuloOperation extends BinaryOperation<Number, Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class MultiplicationOperation extends BinaryOperation<Number, Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class NegationOperation extends UnaryOperation<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public class SubtractionOperation extends BinaryOperation<Number, Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,14 +31,14 @@ public class EqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
Object leftValue = left.invoke(implementationArguments, scope);
|
||||
Object rightValue = right.invoke(implementationArguments, scope);
|
||||
Object leftValue = left.evaluate(implementationArguments, scope);
|
||||
Object rightValue = right.evaluate(implementationArguments, scope);
|
||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
||||
return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolea
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean>
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class LessThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,14 @@ public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
Object leftValue = left.invoke(implementationArguments, scope);
|
||||
Object rightValue = right.invoke(implementationArguments, scope);
|
||||
Object leftValue = left.evaluate(implementationArguments, scope);
|
||||
Object rightValue = right.evaluate(implementationArguments, scope);
|
||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
||||
return FastMath.abs(l.doubleValue() - r.doubleValue()) > EPSILON;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,12 @@ public class BoolAssignmentNode extends VariableAssignmentNode<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,12 @@ public class NumAssignmentNode extends VariableAssignmentNode<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,13 @@ public class StrAssignmentNode extends VariableAssignmentNode<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
String val = value.invoke(implementationArguments, scope);
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
String val = value.evaluate(implementationArguments, scope);
|
||||
scope.setStr(index, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Expression;
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.SourcePosition;
|
||||
|
||||
|
||||
public abstract class VariableAssignmentNode<T> implements Statement<T> {
|
||||
public abstract class VariableAssignmentNode<T> implements Expression<T> {
|
||||
protected final Expression<T> value;
|
||||
protected final int index;
|
||||
private final SourcePosition position;
|
||||
|
||||
@@ -11,7 +11,7 @@ public class BoolVariableReferenceNode extends VariableReferenceNode<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getBool(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class NumVariableReferenceNode extends VariableReferenceNode<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getNum(index);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class StrVariableReferenceNode extends VariableReferenceNode<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getStr(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Num
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Expression<Number>) argumentList.get(0)).invoke(implementationArguments, scope),
|
||||
((Expression<Number>) argumentList.get(1)).invoke(implementationArguments, scope));
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Expression<Number>) argumentList.get(0)).evaluate(implementationArguments, scope),
|
||||
((Expression<Number>) argumentList.get(1)).evaluate(implementationArguments, scope));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,8 +37,8 @@ public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Voi
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Expression<Boolean>) argumentList.get(0)).invoke(implementationArguments, scope),
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Expression<Boolean>) argumentList.get(0)).evaluate(implementationArguments, scope),
|
||||
(TerraImplementationArguments) implementationArguments);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Numb
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Expression<Number>) argumentList.get(0)).invoke(implementationArguments, scope));
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Expression<Number>) argumentList.get(0)).evaluate(implementationArguments, scope));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,8 +35,8 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Expression<String>) argumentList.get(0)).invoke(implementationArguments, scope));
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Expression<String>) argumentList.get(0)).evaluate(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public T invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public T evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply((TerraImplementationArguments) implementationArguments);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ public class BiomeFunction implements Function<String> {
|
||||
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()),
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class BiomeFunction implements Function<String> {
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope).intValue(),
|
||||
y.evaluate(implementationArguments, scope).intValue(),
|
||||
FastMath.roundToInt(xz.getZ()))).immutable(), arguments.getWorld().getSeed()).getID();
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class BlockFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
BlockState rot = getBlockState(implementationArguments, scope);
|
||||
setBlock(implementationArguments, scope, arguments, rot);
|
||||
@@ -68,14 +68,14 @@ public class BlockFunction implements Function<Void> {
|
||||
|
||||
void setBlock(ImplementationArguments implementationArguments, Scope scope,
|
||||
TerraImplementationArguments arguments, BlockState rot) {
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
try {
|
||||
Vector3.Mutable set = Vector3.of(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope).doubleValue(),
|
||||
y.evaluate(implementationArguments, scope).doubleValue(),
|
||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
BlockState current = arguments.getWorld().getBlockState(set);
|
||||
if(overwrite.invoke(implementationArguments, scope) || current.isAir()) {
|
||||
if(overwrite.evaluate(implementationArguments, scope) || current.isAir()) {
|
||||
arguments.getWorld().setBlockState(set, rot);
|
||||
}
|
||||
} catch(RuntimeException e) {
|
||||
@@ -84,7 +84,7 @@ public class BlockFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) {
|
||||
return data.computeIfAbsent(blockData.invoke(arguments, scope), platform.getWorldHandle()::createBlockState);
|
||||
return data.computeIfAbsent(blockData.evaluate(arguments, scope), platform.getWorldHandle()::createBlockState);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ public class CheckBlockFunction implements Function<String> {
|
||||
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()),
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public class CheckBlockFunction implements Function<String> {
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope)
|
||||
y.evaluate(implementationArguments, scope)
|
||||
.doubleValue(), FastMath.roundToInt(xz.getZ()))))
|
||||
.getAsString();
|
||||
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
|
||||
|
||||
@@ -43,12 +43,12 @@ public class EntityFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
Entity entity = arguments.getWorld().spawnEntity(Vector3.of(xz.getX(), y.invoke(implementationArguments, scope).doubleValue(),
|
||||
Entity entity = arguments.getWorld().spawnEntity(Vector3.of(xz.getX(), y.evaluate(implementationArguments, scope).doubleValue(),
|
||||
xz.getZ())
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
|
||||
@@ -32,13 +32,13 @@ public class GetMarkFunction implements Function<String> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
String mark = arguments.getMark(Vector3.of(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(
|
||||
y.invoke(implementationArguments, scope).doubleValue()),
|
||||
y.evaluate(implementationArguments, scope).doubleValue()),
|
||||
FastMath.floorToInt(xz.getZ()))
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
|
||||
@@ -54,20 +54,20 @@ public class LootFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()),
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
String id = data.invoke(implementationArguments, scope);
|
||||
String id = data.evaluate(implementationArguments, scope);
|
||||
|
||||
|
||||
registry.get(RegistryKey.parse(id))
|
||||
.ifPresentOrElse(table -> {
|
||||
Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope)
|
||||
y.evaluate(implementationArguments, scope)
|
||||
.intValue(),
|
||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
|
||||
|
||||
@@ -41,12 +41,12 @@ public class PullFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
Vector3.Mutable mutable = Vector3.of(FastMath.roundToInt(xz.getX()), y.invoke(implementationArguments, scope).intValue(),
|
||||
Vector3.Mutable mutable = Vector3.of(FastMath.roundToInt(xz.getX()), y.evaluate(implementationArguments, scope).intValue(),
|
||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
while(mutable.getY() > arguments.getWorld().getMinHeight()) {
|
||||
if(!arguments.getWorld().getBlockState(mutable).isAir()) {
|
||||
|
||||
@@ -31,9 +31,9 @@ public class RandomFunction implements Function<Integer> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Integer evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(
|
||||
numberReturnable.invoke(implementationArguments, scope).intValue());
|
||||
numberReturnable.evaluate(implementationArguments, scope).intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,7 +27,7 @@ public class RecursionsFunction implements Function<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRecursions();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@ public class SetMarkFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
arguments.setMark(Vector3.of(FastMath.floorToInt(xz.getX()),
|
||||
FastMath.floorToInt(
|
||||
y.invoke(implementationArguments, scope).doubleValue()),
|
||||
y.evaluate(implementationArguments, scope).doubleValue()),
|
||||
FastMath.floorToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(),
|
||||
mark.invoke(implementationArguments, scope));
|
||||
mark.evaluate(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,17 +39,17 @@ public class StateFunction implements Function<Void> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
Vector3 origin = Vector3.of(FastMath.roundToInt(xz.getX()), y.invoke(implementationArguments, scope).intValue(),
|
||||
Vector3 origin = Vector3.of(FastMath.roundToInt(xz.getX()), y.evaluate(implementationArguments, scope).intValue(),
|
||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
try {
|
||||
BlockEntity state = arguments.getWorld().getBlockEntity(origin);
|
||||
state.applyState(data.invoke(implementationArguments, scope));
|
||||
state.applyState(data.evaluate(implementationArguments, scope));
|
||||
state.update(false);
|
||||
} catch(Exception e) {
|
||||
LOGGER.warn("Could not apply BlockState at {}", origin, e);
|
||||
|
||||
@@ -55,20 +55,20 @@ public class StructureFunction implements Function<Boolean> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
if(arguments.getRecursions() > platform.getTerraConfig().getMaxRecursion())
|
||||
throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions());
|
||||
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
String app = id.invoke(implementationArguments, scope);
|
||||
String app = id.evaluate(implementationArguments, scope);
|
||||
return registry.getByID(app).map(script -> {
|
||||
Rotation rotation1;
|
||||
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).invoke(implementationArguments, scope);
|
||||
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).evaluate(implementationArguments, scope);
|
||||
try {
|
||||
rotation1 = Rotation.valueOf(rotString);
|
||||
} catch(IllegalArgumentException e) {
|
||||
@@ -80,7 +80,7 @@ public class StructureFunction implements Function<Boolean> {
|
||||
return structureScript.generate(arguments.getOrigin(),
|
||||
arguments.getWorld()
|
||||
.buffer(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope).intValue(),
|
||||
y.evaluate(implementationArguments, scope).intValue(),
|
||||
FastMath.roundToInt(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
|
||||
@@ -88,7 +88,7 @@ public class StructureFunction implements Function<Boolean> {
|
||||
return script.generate(arguments.getOrigin(),
|
||||
arguments.getWorld()
|
||||
.buffer(FastMath.roundToInt(xz.getX()),
|
||||
y.invoke(implementationArguments, scope).intValue(),
|
||||
y.evaluate(implementationArguments, scope).intValue(),
|
||||
FastMath.roundToInt(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1));
|
||||
|
||||
@@ -39,6 +39,10 @@ public class Token {
|
||||
return this.type.equals(Type.NUMBER) || this.type.equals(Type.STRING) || this.type.equals(Type.BOOLEAN);
|
||||
}
|
||||
|
||||
public boolean isType(Type type) {
|
||||
return type == getType();
|
||||
}
|
||||
|
||||
public boolean isBinaryOperator() {
|
||||
return type.equals(Type.ADDITION_OPERATOR)
|
||||
|| type.equals(Type.SUBTRACTION_OPERATOR)
|
||||
@@ -77,16 +81,12 @@ public class Token {
|
||||
|| type.equals(Type.NUMBER_VARIABLE);
|
||||
}
|
||||
|
||||
public boolean isLoopLike() {
|
||||
public boolean isControlStructure() {
|
||||
return type.equals(Type.IF_STATEMENT)
|
||||
|| type.equals(Type.WHILE_LOOP)
|
||||
|| type.equals(Type.FOR_LOOP);
|
||||
}
|
||||
|
||||
public boolean isIdentifier() {
|
||||
return type.equals(Type.IDENTIFIER);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
/**
|
||||
* Function identifier or language keyword
|
||||
|
||||
@@ -11,13 +11,13 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.PeekableStream;
|
||||
import com.dfsek.terra.addons.terrascript.tokenizer.LookaheadStream;
|
||||
|
||||
|
||||
public class PeekableStreamTest {
|
||||
public class LookaheadStreamTest {
|
||||
@Test
|
||||
public void lookahead() {
|
||||
PeekableStream lookahead = new PeekableStream(new StringReader("Test string..."));
|
||||
LookaheadStream lookahead = new LookaheadStream(new StringReader("Test string..."));
|
||||
|
||||
for(int i = 0; lookahead.next(i) != null; i++) {
|
||||
System.out.print(lookahead.next(i).getCharacter());
|
||||
|
||||
@@ -77,9 +77,9 @@ public class ParserTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
System.out.println("string: " + a.invoke(implementationArguments, scope) + ", double: " +
|
||||
b.invoke(implementationArguments, scope));
|
||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
System.out.println("string: " + a.evaluate(implementationArguments, scope) + ", double: " +
|
||||
b.evaluate(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,19 +37,19 @@ public class CheckFunction implements Function<String> {
|
||||
|
||||
|
||||
@Override
|
||||
public String invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
|
||||
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
|
||||
Vector2 xz = Vector2.of(x.invoke(implementationArguments, scope).doubleValue(),
|
||||
z.invoke(implementationArguments, scope).doubleValue());
|
||||
Vector2 xz = Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
||||
z.evaluate(implementationArguments, scope).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
Vector3 location = arguments.getOrigin().toVector3Mutable().add(
|
||||
Vector3.of(FastMath.roundToInt(xz.getX()), y.invoke(implementationArguments, scope).doubleValue(),
|
||||
Vector3.of(FastMath.roundToInt(xz.getX()), y.evaluate(implementationArguments, scope).doubleValue(),
|
||||
FastMath.roundToInt(xz.getZ()))).immutable();
|
||||
|
||||
return apply(location, arguments.getWorld());
|
||||
|
||||
@@ -32,16 +32,16 @@ public class ConstantSamplerFunction implements Function<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
double x = this.x.invoke(implementationArguments, scope).doubleValue();
|
||||
double x = this.x.evaluate(implementationArguments, scope).doubleValue();
|
||||
|
||||
double z = this.z.invoke(implementationArguments, scope).doubleValue();
|
||||
double z = this.z.evaluate(implementationArguments, scope).doubleValue();
|
||||
|
||||
if(twoD) {
|
||||
return sampler.noise(arguments.getWorld().getSeed(), x, z);
|
||||
} else {
|
||||
double y = this.y.invoke(implementationArguments, scope).doubleValue();
|
||||
double y = this.y.evaluate(implementationArguments, scope).doubleValue();
|
||||
return sampler.noise(arguments.getWorld().getSeed(), x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,17 +37,17 @@ public class SamplerFunction implements Function<Number> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number invoke(ImplementationArguments implementationArguments, Scope scope) {
|
||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
double x = this.x.invoke(implementationArguments, scope).doubleValue();
|
||||
double x = this.x.evaluate(implementationArguments, scope).doubleValue();
|
||||
|
||||
double z = this.z.invoke(implementationArguments, scope).doubleValue();
|
||||
double z = this.z.evaluate(implementationArguments, scope).doubleValue();
|
||||
|
||||
NoiseSampler sampler = samplerFunction.apply(() -> function.invoke(implementationArguments, scope));
|
||||
NoiseSampler sampler = samplerFunction.apply(() -> function.evaluate(implementationArguments, scope));
|
||||
if(twoD) {
|
||||
return sampler.noise(arguments.getWorld().getSeed(), x, z);
|
||||
} else {
|
||||
double y = this.y.invoke(implementationArguments, scope).doubleValue();
|
||||
double y = this.y.evaluate(implementationArguments, scope).doubleValue();
|
||||
return sampler.noise(arguments.getWorld().getSeed(), x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user