mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-19 23:00:19 +00:00
Change Java whitespace handling in .editorconfig (#425)
* Change whitespace handling in .editorconfig * Reformat code * fix format error * Reformat code --------- Co-authored-by: Zoë Gidiere <duplexsys@protonmail.com>
This commit is contained in:
@@ -25,40 +25,40 @@ import com.dfsek.terra.api.util.StringUtil;
|
||||
public class TerraScriptAddon implements AddonInitializer {
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
|
||||
@Inject
|
||||
private BaseAddon addon;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> {
|
||||
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
|
||||
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
|
||||
event.getPack().getLoader().open("", ".tesf").thenEntries(
|
||||
entries ->
|
||||
entries.stream()
|
||||
.parallel()
|
||||
.map(entry -> {
|
||||
try {
|
||||
String id = StringUtil.fileName(entry.getKey());
|
||||
return new StructureScript(entry.getValue(),
|
||||
addon.key(id),
|
||||
platform,
|
||||
structureRegistry,
|
||||
lootRegistry,
|
||||
event.getPack().getOrCreateRegistry(FunctionBuilder.class));
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e);
|
||||
}
|
||||
})
|
||||
.toList()
|
||||
.forEach(structureRegistry::register))
|
||||
.close();
|
||||
})
|
||||
.priority(100)
|
||||
.failThrough();
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> {
|
||||
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
|
||||
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
|
||||
event.getPack().getLoader().open("", ".tesf").thenEntries(
|
||||
entries ->
|
||||
entries.stream()
|
||||
.parallel()
|
||||
.map(entry -> {
|
||||
try {
|
||||
String id = StringUtil.fileName(entry.getKey());
|
||||
return new StructureScript(entry.getValue(),
|
||||
addon.key(id),
|
||||
platform,
|
||||
structureRegistry,
|
||||
lootRegistry,
|
||||
event.getPack().getOrCreateRegistry(FunctionBuilder.class));
|
||||
} catch(ParseException e) {
|
||||
throw new RuntimeException("Failed to load script \"" + entry.getKey() + "\"", e);
|
||||
}
|
||||
})
|
||||
.toList()
|
||||
.forEach(structureRegistry::register))
|
||||
.close();
|
||||
})
|
||||
.priority(100)
|
||||
.failThrough();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,21 +69,21 @@ public class Parser {
|
||||
private final String data;
|
||||
private final Map<String, FunctionBuilder<? extends Function<?>>> functions = new HashMap<>();
|
||||
private final List<String> ignoredFunctions = new ArrayList<>();
|
||||
|
||||
|
||||
public Parser(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public Parser registerFunction(String name, FunctionBuilder<? extends Function<?>> functionBuilder) {
|
||||
functions.put(name, functionBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Parser ignoreFunction(String name) {
|
||||
ignoredFunctions.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse input
|
||||
*
|
||||
@@ -95,43 +95,43 @@ public class Parser {
|
||||
ScopeBuilder scopeBuilder = new ScopeBuilder();
|
||||
return new Executable(parseBlock(new Tokenizer(data), 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());
|
||||
"Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private WhileKeyword parseWhileLoop(Tokenizer tokens, Position start, ScopeBuilder scopeBuilder) {
|
||||
Returnable<?> first = parseExpression(tokens, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN);
|
||||
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
|
||||
return new WhileKeyword(parseStatementBlock(tokens, true, scopeBuilder), (Returnable<Boolean>) first, start); // While loop
|
||||
}
|
||||
|
||||
|
||||
private IfKeyword parseIfStatement(Tokenizer tokens, Position start, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
Returnable<?> condition = parseExpression(tokens, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
|
||||
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
|
||||
Block elseBlock = null;
|
||||
Block statement = parseStatementBlock(tokens, loop, scopeBuilder);
|
||||
|
||||
|
||||
List<Pair<Returnable<Boolean>, Block>> elseIf = new ArrayList<>();
|
||||
|
||||
|
||||
while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) {
|
||||
tokens.consume(); // Consume else.
|
||||
if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) {
|
||||
@@ -144,12 +144,12 @@ public class Parser {
|
||||
break; // Else must be last.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
||||
}
|
||||
|
||||
|
||||
private Block parseStatementBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
|
||||
|
||||
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
|
||||
Block block = parseBlock(tokens, loop, scopeBuilder);
|
||||
@@ -162,7 +162,7 @@ public class Parser {
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ForKeyword parseForLoop(Tokenizer tokens, Position start, ScopeBuilder scopeBuilder) {
|
||||
scopeBuilder = scopeBuilder.sub(); // new scope
|
||||
Token f = tokens.get();
|
||||
@@ -179,19 +179,19 @@ public class Parser {
|
||||
Returnable<?> conditional = parseExpression(tokens, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
|
||||
|
||||
Item<?> incrementer;
|
||||
Token token = tokens.get();
|
||||
if(scopeBuilder.contains(token.getContent())) { // Assume variable assignment
|
||||
incrementer = parseAssignment(tokens, scopeBuilder);
|
||||
} else incrementer = parseFunction(tokens, true, scopeBuilder);
|
||||
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
|
||||
return new ForKeyword(parseStatementBlock(tokens, true, scopeBuilder), initializer, (Returnable<Boolean>) conditional, incrementer,
|
||||
start);
|
||||
start);
|
||||
}
|
||||
|
||||
|
||||
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, ScopeBuilder scopeBuilder) {
|
||||
boolean booleanInverted = false; // Check for boolean not operator
|
||||
boolean negate = false;
|
||||
@@ -202,11 +202,11 @@ public class Parser {
|
||||
negate = true;
|
||||
tokens.consume();
|
||||
}
|
||||
|
||||
|
||||
Token id = tokens.get();
|
||||
|
||||
|
||||
ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN);
|
||||
|
||||
|
||||
Returnable<?> expression;
|
||||
if(id.isConstant()) {
|
||||
expression = parseConstantExpression(tokens);
|
||||
@@ -225,10 +225,10 @@ public class Parser {
|
||||
case BOOLEAN -> new BoolVariableReferenceNode(id.getPosition(), varType, scopeBuilder.getIndex(varId));
|
||||
default -> throw new ParseException("Illegal type for variable reference: " + varType, id.getPosition());
|
||||
};
|
||||
|
||||
|
||||
} else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition());
|
||||
}
|
||||
|
||||
|
||||
if(booleanInverted) { // Invert operation if boolean not detected
|
||||
ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
|
||||
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
||||
@@ -236,13 +236,13 @@ public class Parser {
|
||||
ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER);
|
||||
expression = new NegationOperation((Returnable<Number>) expression, expression.getPosition());
|
||||
}
|
||||
|
||||
|
||||
if(full && tokens.get().isBinaryOperator()) { // Parse binary operations
|
||||
return parseBinaryOperation(expression, tokens, scopeBuilder);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
|
||||
private ConstantExpression<?> parseConstantExpression(Tokenizer tokens) {
|
||||
Token constantToken = tokens.consume();
|
||||
Position position = constantToken.getPosition();
|
||||
@@ -256,24 +256,24 @@ public class Parser {
|
||||
return new BooleanConstant(Boolean.parseBoolean(constantToken.getContent()), position);
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported constant token: " + constantToken.getType() + " at position: " + position);
|
||||
"Unsupported constant token: " + constantToken.getType() + " at position: " + position);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Returnable<?> parseGroup(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
|
||||
Returnable<?> expression = parseExpression(tokens, true, scopeBuilder); // Parse inside of group as a separate expression
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
return expression;
|
||||
}
|
||||
|
||||
|
||||
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens,
|
||||
ScopeBuilder scopeBuilder) {
|
||||
Token binaryOperator = tokens.consume();
|
||||
ParserUtil.checkBinaryOperator(binaryOperator);
|
||||
|
||||
|
||||
Returnable<?> right = parseExpression(tokens, false, scopeBuilder);
|
||||
|
||||
|
||||
Token other = tokens.get();
|
||||
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) {
|
||||
return assemble(left, parseBinaryOperation(right, tokens, scopeBuilder), binaryOperator);
|
||||
@@ -282,7 +282,7 @@ public class Parser {
|
||||
}
|
||||
return assemble(left, right, binaryOperator);
|
||||
}
|
||||
|
||||
|
||||
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) {
|
||||
if(binaryOperator.isStrictNumericOperator())
|
||||
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
|
||||
@@ -309,7 +309,7 @@ public class Parser {
|
||||
return new LessThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case GREATER_THAN_OR_EQUALS_OPERATOR:
|
||||
return new GreaterOrEqualsThanStatement((Returnable<Number>) left, (Returnable<Number>) right,
|
||||
binaryOperator.getPosition());
|
||||
binaryOperator.getPosition());
|
||||
case LESS_THAN_OR_EQUALS_OPERATOR:
|
||||
return new LessThanOrEqualsStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case BOOLEAN_AND:
|
||||
@@ -322,25 +322,25 @@ public class Parser {
|
||||
throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
Returnable.ReturnType returnType = ParserUtil.getVariableReturnType(type);
|
||||
|
||||
|
||||
ParserUtil.checkVarType(type, returnType); // Check for type mismatch
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(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);
|
||||
|
||||
|
||||
Returnable<?> value = parseExpression(tokens, true, scopeBuilder);
|
||||
ParserUtil.checkReturnType(value, returnType);
|
||||
|
||||
|
||||
String id = identifier.getContent();
|
||||
|
||||
|
||||
return switch(value.returnType()) {
|
||||
case NUMBER -> new NumAssignmentNode((Returnable<Number>) value, identifier.getPosition(), scopeBuilder.num(id));
|
||||
case STRING -> new StrAssignmentNode((Returnable<String>) value, identifier.getPosition(), scopeBuilder.str(id));
|
||||
@@ -348,14 +348,14 @@ public class Parser {
|
||||
default -> throw new ParseException("Illegal type for variable declaration: " + type, value.getPosition());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Block parseBlock(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
List<Item<?>> parsedItems = new ArrayList<>();
|
||||
|
||||
|
||||
scopeBuilder = scopeBuilder.sub();
|
||||
|
||||
|
||||
Token first = tokens.get();
|
||||
|
||||
|
||||
while(tokens.hasNext()) {
|
||||
Token token = tokens.get();
|
||||
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||
@@ -367,16 +367,16 @@ public class Parser {
|
||||
}
|
||||
return new Block(parsedItems, first.getPosition());
|
||||
}
|
||||
|
||||
|
||||
private Item<?> parseItem(Tokenizer tokens, boolean loop, ScopeBuilder scopeBuilder) {
|
||||
Token token = tokens.get();
|
||||
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);
|
||||
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);
|
||||
|
||||
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
|
||||
@@ -384,31 +384,31 @@ public class Parser {
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
private VariableAssignmentNode<?> parseAssignment(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokens.consume();
|
||||
|
||||
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
|
||||
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
|
||||
|
||||
|
||||
Returnable<?> value = parseExpression(tokens, true, scopeBuilder);
|
||||
|
||||
|
||||
String id = identifier.getContent();
|
||||
|
||||
|
||||
ParserUtil.checkReturnType(value, scopeBuilder.getType(id));
|
||||
|
||||
|
||||
ReturnType type = value.returnType();
|
||||
|
||||
|
||||
return switch(type) {
|
||||
case NUMBER -> new NumAssignmentNode((Returnable<Number>) value, identifier.getPosition(), scopeBuilder.getIndex(id));
|
||||
case STRING -> new StrAssignmentNode((Returnable<String>) value, identifier.getPosition(), scopeBuilder.getIndex(id));
|
||||
@@ -416,48 +416,48 @@ public class Parser {
|
||||
default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, ScopeBuilder scopeBuilder) {
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(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
|
||||
|
||||
|
||||
|
||||
|
||||
List<Returnable<?>> args = getArgs(tokens, scopeBuilder); // Extract arguments, consume the rest.
|
||||
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end
|
||||
|
||||
|
||||
if(fullStatement) ParserUtil.checkType(tokens.get(), Token.Type.STATEMENT_END);
|
||||
|
||||
|
||||
if(ignoredFunctions.contains(identifier.getContent())) {
|
||||
return Function.NULL;
|
||||
}
|
||||
|
||||
|
||||
if(functions.containsKey(identifier.getContent())) {
|
||||
FunctionBuilder<?> builder = functions.get(identifier.getContent());
|
||||
|
||||
|
||||
if(builder.argNumber() != -1 && args.size() != builder.argNumber())
|
||||
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition());
|
||||
|
||||
|
||||
for(int i = 0; i < args.size(); i++) {
|
||||
Returnable<?> argument = args.get(i);
|
||||
if(builder.getArgument(i) == null)
|
||||
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(),
|
||||
identifier.getPosition());
|
||||
identifier.getPosition());
|
||||
ParserUtil.checkReturnType(argument, builder.getArgument(i));
|
||||
}
|
||||
return builder.build(args, identifier.getPosition());
|
||||
}
|
||||
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
||||
}
|
||||
|
||||
|
||||
private List<Returnable<?>> getArgs(Tokenizer tokens, ScopeBuilder scopeBuilder) {
|
||||
List<Returnable<?>> args = new ArrayList<>();
|
||||
|
||||
|
||||
while(!tokens.get().getType().equals(Token.Type.GROUP_END)) {
|
||||
args.add(parseExpression(tokens, true, scopeBuilder));
|
||||
ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
||||
|
||||
@@ -18,72 +18,72 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Token;
|
||||
|
||||
|
||||
public class ParserUtil {
|
||||
|
||||
|
||||
private static final Map<Token.Type, Map<Token.Type, Boolean>> PRECEDENCE = new HashMap<>(); // If second has precedence, true.
|
||||
private static final List<Token.Type> ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR,
|
||||
Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR,
|
||||
Token.Type.MODULO_OPERATOR);
|
||||
Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR,
|
||||
Token.Type.MODULO_OPERATOR);
|
||||
private static final List<Token.Type> COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR,
|
||||
Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR,
|
||||
Token.Type.GREATER_THAN_OPERATOR,
|
||||
Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR);
|
||||
|
||||
Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR,
|
||||
Token.Type.GREATER_THAN_OPERATOR,
|
||||
Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR);
|
||||
|
||||
static { // Setup precedence
|
||||
Map<Token.Type, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
|
||||
add.put(Token.Type.MULTIPLICATION_OPERATOR, true);
|
||||
add.put(Token.Type.DIVISION_OPERATOR, true);
|
||||
|
||||
|
||||
PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add);
|
||||
PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add);
|
||||
|
||||
|
||||
Map<Token.Type, Boolean> numericBoolean = new HashMap<>();
|
||||
|
||||
|
||||
ARITHMETIC.forEach(op -> numericBoolean.put(op, true)); // Numbers before comparison
|
||||
COMPARISON.forEach(op -> PRECEDENCE.put(op, numericBoolean));
|
||||
|
||||
|
||||
|
||||
|
||||
Map<Token.Type, Boolean> booleanOps = new HashMap<>();
|
||||
ARITHMETIC.forEach(op -> booleanOps.put(op, true)); // Everything before boolean
|
||||
COMPARISON.forEach(op -> booleanOps.put(op, true));
|
||||
|
||||
|
||||
|
||||
|
||||
PRECEDENCE.put(Token.Type.BOOLEAN_AND, booleanOps);
|
||||
PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps);
|
||||
}
|
||||
|
||||
|
||||
public static void checkType(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());
|
||||
}
|
||||
|
||||
|
||||
public static void checkReturnType(Returnable<?> returnable, Returnable.ReturnType... types) {
|
||||
for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition());
|
||||
}
|
||||
|
||||
|
||||
public static void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token operation) {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||
throw new ParseException(
|
||||
"Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(),
|
||||
operation.getPosition());
|
||||
"Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(),
|
||||
operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token operation) {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
|
||||
throw new ParseException(
|
||||
"Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(),
|
||||
operation.getPosition());
|
||||
"Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(),
|
||||
operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void checkVarType(Token token, Returnable.ReturnType returnType) {
|
||||
if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return;
|
||||
throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if token is a binary operator
|
||||
*
|
||||
@@ -95,17 +95,17 @@ public class ParserUtil {
|
||||
if(!token.isBinaryOperator())
|
||||
throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
|
||||
public static Returnable.ReturnType getVariableReturnType(Token varToken) {
|
||||
return switch(varToken.getType()) {
|
||||
case NUMBER_VARIABLE -> Returnable.ReturnType.NUMBER;
|
||||
case STRING_VARIABLE -> Returnable.ReturnType.STRING;
|
||||
case BOOLEAN_VARIABLE -> Returnable.ReturnType.BOOLEAN;
|
||||
default -> throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration",
|
||||
varToken.getPosition());
|
||||
varToken.getPosition());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static boolean hasPrecedence(Token.Type first, Token.Type second) {
|
||||
if(!PRECEDENCE.containsKey(first)) return false;
|
||||
Map<Token.Type, Boolean> pre = PRECEDENCE.get(first);
|
||||
|
||||
@@ -16,22 +16,22 @@ public class ParseException extends RuntimeException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 6744390543046766386L;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public ParseException(String message, Position position) {
|
||||
super(message);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
public ParseException(String message, Position position, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return super.getMessage() + ": " + position;
|
||||
}
|
||||
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class Block implements Item<Block.ReturnInfo<?>> {
|
||||
private final List<Item<?>> items;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public Block(List<Item<?>> items, Position position) {
|
||||
this.items = items;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(Item<?> item : items) {
|
||||
@@ -31,44 +31,44 @@ public class Block implements Item<Block.ReturnInfo<?>> {
|
||||
}
|
||||
return new ReturnInfo<>(ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
public enum ReturnLevel {
|
||||
NONE(false),
|
||||
BREAK(false),
|
||||
CONTINUE(false),
|
||||
RETURN(true),
|
||||
FAIL(true);
|
||||
|
||||
|
||||
private final boolean returnFast;
|
||||
|
||||
|
||||
ReturnLevel(boolean returnFast) {
|
||||
this.returnFast = returnFast;
|
||||
}
|
||||
|
||||
|
||||
public boolean isReturnFast() {
|
||||
return returnFast;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class ReturnInfo<T> {
|
||||
private final ReturnLevel level;
|
||||
private final T data;
|
||||
|
||||
|
||||
public ReturnInfo(ReturnLevel level, T data) {
|
||||
this.level = level;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
||||
public ReturnLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder;
|
||||
public class Executable {
|
||||
private final Block script;
|
||||
private final ThreadLocal<Scope> scope;
|
||||
|
||||
|
||||
public Executable(Block script, ScopeBuilder scopeBuilder) {
|
||||
this.script = script;
|
||||
this.scope = ThreadLocal.withInitial(scopeBuilder::build);
|
||||
}
|
||||
|
||||
|
||||
public boolean execute(ImplementationArguments arguments) {
|
||||
return script.apply(arguments, scope.get()).getLevel() != Block.ReturnLevel.FAIL;
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public interface Item<T> {
|
||||
T apply(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");
|
||||
}
|
||||
|
||||
|
||||
Position getPosition();
|
||||
}
|
||||
|
||||
@@ -9,20 +9,20 @@ package com.dfsek.terra.addons.terrascript.parser.lang;
|
||||
|
||||
public interface Returnable<T> extends Item<T> {
|
||||
ReturnType returnType();
|
||||
|
||||
|
||||
enum ReturnType {
|
||||
NUMBER(true),
|
||||
STRING(true),
|
||||
BOOLEAN(false),
|
||||
VOID(false),
|
||||
OBJECT(false);
|
||||
|
||||
|
||||
private final boolean comparable;
|
||||
|
||||
|
||||
ReturnType(boolean comparable) {
|
||||
this.comparable = comparable;
|
||||
}
|
||||
|
||||
|
||||
public boolean isComparable() {
|
||||
return comparable;
|
||||
}
|
||||
|
||||
@@ -12,46 +12,46 @@ public class Scope {
|
||||
private final double[] num;
|
||||
private final boolean[] bool;
|
||||
private final String[] str;
|
||||
|
||||
|
||||
private Scope(int numSize, int boolSize, int strSize) {
|
||||
this.num = new double[numSize];
|
||||
this.bool = new boolean[boolSize];
|
||||
this.str = new String[strSize];
|
||||
}
|
||||
|
||||
|
||||
public double getNum(int index) {
|
||||
return num[index];
|
||||
}
|
||||
|
||||
|
||||
public boolean getBool(int index) {
|
||||
return bool[index];
|
||||
}
|
||||
|
||||
|
||||
public String getStr(int index) {
|
||||
return str[index];
|
||||
}
|
||||
|
||||
|
||||
public void setNum(int index, double value) {
|
||||
num[index] = value;
|
||||
}
|
||||
|
||||
|
||||
public void setBool(int index, boolean value) {
|
||||
bool[index] = value;
|
||||
}
|
||||
|
||||
|
||||
public void setStr(int index, String value) {
|
||||
str[index] = value;
|
||||
}
|
||||
|
||||
|
||||
public static final class ScopeBuilder {
|
||||
private final Map<String, Pair<Integer, ReturnType>> indices;
|
||||
private int numSize, boolSize, strSize = 0;
|
||||
private ScopeBuilder parent;
|
||||
|
||||
|
||||
public ScopeBuilder() {
|
||||
this.indices = new HashMap<>();
|
||||
}
|
||||
|
||||
|
||||
private ScopeBuilder(ScopeBuilder parent) {
|
||||
this.parent = parent;
|
||||
this.numSize = parent.numSize;
|
||||
@@ -59,22 +59,22 @@ public class Scope {
|
||||
this.strSize = parent.strSize;
|
||||
this.indices = new HashMap<>(parent.indices);
|
||||
}
|
||||
|
||||
|
||||
public Scope build() {
|
||||
return new Scope(numSize, boolSize, strSize);
|
||||
}
|
||||
|
||||
|
||||
public ScopeBuilder sub() {
|
||||
return new ScopeBuilder(this);
|
||||
}
|
||||
|
||||
|
||||
private String check(String id) {
|
||||
if(indices.containsKey(id)) {
|
||||
throw new IllegalArgumentException("Variable with ID " + id + " already registered.");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public int num(String id) {
|
||||
int num = numSize;
|
||||
indices.put(check(id), Pair.of(num, ReturnType.NUMBER));
|
||||
@@ -82,7 +82,7 @@ public class Scope {
|
||||
updateNumSize(numSize);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
public int str(String id) {
|
||||
int str = strSize;
|
||||
indices.put(check(id), Pair.of(str, ReturnType.STRING));
|
||||
@@ -90,7 +90,7 @@ public class Scope {
|
||||
updateStrSize(strSize);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
public int bool(String id) {
|
||||
int bool = boolSize;
|
||||
indices.put(check(id), Pair.of(bool, ReturnType.BOOLEAN));
|
||||
@@ -98,37 +98,37 @@ public class Scope {
|
||||
updateBoolSize(boolSize);
|
||||
return bool;
|
||||
}
|
||||
|
||||
|
||||
private void updateBoolSize(int size) {
|
||||
this.boolSize = Math.max(boolSize, size);
|
||||
if(parent != null) {
|
||||
parent.updateBoolSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateNumSize(int size) {
|
||||
this.numSize = Math.max(numSize, size);
|
||||
if(parent != null) {
|
||||
parent.updateNumSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void updateStrSize(int size) {
|
||||
this.strSize = Math.max(strSize, size);
|
||||
if(parent != null) {
|
||||
parent.updateStrSize(size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getIndex(String id) {
|
||||
return indices.get(id).getLeft();
|
||||
}
|
||||
|
||||
|
||||
public ReturnType getType(String id) {
|
||||
return indices.get(id).getRight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean contains(String id) {
|
||||
return indices.containsKey(id);
|
||||
}
|
||||
|
||||
@@ -14,17 +14,17 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class BooleanConstant extends ConstantExpression<Boolean> {
|
||||
private final boolean constant;
|
||||
|
||||
|
||||
public BooleanConstant(Boolean constant, Position position) {
|
||||
super(constant, position);
|
||||
this.constant = constant;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
|
||||
@@ -16,22 +16,22 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public abstract class ConstantExpression<T> implements Returnable<T> {
|
||||
private final T constant;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public ConstantExpression(T constant, Position position) {
|
||||
this.constant = constant;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
public T getConstant() {
|
||||
return constant;
|
||||
}
|
||||
|
||||
@@ -15,17 +15,17 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class NumericConstant extends ConstantExpression<Number> {
|
||||
private final double constant;
|
||||
|
||||
|
||||
public NumericConstant(Number constant, Position position) {
|
||||
super(constant, position);
|
||||
this.constant = constant.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class StringConstant extends ConstantExpression<String> {
|
||||
public StringConstant(String constant, Position position) {
|
||||
super(constant, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.STRING;
|
||||
|
||||
@@ -19,23 +19,23 @@ public interface Function<T> extends Returnable<T> {
|
||||
public ReturnType returnType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((Number) apply(implementationArguments, scope)).doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return (Boolean) apply(implementationArguments, scope);
|
||||
|
||||
@@ -15,8 +15,8 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public interface FunctionBuilder<T extends Function<?>> {
|
||||
T build(List<Returnable<?>> argumentList, Position position);
|
||||
|
||||
|
||||
int argNumber();
|
||||
|
||||
|
||||
Returnable.ReturnType getArgument(int position);
|
||||
}
|
||||
|
||||
@@ -16,21 +16,21 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
|
||||
public BreakKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -16,21 +16,21 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
|
||||
public ContinueKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -16,21 +16,21 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
|
||||
public FailKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -16,21 +16,21 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
|
||||
public ReturnKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -22,7 +22,7 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Returnable<Boolean> statement;
|
||||
private final Item<?> incrementer;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public ForKeyword(Block conditional, Item<?> initializer, Returnable<Boolean> statement, Item<?> incrementer, Position position) {
|
||||
this.conditional = conditional;
|
||||
this.initializer = initializer;
|
||||
@@ -30,7 +30,7 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
this.incrementer = incrementer;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
for(initializer.apply(implementationArguments, scope);
|
||||
@@ -42,12 +42,12 @@ public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
private final List<Pair<Returnable<Boolean>, Block>> elseIf;
|
||||
private final Block elseBlock;
|
||||
|
||||
|
||||
public IfKeyword(Block conditional, Returnable<Boolean> statement, List<Pair<Returnable<Boolean>, Block>> elseIf,
|
||||
@Nullable Block elseBlock, Position position) {
|
||||
this.conditional = conditional;
|
||||
@@ -35,7 +35,7 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
this.elseIf = elseIf;
|
||||
this.elseBlock = elseBlock;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
if(statement.apply(implementationArguments, scope)) return conditional.apply(implementationArguments, scope);
|
||||
@@ -49,12 +49,12 @@ public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -19,13 +19,13 @@ public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Block conditional;
|
||||
private final Returnable<Boolean> statement;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public WhileKeyword(Block conditional, Returnable<Boolean> statement, Position position) {
|
||||
this.conditional = conditional;
|
||||
this.statement = statement;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
while(statement.apply(implementationArguments, scope)) {
|
||||
@@ -35,12 +35,12 @@ public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -15,13 +15,13 @@ public abstract class BinaryOperation<I, O> implements Returnable<O> {
|
||||
protected final Returnable<I> left;
|
||||
protected final Returnable<I> right;
|
||||
private final Position start;
|
||||
|
||||
|
||||
public BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return start;
|
||||
|
||||
@@ -17,17 +17,17 @@ public class BooleanAndOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
public BooleanAndOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyBoolean(implementationArguments, scope) && right.applyBoolean(implementationArguments, scope);
|
||||
|
||||
@@ -17,17 +17,17 @@ public class BooleanNotOperation extends UnaryOperation<Boolean> {
|
||||
public BooleanNotOperation(Returnable<Boolean> input, Position position) {
|
||||
super(input, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return !input.applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
|
||||
@@ -17,17 +17,17 @@ public class BooleanOrOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
public BooleanOrOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyBoolean(implementationArguments, scope) || right.applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ConcatenationOperation extends BinaryOperation<Object, Object> {
|
||||
public ConcatenationOperation(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
private static String toString(Object object) {
|
||||
String s = object.toString();
|
||||
if(object instanceof Double) {
|
||||
@@ -28,12 +28,12 @@ public class ConcatenationOperation extends BinaryOperation<Object, Object> {
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.STRING;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return toString(left.apply(implementationArguments, scope)) + toString(right.apply(implementationArguments, scope));
|
||||
|
||||
@@ -17,17 +17,17 @@ public class DivisionOperation extends BinaryOperation<Number, Number> {
|
||||
public DivisionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) / right.applyDouble(implementationArguments, scope);
|
||||
|
||||
@@ -17,17 +17,17 @@ public class ModuloOperation extends BinaryOperation<Number, Number> {
|
||||
public ModuloOperation(Returnable<Number> left, Returnable<Number> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) % right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
|
||||
@@ -17,17 +17,17 @@ public class MultiplicationOperation extends BinaryOperation<Number, Number> {
|
||||
public MultiplicationOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) * right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
|
||||
@@ -17,17 +17,17 @@ public class NegationOperation extends UnaryOperation<Number> {
|
||||
public NegationOperation(Returnable<Number> input, Position position) {
|
||||
super(input, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return -input.applyDouble(implementationArguments, scope);
|
||||
|
||||
@@ -17,17 +17,17 @@ public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
|
||||
public NumberAdditionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) + right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
|
||||
@@ -17,17 +17,17 @@ public class SubtractionOperation extends BinaryOperation<Number, Number> {
|
||||
public SubtractionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) - right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
|
||||
@@ -14,12 +14,12 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public abstract class UnaryOperation<T> implements Returnable<T> {
|
||||
protected final Returnable<T> input;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public UnaryOperation(Returnable<T> input, Position position) {
|
||||
this.input = input;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -17,22 +17,22 @@ import static com.dfsek.terra.api.util.MathUtil.EPSILON;
|
||||
|
||||
|
||||
public class EqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
|
||||
|
||||
public EqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
Object leftValue = left.apply(implementationArguments, scope);
|
||||
@@ -40,7 +40,7 @@ public class EqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
||||
return Math.abs(l.doubleValue() - r.doubleValue()) <= EPSILON;
|
||||
}
|
||||
|
||||
|
||||
return leftValue.equals(rightValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,17 @@ public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolea
|
||||
public GreaterOrEqualsThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) >= right.applyDouble(implementationArguments, scope);
|
||||
|
||||
@@ -18,18 +18,18 @@ public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
public GreaterThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) > right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
|
||||
@@ -18,18 +18,18 @@ public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean>
|
||||
public LessThanOrEqualsStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) <= right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
|
||||
@@ -18,18 +18,18 @@ public class LessThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
public LessThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return left.applyDouble(implementationArguments, scope) < right.applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
|
||||
@@ -20,12 +20,12 @@ public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
public NotEqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
Object leftValue = left.apply(implementationArguments, scope);
|
||||
@@ -33,10 +33,10 @@ public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
||||
return Math.abs(l.doubleValue() - r.doubleValue()) > EPSILON;
|
||||
}
|
||||
|
||||
|
||||
return !leftValue.equals(rightValue);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType returnType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
|
||||
@@ -14,27 +14,27 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class BooleanVariable implements Variable<Boolean> {
|
||||
private final Position position;
|
||||
private Boolean value;
|
||||
|
||||
|
||||
public BooleanVariable(Boolean value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -14,27 +14,27 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class NumberVariable implements Variable<Number> {
|
||||
private final Position position;
|
||||
private Number value;
|
||||
|
||||
|
||||
public NumberVariable(Number value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setValue(Number value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -14,27 +14,27 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class StringVariable implements Variable<String> {
|
||||
private final Position position;
|
||||
private String value;
|
||||
|
||||
|
||||
public StringVariable(String value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.STRING;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -13,10 +13,10 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public interface Variable<T> {
|
||||
T getValue();
|
||||
|
||||
|
||||
void setValue(T value);
|
||||
|
||||
|
||||
Returnable.ReturnType getType();
|
||||
|
||||
|
||||
Position getPosition();
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ public class BoolAssignmentNode extends VariableAssignmentNode<Boolean> {
|
||||
public BoolAssignmentNode(Returnable<Boolean> value, Position position, int index) {
|
||||
super(value, position, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyBoolean(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
boolean val = value.applyBoolean(implementationArguments, scope);
|
||||
|
||||
@@ -10,12 +10,12 @@ public class NumAssignmentNode extends VariableAssignmentNode<Number> {
|
||||
public NumAssignmentNode(Returnable<Number> value, Position position, int index) {
|
||||
super(value, position, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return applyDouble(implementationArguments, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
double val = value.applyDouble(implementationArguments, scope);
|
||||
|
||||
@@ -10,12 +10,12 @@ public class StrAssignmentNode extends VariableAssignmentNode<String> {
|
||||
public StrAssignmentNode(Returnable<String> value, Position position, int index) {
|
||||
super(value, position, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
String val = value.apply(implementationArguments, scope);
|
||||
scope.setStr(index, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ public abstract class VariableAssignmentNode<T> implements Item<T> {
|
||||
protected final Returnable<T> value;
|
||||
protected final int index;
|
||||
private final Position position;
|
||||
|
||||
|
||||
|
||||
|
||||
public VariableAssignmentNode(Returnable<T> value, Position position, int index) {
|
||||
this.value = value;
|
||||
this.index = index;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -9,12 +9,12 @@ public class BoolVariableReferenceNode extends VariableReferenceNode<Boolean> {
|
||||
public BoolVariableReferenceNode(Position position, ReturnType type, int index) {
|
||||
super(position, type, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getBool(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getBool(index);
|
||||
|
||||
@@ -9,12 +9,12 @@ public class NumVariableReferenceNode extends VariableReferenceNode<Number> {
|
||||
public NumVariableReferenceNode(Position position, ReturnType type, int index) {
|
||||
super(position, type, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getNum(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getNum(index);
|
||||
|
||||
@@ -9,7 +9,7 @@ public class StrVariableReferenceNode extends VariableReferenceNode<String> {
|
||||
public StrVariableReferenceNode(Position position, ReturnType type, int index) {
|
||||
super(position, type, index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return scope.getStr(index);
|
||||
|
||||
@@ -15,18 +15,18 @@ public abstract class VariableReferenceNode<T> implements Returnable<T> {
|
||||
protected final int index;
|
||||
private final Position position;
|
||||
private final ReturnType type;
|
||||
|
||||
|
||||
public VariableReferenceNode(Position position, ReturnType type, int index) {
|
||||
this.position = position;
|
||||
this.type = type;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -53,10 +53,10 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StructureScript.class);
|
||||
private final Executable block;
|
||||
private final RegistryKey id;
|
||||
|
||||
|
||||
private final String profile;
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public StructureScript(InputStream inputStream, RegistryKey id, Platform platform, Registry<Structure> registry,
|
||||
Registry<LootTable> lootRegistry,
|
||||
@@ -69,66 +69,66 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
|
||||
}
|
||||
this.id = id;
|
||||
this.profile = "terrascript_direct:" + id;
|
||||
|
||||
|
||||
//noinspection unchecked
|
||||
functionRegistry.forEach((key, function) -> parser.registerFunction(key.getID(), function)); // Register registry functions.
|
||||
|
||||
|
||||
parser
|
||||
.registerFunction("block", new BlockFunctionBuilder(platform))
|
||||
.registerFunction("debugBlock", new BlockFunctionBuilder(platform))
|
||||
.registerFunction("structure", new StructureFunctionBuilder(registry, platform))
|
||||
.registerFunction("randomInt", new RandomFunctionBuilder())
|
||||
.registerFunction("recursions", new RecursionsFunctionBuilder())
|
||||
.registerFunction("setMark", new SetMarkFunctionBuilder())
|
||||
.registerFunction("getMark", new GetMarkFunctionBuilder())
|
||||
.registerFunction("pull", new PullFunctionBuilder(platform))
|
||||
.registerFunction("loot", new LootFunctionBuilder(platform, lootRegistry, this))
|
||||
.registerFunction("entity", new EntityFunctionBuilder(platform))
|
||||
.registerFunction("getBiome", new BiomeFunctionBuilder(platform))
|
||||
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
|
||||
.registerFunction("state", new StateFunctionBuilder(platform))
|
||||
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
|
||||
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getX(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getY(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getZ(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(),
|
||||
Returnable.ReturnType.STRING))
|
||||
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("print",
|
||||
new UnaryStringFunctionBuilder(string -> LOGGER.info("[TerraScript:{}] {}", id, string)))
|
||||
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> Math.abs(number.doubleValue())))
|
||||
.registerFunction("pow2", new UnaryNumberFunctionBuilder(number -> Math.pow(number.doubleValue(), 2)))
|
||||
.registerFunction("pow", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.pow(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> Math.sqrt(number.doubleValue())))
|
||||
.registerFunction("rsqrt", new UnaryNumberFunctionBuilder(number -> MathUtil.invSqrt(number.doubleValue())))
|
||||
.registerFunction("floor", new UnaryNumberFunctionBuilder(number -> Math.floor(number.doubleValue())))
|
||||
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> Math.ceil(number.doubleValue())))
|
||||
.registerFunction("log", new UnaryNumberFunctionBuilder(number -> Math.log(number.doubleValue())))
|
||||
.registerFunction("round", new UnaryNumberFunctionBuilder(number -> Math.round(number.doubleValue())))
|
||||
.registerFunction("sin", new UnaryNumberFunctionBuilder(number -> MathUtil.sin(number.doubleValue())))
|
||||
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> MathUtil.cos(number.doubleValue())))
|
||||
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> MathUtil.tan(number.doubleValue())))
|
||||
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> Math.asin(number.doubleValue())))
|
||||
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> Math.acos(number.doubleValue())))
|
||||
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> Math.atan(number.doubleValue())))
|
||||
.registerFunction("max", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.max(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("min", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.min(number.doubleValue(), number2.doubleValue())));
|
||||
|
||||
.registerFunction("block", new BlockFunctionBuilder(platform))
|
||||
.registerFunction("debugBlock", new BlockFunctionBuilder(platform))
|
||||
.registerFunction("structure", new StructureFunctionBuilder(registry, platform))
|
||||
.registerFunction("randomInt", new RandomFunctionBuilder())
|
||||
.registerFunction("recursions", new RecursionsFunctionBuilder())
|
||||
.registerFunction("setMark", new SetMarkFunctionBuilder())
|
||||
.registerFunction("getMark", new GetMarkFunctionBuilder())
|
||||
.registerFunction("pull", new PullFunctionBuilder(platform))
|
||||
.registerFunction("loot", new LootFunctionBuilder(platform, lootRegistry, this))
|
||||
.registerFunction("entity", new EntityFunctionBuilder(platform))
|
||||
.registerFunction("getBiome", new BiomeFunctionBuilder(platform))
|
||||
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
|
||||
.registerFunction("state", new StateFunctionBuilder(platform))
|
||||
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
|
||||
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getX(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getY(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getZ(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(),
|
||||
Returnable.ReturnType.STRING))
|
||||
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(),
|
||||
Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("print",
|
||||
new UnaryStringFunctionBuilder(string -> LOGGER.info("[TerraScript:{}] {}", id, string)))
|
||||
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> Math.abs(number.doubleValue())))
|
||||
.registerFunction("pow2", new UnaryNumberFunctionBuilder(number -> Math.pow(number.doubleValue(), 2)))
|
||||
.registerFunction("pow", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.pow(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> Math.sqrt(number.doubleValue())))
|
||||
.registerFunction("rsqrt", new UnaryNumberFunctionBuilder(number -> MathUtil.invSqrt(number.doubleValue())))
|
||||
.registerFunction("floor", new UnaryNumberFunctionBuilder(number -> Math.floor(number.doubleValue())))
|
||||
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> Math.ceil(number.doubleValue())))
|
||||
.registerFunction("log", new UnaryNumberFunctionBuilder(number -> Math.log(number.doubleValue())))
|
||||
.registerFunction("round", new UnaryNumberFunctionBuilder(number -> Math.round(number.doubleValue())))
|
||||
.registerFunction("sin", new UnaryNumberFunctionBuilder(number -> MathUtil.sin(number.doubleValue())))
|
||||
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> MathUtil.cos(number.doubleValue())))
|
||||
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> MathUtil.tan(number.doubleValue())))
|
||||
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> Math.asin(number.doubleValue())))
|
||||
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> Math.acos(number.doubleValue())))
|
||||
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> Math.atan(number.doubleValue())))
|
||||
.registerFunction("max", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.max(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("min", new BinaryNumberFunctionBuilder(
|
||||
(number, number2) -> Math.min(number.doubleValue(), number2.doubleValue())));
|
||||
|
||||
if(!platform.getTerraConfig().isDebugScript()) {
|
||||
parser.ignoreFunction("debugBlock");
|
||||
}
|
||||
|
||||
|
||||
block = parser.parse();
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
|
||||
@@ -137,14 +137,14 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
|
||||
platform.getProfiler().pop(profile);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation, int recursions) {
|
||||
platform.getProfiler().push(profile);
|
||||
boolean result = applyBlock(new TerraImplementationArguments(location, rotation, random, world, recursions));
|
||||
platform.getProfiler().pop(profile);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private boolean applyBlock(TerraImplementationArguments arguments) {
|
||||
try {
|
||||
return block.execute(arguments);
|
||||
@@ -153,7 +153,7 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RegistryKey getRegistryKey() {
|
||||
return id;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class TerraImplementationArguments implements ImplementationArguments {
|
||||
private final int recursions;
|
||||
private final Vector3Int origin;
|
||||
private boolean waterlog = false;
|
||||
|
||||
|
||||
public TerraImplementationArguments(Vector3Int origin, Rotation rotation, Random random, WritableWorld world, int recursions) {
|
||||
this.rotation = rotation;
|
||||
this.random = random;
|
||||
@@ -34,39 +34,39 @@ public class TerraImplementationArguments implements ImplementationArguments {
|
||||
this.recursions = recursions;
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
|
||||
public int getRecursions() {
|
||||
return recursions;
|
||||
}
|
||||
|
||||
|
||||
public Random getRandom() {
|
||||
return random;
|
||||
}
|
||||
|
||||
|
||||
public Rotation getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
|
||||
public boolean isWaterlog() {
|
||||
return waterlog;
|
||||
}
|
||||
|
||||
|
||||
public void setWaterlog(boolean waterlog) {
|
||||
this.waterlog = waterlog;
|
||||
}
|
||||
|
||||
|
||||
public WritableWorld getWorld() {
|
||||
return world;
|
||||
}
|
||||
|
||||
|
||||
public Vector3Int getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
|
||||
public void setMark(Vector3 pos, String mark) {
|
||||
marks.put(pos, mark);
|
||||
}
|
||||
|
||||
|
||||
public String getMark(Vector3 pos) {
|
||||
return marks.get(pos);
|
||||
}
|
||||
|
||||
@@ -19,13 +19,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
||||
|
||||
|
||||
private final BiFunction<Number, Number, Number> function;
|
||||
|
||||
|
||||
public BinaryNumberFunctionBuilder(BiFunction<Number, Number, Number> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<>() {
|
||||
@@ -33,26 +33,26 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Num
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, scope),
|
||||
((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, scope));
|
||||
((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, scope));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0 || position == 1) return Returnable.ReturnType.NUMBER;
|
||||
|
||||
@@ -18,23 +18,23 @@ import com.dfsek.terra.api.Platform;
|
||||
|
||||
public class BiomeFunctionBuilder implements FunctionBuilder<BiomeFunction> {
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public BiomeFunctionBuilder(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BiomeFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new BiomeFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -21,11 +21,11 @@ import com.dfsek.terra.api.Platform;
|
||||
|
||||
public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> {
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public BlockFunctionBuilder(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BlockFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
@@ -36,19 +36,19 @@ public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> {
|
||||
if(argumentList.size() == 6) physics = (Returnable<Boolean>) argumentList.get(5);
|
||||
if(argumentList.get(3) instanceof StringConstant) {
|
||||
return new BlockFunction.Constant((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (StringConstant) argumentList.get(3),
|
||||
overwrite, physics, platform, position);
|
||||
(Returnable<Number>) argumentList.get(2), (StringConstant) argumentList.get(3),
|
||||
overwrite, physics, platform, position);
|
||||
}
|
||||
return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), overwrite, physics,
|
||||
platform, position);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), overwrite, physics,
|
||||
platform, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -20,14 +20,14 @@ public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunc
|
||||
@Override
|
||||
public CheckBlockFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new CheckBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -18,23 +18,23 @@ import com.dfsek.terra.api.Platform;
|
||||
|
||||
public class EntityFunctionBuilder implements FunctionBuilder<EntityFunction> {
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public EntityFunctionBuilder(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public EntityFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new EntityFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -16,22 +16,22 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class GetMarkFunctionBuilder implements FunctionBuilder<GetMarkFunction> {
|
||||
|
||||
|
||||
public GetMarkFunctionBuilder() {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public GetMarkFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new GetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
(Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -23,26 +23,26 @@ public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
|
||||
private final Platform platform;
|
||||
private final Registry<LootTable> registry;
|
||||
private final StructureScript script;
|
||||
|
||||
|
||||
public LootFunctionBuilder(Platform platform, Registry<LootTable> registry, StructureScript script) {
|
||||
this.platform = platform;
|
||||
this.registry = registry;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position,
|
||||
script);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position,
|
||||
script);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -18,23 +18,23 @@ import com.dfsek.terra.api.Platform;
|
||||
|
||||
public class PullFunctionBuilder implements FunctionBuilder<PullFunction> {
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public PullFunctionBuilder(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PullFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new PullFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), platform, position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -21,12 +21,12 @@ public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
|
||||
public RandomFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new RandomFunction((Returnable<Number>) argumentList.get(0), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.NUMBER;
|
||||
|
||||
@@ -20,12 +20,12 @@ public class RecursionsFunctionBuilder implements FunctionBuilder<RecursionsFunc
|
||||
public RecursionsFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new RecursionsFunction(position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return null;
|
||||
|
||||
@@ -16,22 +16,22 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class SetMarkFunctionBuilder implements FunctionBuilder<SetMarkFunction> {
|
||||
|
||||
|
||||
public SetMarkFunctionBuilder() {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public SetMarkFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new SetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -19,24 +19,24 @@ import com.dfsek.terra.api.Platform;
|
||||
|
||||
public class StateFunctionBuilder implements FunctionBuilder<StateFunction> {
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public StateFunctionBuilder(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StateFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
|
||||
return new StateFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1),
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
|
||||
(Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -23,28 +23,28 @@ import com.dfsek.terra.api.structure.Structure;
|
||||
public class StructureFunctionBuilder implements FunctionBuilder<StructureFunction> {
|
||||
private final Registry<Structure> registry;
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public StructureFunctionBuilder(Registry<Structure> registry, Platform platform) {
|
||||
this.registry = registry;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StructureFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
if(argumentList.size() < 5) throw new ParseException("Expected rotations", position);
|
||||
|
||||
|
||||
return new StructureFunction((Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0),
|
||||
(Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
|
||||
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry,
|
||||
position, platform);
|
||||
(Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
|
||||
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry,
|
||||
position, platform);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
|
||||
@@ -20,13 +20,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
||||
|
||||
|
||||
private final BiConsumer<Boolean, TerraImplementationArguments> function;
|
||||
|
||||
|
||||
public UnaryBooleanFunctionBuilder(BiConsumer<Boolean, TerraImplementationArguments> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<>() {
|
||||
@@ -34,27 +34,27 @@ public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Voi
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Returnable<Boolean>) argumentList.get(0)).apply(implementationArguments, scope),
|
||||
(TerraImplementationArguments) implementationArguments);
|
||||
(TerraImplementationArguments) implementationArguments);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.BOOLEAN;
|
||||
|
||||
@@ -18,13 +18,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
||||
|
||||
|
||||
private final java.util.function.Function<Number, Number> function;
|
||||
|
||||
|
||||
public UnaryNumberFunctionBuilder(java.util.function.Function<Number, Number> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<>() {
|
||||
@@ -32,25 +32,25 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Numb
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, scope));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.NUMBER;
|
||||
|
||||
@@ -18,13 +18,13 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
||||
|
||||
|
||||
private final java.util.function.Consumer<String> function;
|
||||
|
||||
|
||||
public UnaryStringFunctionBuilder(java.util.function.Consumer<String> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<>() {
|
||||
@@ -32,26 +32,26 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
function.accept(((Returnable<String>) argumentList.get(0)).apply(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.STRING;
|
||||
|
||||
@@ -21,12 +21,12 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
|
||||
private final java.util.function.Function<TerraImplementationArguments, T> function;
|
||||
private final Returnable.ReturnType type;
|
||||
|
||||
|
||||
public ZeroArgFunctionBuilder(java.util.function.Function<TerraImplementationArguments, T> function, Returnable.ReturnType type) {
|
||||
this.function = function;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<T> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<>() {
|
||||
@@ -34,24 +34,24 @@ public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
|
||||
public ReturnType returnType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return function.apply((TerraImplementationArguments) implementationArguments);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return type;
|
||||
|
||||
@@ -22,40 +22,40 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
public class BiomeFunction implements Function<String> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
|
||||
|
||||
public BiomeFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
BiomeProvider grid = arguments.getWorld().getBiomeProvider();
|
||||
|
||||
|
||||
return grid.getBiome(arguments.getOrigin()
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ()))).immutable(), arguments.getWorld().getSeed()).getID();
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ()))).immutable(), arguments.getWorld().getSeed()).getID();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
package com.dfsek.terra.addons.terrascript.script.functions;
|
||||
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -18,6 +16,7 @@ import java.util.Map;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.Scope;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant;
|
||||
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
|
||||
@@ -38,7 +37,7 @@ public class BlockFunction implements Function<Void> {
|
||||
private final Returnable<Boolean> overwrite;
|
||||
private final Returnable<Boolean> physics;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData,
|
||||
Returnable<Boolean> overwrite, Platform platform, Position position) {
|
||||
this.x = x;
|
||||
@@ -48,9 +47,9 @@ public class BlockFunction implements Function<Void> {
|
||||
this.overwrite = overwrite;
|
||||
this.platform = platform;
|
||||
this.position = position;
|
||||
this.physics = new BooleanConstant(false, position);;
|
||||
this.physics = new BooleanConstant(false, position);
|
||||
}
|
||||
|
||||
|
||||
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData,
|
||||
Returnable<Boolean> overwrite, Returnable<Boolean> physics, Platform platform, Position position) {
|
||||
this.x = x;
|
||||
@@ -62,7 +61,7 @@ public class BlockFunction implements Function<Void> {
|
||||
this.position = position;
|
||||
this.physics = physics;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
@@ -70,25 +69,25 @@ public class BlockFunction implements Function<Void> {
|
||||
setBlock(implementationArguments, scope, arguments, rot);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
|
||||
void setBlock(ImplementationArguments implementationArguments, Scope scope,
|
||||
TerraImplementationArguments arguments, BlockState rot) {
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
try {
|
||||
Vector3.Mutable set = Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).doubleValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
y.apply(implementationArguments, scope).doubleValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
BlockState current = arguments.getWorld().getBlockState(set);
|
||||
if(overwrite.apply(implementationArguments, scope) || current.isAir()) {
|
||||
arguments.getWorld().setBlockState(set, rot, physics.apply(implementationArguments, scope));
|
||||
@@ -97,21 +96,21 @@ public class BlockFunction implements Function<Void> {
|
||||
logger.error("Failed to place block at location {}", arguments.getOrigin(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) {
|
||||
return data.computeIfAbsent(blockData.apply(arguments, scope), platform.getWorldHandle()::createBlockState);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static class Constant extends BlockFunction {
|
||||
private final BlockState state;
|
||||
|
||||
|
||||
public Constant(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, StringConstant blockData,
|
||||
Returnable<Boolean> overwrite, Returnable<Boolean> physics, Platform platform, Position position) {
|
||||
super(x, y, z, blockData, overwrite, physics, platform, position);
|
||||
this.state = platform.getWorldHandle().createBlockState(blockData.getConstant());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) {
|
||||
return state;
|
||||
|
||||
@@ -21,41 +21,41 @@ import com.dfsek.terra.api.util.vector.Vector3;
|
||||
public class CheckBlockFunction implements Function<String> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public CheckBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
String data = arguments.getWorld()
|
||||
.getBlockState(arguments.getOrigin()
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope)
|
||||
.doubleValue(), (int) Math.round(xz.getZ()))))
|
||||
.getAsString();
|
||||
.getBlockState(arguments.getOrigin()
|
||||
.toVector3()
|
||||
.mutable()
|
||||
.add(Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope)
|
||||
.doubleValue(), (int) Math.round(xz.getZ()))))
|
||||
.getAsString();
|
||||
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
|
||||
else return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
|
||||
@@ -29,40 +29,40 @@ public class EntityFunction implements Function<Void> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final Platform platform;
|
||||
|
||||
|
||||
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Platform platform,
|
||||
Position position) {
|
||||
this.position = position;
|
||||
this.platform = platform;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
|
||||
|
||||
|
||||
this.data = platform.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
Entity entity = arguments.getWorld().spawnEntity(Vector3.of(xz.getX(), y.apply(implementationArguments, scope).doubleValue(),
|
||||
xz.getZ())
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
.add(0.5, 0, 0.5)
|
||||
.immutable(), data);
|
||||
xz.getZ())
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
.add(0.5, 0, 0.5)
|
||||
.immutable(), data);
|
||||
platform.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getPack(), entity));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -21,34 +21,34 @@ import com.dfsek.terra.api.util.vector.Vector3;
|
||||
public class GetMarkFunction implements Function<String> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public GetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.position = position;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
String mark = arguments.getMark(Vector3.of((int) Math.floor(xz.getX()), (int) Math.floor(
|
||||
y.apply(implementationArguments, scope).doubleValue()),
|
||||
(int) Math.floor(xz.getZ()))
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
.immutable());
|
||||
y.apply(implementationArguments, scope).doubleValue()),
|
||||
(int) Math.floor(xz.getZ()))
|
||||
.mutable()
|
||||
.add(arguments.getOrigin())
|
||||
.immutable());
|
||||
return mark == null ? "" : mark;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
|
||||
@@ -39,7 +39,7 @@ public class LootFunction implements Function<Void> {
|
||||
private final Position position;
|
||||
private final Platform platform;
|
||||
private final StructureScript script;
|
||||
|
||||
|
||||
public LootFunction(Registry<LootTable> registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z,
|
||||
Returnable<String> data, Platform platform, Position position, StructureScript script) {
|
||||
this.registry = registry;
|
||||
@@ -51,55 +51,55 @@ public class LootFunction implements Function<Void> {
|
||||
this.platform = platform;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()),
|
||||
arguments.getRotation());
|
||||
|
||||
|
||||
String id = data.apply(implementationArguments, scope);
|
||||
|
||||
|
||||
|
||||
|
||||
registry.get(RegistryKey.parse(id))
|
||||
.ifPresentOrElse(table -> {
|
||||
Vector3 apply = Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope)
|
||||
.intValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
|
||||
try {
|
||||
BlockEntity data = arguments.getWorld().getBlockEntity(apply);
|
||||
if(!(data instanceof Container container)) {
|
||||
LOGGER.error("Failed to place loot at {}; block {} is not a container",
|
||||
apply, data);
|
||||
return;
|
||||
}
|
||||
|
||||
LootPopulateEvent event = new LootPopulateEvent(container, table,
|
||||
arguments.getWorld().getPack(), script);
|
||||
platform.getEventManager().callEvent(event);
|
||||
if(event.isCancelled()) return;
|
||||
|
||||
event.getTable().fillInventory(container.getInventory(),
|
||||
new Random(apply.hashCode()));
|
||||
data.update(false);
|
||||
} catch(Exception e) {
|
||||
LOGGER.error("Could not apply loot at {}", apply, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
},
|
||||
() -> LOGGER.error("No such loot table {}", id));
|
||||
.ifPresentOrElse(table -> {
|
||||
Vector3 apply = Vector3.of((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope)
|
||||
.intValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
|
||||
try {
|
||||
BlockEntity data = arguments.getWorld().getBlockEntity(apply);
|
||||
if(!(data instanceof Container container)) {
|
||||
LOGGER.error("Failed to place loot at {}; block {} is not a container",
|
||||
apply, data);
|
||||
return;
|
||||
}
|
||||
|
||||
LootPopulateEvent event = new LootPopulateEvent(container, table,
|
||||
arguments.getWorld().getPack(), script);
|
||||
platform.getEventManager().callEvent(event);
|
||||
if(event.isCancelled()) return;
|
||||
|
||||
event.getTable().fillInventory(container.getInventory(),
|
||||
new Random(apply.hashCode()));
|
||||
data.update(false);
|
||||
} catch(Exception e) {
|
||||
LOGGER.error("Could not apply loot at {}", apply, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
},
|
||||
() -> LOGGER.error("No such loot table {}", id));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -26,26 +26,26 @@ public class PullFunction implements Function<Void> {
|
||||
private final BlockState data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public PullFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Platform platform,
|
||||
Position position) {
|
||||
this.position = position;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
|
||||
|
||||
|
||||
this.data = platform.getWorldHandle().createBlockState(((ConstantExpression<String>) data).getConstant());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
Vector3.Mutable mutable = Vector3.of((int) Math.round(xz.getX()), y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin());
|
||||
while(mutable.getY() > arguments.getWorld().getMinHeight()) {
|
||||
if(!arguments.getWorld().getBlockState(mutable).isAir()) {
|
||||
arguments.getWorld().setBlockState(mutable, data);
|
||||
@@ -55,12 +55,12 @@ public class PullFunction implements Function<Void> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -18,24 +18,24 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
public class RandomFunction implements Function<Integer> {
|
||||
private final Returnable<Number> numberReturnable;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public RandomFunction(Returnable<Number> numberReturnable, Position position) {
|
||||
this.numberReturnable = numberReturnable;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Integer apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(
|
||||
numberReturnable.apply(implementationArguments, scope).intValue());
|
||||
numberReturnable.apply(implementationArguments, scope).intValue());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -16,21 +16,21 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
public class RecursionsFunction implements Function<Number> {
|
||||
private final Position position;
|
||||
|
||||
|
||||
public RecursionsFunction(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRecursions();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -22,7 +22,7 @@ public class SetMarkFunction implements Function<Void> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final Returnable<String> mark;
|
||||
|
||||
|
||||
public SetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> mark, Position position) {
|
||||
this.position = position;
|
||||
this.mark = mark;
|
||||
@@ -30,27 +30,27 @@ public class SetMarkFunction implements Function<Void> {
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
arguments.setMark(Vector3.of((int) Math.floor(xz.getX()),
|
||||
(int) Math.floor(
|
||||
y.apply(implementationArguments, scope).doubleValue()),
|
||||
(int) Math.floor(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(),
|
||||
mark.apply(implementationArguments, scope));
|
||||
(int) Math.floor(
|
||||
y.apply(implementationArguments, scope).doubleValue()),
|
||||
(int) Math.floor(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(),
|
||||
mark.apply(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -27,7 +27,7 @@ public class StateFunction implements Function<Void> {
|
||||
private final Returnable<String> data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public StateFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data,
|
||||
Position position) {
|
||||
this.position = position;
|
||||
@@ -36,16 +36,16 @@ public class StateFunction implements Function<Void> {
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
Vector3 origin = Vector3.of((int) Math.round(xz.getX()), y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
||||
try {
|
||||
BlockEntity state = arguments.getWorld().getBlockEntity(origin);
|
||||
state.applyState(data.apply(implementationArguments, scope));
|
||||
@@ -56,12 +56,12 @@ public class StateFunction implements Function<Void> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class StructureFunction implements Function<Boolean> {
|
||||
private final Position position;
|
||||
private final Platform platform;
|
||||
private final List<Returnable<String>> rotations;
|
||||
|
||||
|
||||
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id,
|
||||
List<Returnable<String>> rotations, Registry<Structure> registry, Position position, Platform platform) {
|
||||
this.registry = registry;
|
||||
@@ -47,23 +47,23 @@ public class StructureFunction implements Function<Boolean> {
|
||||
this.platform = platform;
|
||||
this.rotations = rotations;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean apply(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.apply(implementationArguments, scope).doubleValue(),
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
z.apply(implementationArguments, scope).doubleValue()), arguments.getRotation());
|
||||
|
||||
|
||||
String app = id.apply(implementationArguments, scope);
|
||||
return registry.getByID(app).map(script -> {
|
||||
Rotation rotation1;
|
||||
@@ -74,29 +74,29 @@ public class StructureFunction implements Function<Boolean> {
|
||||
LOGGER.warn("Invalid rotation {}", rotString);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(script instanceof StructureScript structureScript) {
|
||||
return structureScript.generate(arguments.getOrigin(),
|
||||
arguments.getWorld()
|
||||
.buffer((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
|
||||
arguments.getWorld()
|
||||
.buffer((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
|
||||
}
|
||||
return script.generate(arguments.getOrigin(),
|
||||
arguments.getWorld()
|
||||
.buffer((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1));
|
||||
arguments.getWorld()
|
||||
.buffer((int) Math.round(xz.getX()),
|
||||
y.apply(implementationArguments, scope).intValue(),
|
||||
(int) Math.round(xz.getZ())),
|
||||
arguments.getRandom(),
|
||||
arguments.getRotation().rotate(rotation1));
|
||||
}).orElseGet(() -> {
|
||||
LOGGER.error("No such structure {}", app);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
|
||||
@@ -11,14 +11,14 @@ public class Char {
|
||||
private final char character;
|
||||
private final int index;
|
||||
private final int line;
|
||||
|
||||
|
||||
|
||||
|
||||
public Char(char character, int index, int line) {
|
||||
this.character = character;
|
||||
this.index = index;
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
|
||||
public boolean is(char... tests) {
|
||||
for(char test : tests) {
|
||||
if(test == character && test != '\0') {
|
||||
@@ -27,36 +27,36 @@ public class Char {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Character.toString(character);
|
||||
}
|
||||
|
||||
|
||||
public char getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
public boolean isWhitespace() {
|
||||
return Character.isWhitespace(character);
|
||||
}
|
||||
|
||||
|
||||
public boolean isNewLine() {
|
||||
return character == '\n';
|
||||
}
|
||||
|
||||
|
||||
public boolean isDigit() {
|
||||
return Character.isDigit(character);
|
||||
}
|
||||
|
||||
|
||||
public boolean isEOF() {
|
||||
return character == '\0';
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ public class Lookahead {
|
||||
private int index = 0;
|
||||
private int line = 0;
|
||||
private boolean end = false;
|
||||
|
||||
|
||||
public Lookahead(Reader r) {
|
||||
this.input = r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current character without consuming it.
|
||||
*
|
||||
@@ -36,8 +36,8 @@ public class Lookahead {
|
||||
public Char current() {
|
||||
return next(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Consume and return one character.
|
||||
*
|
||||
@@ -48,7 +48,7 @@ public class Lookahead {
|
||||
consume(1);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a future character without consuming it.
|
||||
*
|
||||
@@ -58,19 +58,19 @@ public class Lookahead {
|
||||
*/
|
||||
public Char next(int ahead) {
|
||||
if(ahead < 0) throw new IllegalArgumentException();
|
||||
|
||||
|
||||
while(buffer.size() <= ahead && !end) {
|
||||
Char item = fetch();
|
||||
if(item != null) {
|
||||
buffer.add(item);
|
||||
} else end = true;
|
||||
}
|
||||
|
||||
|
||||
if(ahead >= buffer.size()) {
|
||||
return null;
|
||||
} else return buffer.get(ahead);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Consume an amount of characters
|
||||
*
|
||||
@@ -87,18 +87,18 @@ public class Lookahead {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(String check, boolean consume) {
|
||||
if(check == null) return false;
|
||||
|
||||
|
||||
for(int i = 0; i < check.length(); i++) {
|
||||
if(!next(i).is(check.charAt(i))) return false;
|
||||
}
|
||||
|
||||
|
||||
if(consume) consume(check.length()); // Consume string
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch the next character.
|
||||
*
|
||||
@@ -119,11 +119,11 @@ public class Lookahead {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ package com.dfsek.terra.addons.terrascript.tokenizer;
|
||||
public class Position {
|
||||
private final int line;
|
||||
private final int index;
|
||||
|
||||
|
||||
public Position(int line, int index) {
|
||||
this.line = line;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (line + 1) + ":" + index;
|
||||
|
||||
@@ -11,34 +11,34 @@ public class Token {
|
||||
private final String content;
|
||||
private final Type type;
|
||||
private final Position start;
|
||||
|
||||
|
||||
public Token(String content, Type type, Position start) {
|
||||
this.content = content;
|
||||
this.type = type;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type + ": '" + content + "'";
|
||||
}
|
||||
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
public Position getPosition() {
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
public boolean isConstant() {
|
||||
return this.type.equals(Type.NUMBER) || this.type.equals(Type.STRING) || this.type.equals(Type.BOOLEAN);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBinaryOperator() {
|
||||
return type.equals(Type.ADDITION_OPERATOR)
|
||||
|| type.equals(Type.SUBTRACTION_OPERATOR)
|
||||
@@ -54,7 +54,7 @@ public class Token {
|
||||
|| type.equals(Type.BOOLEAN_AND)
|
||||
|| type.equals(Type.MODULO_OPERATOR);
|
||||
}
|
||||
|
||||
|
||||
public boolean isStrictNumericOperator() {
|
||||
return type.equals(Type.SUBTRACTION_OPERATOR)
|
||||
|| type.equals(Type.MULTIPLICATION_OPERATOR)
|
||||
@@ -65,34 +65,34 @@ public class Token {
|
||||
|| type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR)
|
||||
|| type.equals(Type.MODULO_OPERATOR);
|
||||
}
|
||||
|
||||
|
||||
public boolean isStrictBooleanOperator() {
|
||||
return type.equals(Type.BOOLEAN_AND)
|
||||
|| type.equals(Type.BOOLEAN_OR);
|
||||
}
|
||||
|
||||
|
||||
public boolean isVariableDeclaration() {
|
||||
return type.equals(Type.STRING_VARIABLE)
|
||||
|| type.equals(Type.BOOLEAN_VARIABLE)
|
||||
|| type.equals(Type.NUMBER_VARIABLE);
|
||||
}
|
||||
|
||||
|
||||
public boolean isLoopLike() {
|
||||
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
|
||||
*/
|
||||
IDENTIFIER,
|
||||
|
||||
|
||||
/**
|
||||
* Numeric literal
|
||||
*/
|
||||
|
||||
@@ -21,17 +21,17 @@ import com.dfsek.terra.addons.terrascript.tokenizer.exceptions.TokenizerExceptio
|
||||
|
||||
public class Tokenizer {
|
||||
public static final Set<Character> syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/',
|
||||
'>', '<', '!'); // Reserved chars
|
||||
'>', '<', '!'); // Reserved chars
|
||||
private final Lookahead reader;
|
||||
private final Stack<Token> brackets = new Stack<>();
|
||||
private Token current;
|
||||
private Token last;
|
||||
|
||||
|
||||
public Tokenizer(String data) {
|
||||
reader = new Lookahead(new StringReader(data + '\0'));
|
||||
current = fetchCheck();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the first token.
|
||||
*
|
||||
@@ -43,7 +43,7 @@ public class Tokenizer {
|
||||
if(!hasNext()) throw new ParseException("Unexpected end of input", last.getPosition());
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Consume (get and remove) the first token.
|
||||
*
|
||||
@@ -57,7 +57,7 @@ public class Tokenizer {
|
||||
current = fetchCheck();
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
private Token fetchCheck() {
|
||||
Token fetch = fetch();
|
||||
if(fetch != null) {
|
||||
@@ -72,16 +72,16 @@ public class Tokenizer {
|
||||
}
|
||||
return fetch;
|
||||
}
|
||||
|
||||
|
||||
private Token fetch() throws TokenizerException {
|
||||
while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume();
|
||||
|
||||
|
||||
while(reader.matches("//", true)) skipLine(); // Skip line if comment
|
||||
|
||||
|
||||
if(reader.matches("/*", true)) skipTo("*/"); // Skip multi line comment
|
||||
|
||||
|
||||
if(reader.current().isEOF()) return null; // EOF
|
||||
|
||||
|
||||
if(reader.matches("==", true))
|
||||
return new Token("==", Token.Type.EQUALS_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.matches("!=", true))
|
||||
@@ -94,14 +94,14 @@ public class Tokenizer {
|
||||
return new Token(">", Token.Type.GREATER_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.matches("<", true))
|
||||
return new Token("<", Token.Type.LESS_THAN_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
|
||||
|
||||
if(reader.matches("||", true))
|
||||
return new Token("||", Token.Type.BOOLEAN_OR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.matches("&&", true))
|
||||
return new Token("&&", Token.Type.BOOLEAN_AND, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
|
||||
|
||||
if(isNumberStart()) {
|
||||
StringBuilder num = new StringBuilder();
|
||||
while(!reader.current().isEOF() && isNumberLike()) {
|
||||
@@ -109,7 +109,7 @@ public class Tokenizer {
|
||||
}
|
||||
return new Token(num.toString(), Token.Type.NUMBER, new Position(reader.getLine(), reader.getIndex()));
|
||||
}
|
||||
|
||||
|
||||
if(reader.current().is('"')) {
|
||||
reader.consume(); // Consume first quote
|
||||
StringBuilder string = new StringBuilder();
|
||||
@@ -125,10 +125,10 @@ public class Tokenizer {
|
||||
string.append(reader.consume());
|
||||
}
|
||||
reader.consume(); // Consume last quote
|
||||
|
||||
|
||||
return new Token(string.toString(), Token.Type.STRING, new Position(reader.getLine(), reader.getIndex()));
|
||||
}
|
||||
|
||||
|
||||
if(reader.current().is('('))
|
||||
return new Token(reader.consume().toString(), Token.Type.GROUP_BEGIN, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is(')'))
|
||||
@@ -147,38 +147,38 @@ public class Tokenizer {
|
||||
return new Token(reader.consume().toString(), Token.Type.ADDITION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is('-'))
|
||||
return new Token(reader.consume().toString(), Token.Type.SUBTRACTION_OPERATOR,
|
||||
new Position(reader.getLine(), reader.getIndex()));
|
||||
new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is('*'))
|
||||
return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR,
|
||||
new Position(reader.getLine(), reader.getIndex()));
|
||||
new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is('/'))
|
||||
return new Token(reader.consume().toString(), Token.Type.DIVISION_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is('%'))
|
||||
return new Token(reader.consume().toString(), Token.Type.MODULO_OPERATOR, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(reader.current().is('!'))
|
||||
return new Token(reader.consume().toString(), Token.Type.BOOLEAN_NOT, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
StringBuilder token = new StringBuilder();
|
||||
while(!reader.current().isEOF() && !isSyntaxSignificant(reader.current().getCharacter())) {
|
||||
Char c = reader.consume();
|
||||
if(c.isWhitespace()) break;
|
||||
token.append(c);
|
||||
}
|
||||
|
||||
|
||||
String tokenString = token.toString();
|
||||
|
||||
|
||||
if(tokenString.equals("true"))
|
||||
return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("false"))
|
||||
return new Token(tokenString, Token.Type.BOOLEAN, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
if(tokenString.equals("num"))
|
||||
return new Token(tokenString, Token.Type.NUMBER_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("str"))
|
||||
return new Token(tokenString, Token.Type.STRING_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("bool"))
|
||||
return new Token(tokenString, Token.Type.BOOLEAN_VARIABLE, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
if(tokenString.equals("if"))
|
||||
return new Token(tokenString, Token.Type.IF_STATEMENT, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("else"))
|
||||
@@ -187,7 +187,7 @@ public class Tokenizer {
|
||||
return new Token(tokenString, Token.Type.WHILE_LOOP, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("for"))
|
||||
return new Token(tokenString, Token.Type.FOR_LOOP, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
if(tokenString.equals("return"))
|
||||
return new Token(tokenString, Token.Type.RETURN, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("continue"))
|
||||
@@ -196,19 +196,19 @@ public class Tokenizer {
|
||||
return new Token(tokenString, Token.Type.BREAK, new Position(reader.getLine(), reader.getIndex()));
|
||||
if(tokenString.equals("fail"))
|
||||
return new Token(tokenString, Token.Type.FAIL, new Position(reader.getLine(), reader.getIndex()));
|
||||
|
||||
|
||||
return new Token(tokenString, Token.Type.IDENTIFIER, new Position(reader.getLine(), reader.getIndex()));
|
||||
}
|
||||
|
||||
|
||||
private void skipLine() {
|
||||
while(!reader.current().isEOF() && !reader.current().isNewLine()) reader.consume();
|
||||
consumeWhitespace();
|
||||
}
|
||||
|
||||
|
||||
private void consumeWhitespace() {
|
||||
while(!reader.current().isEOF() && reader.current().isWhitespace()) reader.consume(); // Consume whitespace.
|
||||
}
|
||||
|
||||
|
||||
private void skipTo(String s) throws EOFException {
|
||||
Position begin = new Position(reader.getLine(), reader.getIndex());
|
||||
while(!reader.current().isEOF()) {
|
||||
@@ -220,7 +220,7 @@ public class Tokenizer {
|
||||
}
|
||||
throw new EOFException("No end of expression found.", begin);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Whether this {@code Tokenizer} contains additional tokens.
|
||||
*
|
||||
@@ -229,19 +229,19 @@ public class Tokenizer {
|
||||
public boolean hasNext() {
|
||||
return !(current == null);
|
||||
}
|
||||
|
||||
|
||||
private boolean isNumberLike() {
|
||||
return reader.current().isDigit()
|
||||
|| reader.current().is('_', '.', 'E');
|
||||
}
|
||||
|
||||
|
||||
private boolean isNumberStart() {
|
||||
return reader.current().isDigit()
|
||||
|| reader.current().is('.') && reader.next(1).isDigit();
|
||||
}
|
||||
|
||||
|
||||
public boolean isSyntaxSignificant(char c) {
|
||||
return syntaxSignificant.contains(c);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class EOFException extends TokenizerException {
|
||||
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 3980047409902809440L;
|
||||
|
||||
|
||||
public EOFException(String message, Position position) {
|
||||
super(message, position);
|
||||
}
|
||||
|
||||
|
||||
public EOFException(String message, Position position, Throwable cause) {
|
||||
super(message, position, cause);
|
||||
}
|
||||
|
||||
@@ -13,14 +13,14 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public class FormatException extends TokenizerException {
|
||||
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = -791308012940744455L;
|
||||
|
||||
|
||||
public FormatException(String message, Position position) {
|
||||
super(message, position);
|
||||
}
|
||||
|
||||
|
||||
public FormatException(String message, Position position, Throwable cause) {
|
||||
super(message, position, cause);
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ import com.dfsek.terra.addons.terrascript.tokenizer.Position;
|
||||
|
||||
|
||||
public abstract class TokenizerException extends ParseException {
|
||||
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 2792384010083575420L;
|
||||
|
||||
|
||||
public TokenizerException(String message, Position position) {
|
||||
super(message, position);
|
||||
}
|
||||
|
||||
|
||||
public TokenizerException(String message, Position position, Throwable cause) {
|
||||
super(message, position, cause);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class LookaheadTest {
|
||||
@Test
|
||||
public void lookahead() {
|
||||
Lookahead lookahead = new Lookahead(new StringReader("Test string..."));
|
||||
|
||||
|
||||
for(int i = 0; lookahead.next(i) != null; i++) {
|
||||
System.out.print(lookahead.next(i).getCharacter());
|
||||
}
|
||||
|
||||
@@ -31,19 +31,19 @@ public class ParserTest {
|
||||
@Test
|
||||
public void parse() throws IOException, ParseException {
|
||||
Parser parser = new Parser(
|
||||
IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset()));
|
||||
|
||||
IOUtils.toString(Objects.requireNonNull(getClass().getResourceAsStream("/test.tesf")), Charset.defaultCharset()));
|
||||
|
||||
parser.registerFunction("test", new FunctionBuilder<Test1>() {
|
||||
@Override
|
||||
public Test1 build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Test1(argumentList.get(0), argumentList.get(1), position);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return switch(position) {
|
||||
@@ -52,42 +52,42 @@ public class ParserTest {
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
long l = System.nanoTime();
|
||||
Executable block = parser.parse();
|
||||
long t = System.nanoTime() - l;
|
||||
System.out.println("Took " + (double) t / 1000000);
|
||||
|
||||
|
||||
block.execute(null);
|
||||
|
||||
|
||||
block.execute(null);
|
||||
}
|
||||
|
||||
|
||||
private static class Test1 implements Function<Void> {
|
||||
private final Returnable<?> a;
|
||||
private final Returnable<?> b;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public Test1(Returnable<?> a, Returnable<?> b, Position position) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Scope scope) {
|
||||
System.out.println("string: " + a.apply(implementationArguments, scope) + ", double: " +
|
||||
b.apply(implementationArguments, scope));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
|
||||
Reference in New Issue
Block a user