diff --git a/common/addons/structure-terrascript-loader/build.gradle.kts b/common/addons/structure-terrascript-loader/build.gradle.kts index 18d4019b9..e114dea0a 100644 --- a/common/addons/structure-terrascript-loader/build.gradle.kts +++ b/common/addons/structure-terrascript-loader/build.gradle.kts @@ -12,4 +12,140 @@ dependencies { tasks.named("shadowJar") { relocate("org.apache.commons", "com.dfsek.terra.addons.terrascript.lib.commons") relocate("net.jafama", "com.dfsek.terra.addons.terrascript.lib.jafama") -} \ No newline at end of file +} + +val astSourceSet = buildDir.resolve("generated/ast") +val astPackage = astSourceSet.resolve("com/dfsek/terra/addons/terrascript/ast") + +// Auto generate AST classes rather than writing them by hand +tasks.register("genTerrascriptAstClasses") { + val packageName = astPackage.toRelativeString(astSourceSet).replace('/', '.') + fun generateClass(name: String, imports: List, nodes: List>>) { + val src = StringBuilder() + src.appendLine("package $packageName;\n"); + for (imprt in imports) src.appendLine("import $imprt;") + src.appendLine(""" + import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + import com.dfsek.terra.addons.terrascript.Environment; + + /** + * Auto-generated class via genTerrascriptAstClasses gradle task + */ + public abstract class $name { + + public final SourcePosition position; + private Environment environment; + + public $name(SourcePosition position) { + this.position = position; + } + + public Environment getEnvironment() { + if (this.environment == null) throw new RuntimeException("Compilation bug! environment has not been set yet for AST node"); + return environment; + } + + public void setEnvironment(Environment environment) { + if (this.environment != null) throw new RuntimeException("Compilation bug! environment has already been set for AST node and cannot be changed"); + this.environment = environment; + } + + public interface Visitor { + + """.trimIndent()) + for (node in nodes) { + src.appendLine(" R visit${node.first}$name(${node.first} ${name.toLowerCase()});") + } + + src.appendLine(""" + | + | } + | + | public abstract R accept(Visitor visitor); + """.trimMargin()) + + for (node in nodes) { + src.appendLine() + // Inner class declaration + src.appendLine(" public static class ${node.first} extends $name {\n") + + // Add fields + for (field in node.second) { + src.appendLine(" public final $field;") + } + src.appendLine() + + // Add constructor + src.append(" public ${node.first}(") + for (field in node.second) + src.append("$field, ") + src.appendLine("SourcePosition position) {\n super(position);") + for (field in node.second) { + val fieldName = field.split(' ').last() + src.appendLine(" this.$fieldName = $fieldName;") + } + + src.appendLine(""" + | } + | + | @Override + | public R accept(Visitor visitor) { + | return visitor.visit${node.first}$name(this); + | } + | } + """.trimMargin()) + } + src.appendLine("}") + val outputFile = astPackage.resolve("$name.java") + outputFile.writeText(src.toString()) + } + + doLast { + astSourceSet.deleteRecursively() + astPackage.mkdirs() + generateClass("Expr", listOf( + "com.dfsek.terra.addons.terrascript.Type", + "com.dfsek.terra.addons.terrascript.parser.UnaryOperator", + "com.dfsek.terra.addons.terrascript.parser.BinaryOperator", + "java.util.List", + ), + listOf( + Pair("Binary", listOf("Expr left", "BinaryOperator operator", "Expr right",)), + Pair("Grouping", listOf("Expr expression")), + Pair("Literal", listOf("Object value", "Type type")), + Pair("Unary", listOf("UnaryOperator operator", "Expr operand")), + Pair("Call", listOf("String identifier", "List arguments")), + Pair("Variable", listOf("String identifier")), + Pair("Assignment", listOf("Variable lValue", "Expr rValue")), + Pair("Void", listOf()), + )) + generateClass("Stmt", listOf( + "com.dfsek.terra.addons.terrascript.Type", + "com.dfsek.terra.api.util.generic.pair.Pair", + "java.util.List", + ), + listOf( + Pair("Expression", listOf("Expr expression")), + Pair("Block", listOf("List statements")), + Pair("FunctionDeclaration", listOf("String identifier", "List> parameters", "Type type", "Block body")), + Pair("VariableDeclaration", listOf("Type type", "String identifier", "Expr value")), + Pair("Return", listOf("Expr value")), + Pair("If", listOf("Expr condition", "Block trueBody", "List> elseIfClauses", "Block elseBody")), + Pair("For", listOf("Stmt initializer", "Expr condition", "Expr incrementer", "Block body")), + Pair("While", listOf("Expr condition", "Block body")), + Pair("NoOp", listOf()), + Pair("Break", listOf()), + Pair("Continue", listOf()), + )) + } +} + +tasks.getByName("compileJava") { + dependsOn("genTerrascriptAstClasses") +} + +sourceSets.getByName("main") { + java { + srcDirs(astSourceSet) + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Environment.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Environment.java new file mode 100644 index 000000000..b7824f14c --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Environment.java @@ -0,0 +1,135 @@ +package com.dfsek.terra.addons.terrascript; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.List; + +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.NonexistentSymbolException; +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.SymbolAlreadyExistsException; +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.SymbolTypeMismatchException; +import com.dfsek.terra.addons.terrascript.Environment.Symbol.Function; +import com.dfsek.terra.addons.terrascript.Environment.Symbol.Variable; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class Environment { + + private final Environment outer; + + private final boolean canAccessOuterVariables; + + private final HashMap symbolTable = new HashMap<>(); + + private final boolean inLoop; + + private Environment(@Nullable Environment outer, boolean canAccessOuterVariables, boolean inLoop) { + this.outer = outer; + this.canAccessOuterVariables = canAccessOuterVariables; + this.inLoop = inLoop; + } + + public static Environment global() { + return new Environment(null, false, false); + } + + public Environment lexicalInner() { + return new Environment(this, true, inLoop); + } + + public Environment loopInner() { + return new Environment(this, true, true); + } + + public Environment functionalInner() { + return new Environment(this, false, inLoop); + } + + public Environment outer() { + if(outer == null) throw new RuntimeException("Attempted to retrieve outer scope of global scope"); + return outer; + } + + public Function getFunction(String id) throws NonexistentSymbolException, SymbolTypeMismatchException { + Function function; + Symbol symbol = symbolTable.get(id); + if(symbol == null) { + if(outer == null) throw new NonexistentSymbolException(); + function = outer.getFunction(id); + } else { + if(!(symbol instanceof Function)) throw new SymbolTypeMismatchException(); + function = (Function) symbol; + } + return function; + } + + /** + * Returns symbol table entry for a variable identifier, includes enclosing scopes in lookup. + *
+ * Does not factor context of lookup, checks for order of declaration should be done while + * symbol tables are being populated. + * + * @param id identifier used in variable declaration + * + * @return variable symbol table entry + * + * @throws NonexistentSymbolException if symbol is not declared in symbol table + * @throws SymbolTypeMismatchException if symbol is not a variable + */ + public Variable getVariable(String id) throws NonexistentSymbolException, SymbolTypeMismatchException { + Variable variable; + Symbol symbol = symbolTable.get(id); + if(symbol == null) { + if(!canAccessOuterVariables || outer == null) throw new NonexistentSymbolException(); + variable = outer.getVariable(id); + } else { + if(!(symbol instanceof Variable)) throw new SymbolTypeMismatchException(); + variable = (Variable) symbol; + } + return variable; + } + + public void put(String id, Symbol symbol) throws SymbolAlreadyExistsException { + if(symbolTable.containsKey(id)) throw new SymbolAlreadyExistsException(); + symbolTable.put(id, symbol); + } + + public static abstract class Symbol { + + public static class Function extends Symbol { + + public final Type type; + + public final List> parameters; + + public Function(Type type, List> parameters) { + this.type = type; + this.parameters = parameters; + } + } + + + public static class Variable extends Symbol { + + public final Type type; + + public Variable(Type type) { + this.type = type; + } + } + } + + + public static class ScopeException extends RuntimeException { + + public static class SymbolAlreadyExistsException extends ScopeException { + } + + + public static class NonexistentSymbolException extends ScopeException { + } + + + public static class SymbolTypeMismatchException extends ScopeException { + } + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/ErrorHandler.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/ErrorHandler.java new file mode 100644 index 000000000..5b3450f09 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/ErrorHandler.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.addons.terrascript; + +import java.util.ArrayList; +import java.util.List; + + +public class ErrorHandler { + + private final List exceptions = new ArrayList<>(); + + public void add(Exception e) { + exceptions.add(e); + } + + public void throwAny() throws Exception { + for(Exception e : exceptions) { + throw e; + } + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java index f2e1d0055..1435916e7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/TerraScriptAddon.java @@ -8,9 +8,9 @@ package com.dfsek.terra.addons.terrascript; import com.dfsek.terra.addons.manifest.api.AddonInitializer; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.StructureScript; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.StructureScript; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; @@ -31,6 +31,7 @@ public class TerraScriptAddon implements AddonInitializer { @Override public void initialize() { + platform.getEventManager() .getHandler(FunctionalEventHandler.class) .register(addon, ConfigPackPreLoadEvent.class) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Type.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Type.java new file mode 100644 index 000000000..dbcfff372 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/Type.java @@ -0,0 +1,9 @@ +package com.dfsek.terra.addons.terrascript; + +// TODO - Make not enum +public enum Type { + NUMBER, + STRING, + BOOLEAN, + VOID, +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/CompilationException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/CompilationException.java new file mode 100644 index 000000000..99b98b7e3 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/CompilationException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.exception; + +import java.io.Serial; + +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class CompilationException extends Exception { + @Serial + private static final long serialVersionUID = 6744390543046766386L; + private final SourcePosition position; + + public CompilationException(String message, SourcePosition position) { + super(message); + this.position = position; + } + + @Override + public String getMessage() { + return "Error at " + position + ": " + super.getMessage(); + } + + public SourcePosition getPosition() { + return position; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/EOFException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/EOFException.java similarity index 91% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/EOFException.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/EOFException.java index b10214b1c..d219a8286 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/EOFException.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/EOFException.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.lexer.exceptions; +package com.dfsek.terra.addons.terrascript.exception.lexer; import java.io.Serial; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/FormatException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/FormatException.java similarity index 92% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/FormatException.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/FormatException.java index 39dcae08f..0f02a35c7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/FormatException.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/FormatException.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.lexer.exceptions; +package com.dfsek.terra.addons.terrascript.exception.lexer; import java.io.Serial; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/TokenizerException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/TokenizerException.java similarity index 83% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/TokenizerException.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/TokenizerException.java index 200aa9a00..5f2e6a2da 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/exceptions/TokenizerException.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/lexer/TokenizerException.java @@ -5,12 +5,12 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.lexer.exceptions; +package com.dfsek.terra.addons.terrascript.exception.lexer; import java.io.Serial; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; public abstract class TokenizerException extends ParseException { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/IdentifierAlreadyDeclaredException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/IdentifierAlreadyDeclaredException.java new file mode 100644 index 000000000..983974559 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/IdentifierAlreadyDeclaredException.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.addons.terrascript.exception.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.exception.CompilationException; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class IdentifierAlreadyDeclaredException extends CompilationException { + public IdentifierAlreadyDeclaredException(String message, SourcePosition position) { + super(message, position); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidFunctionDeclarationException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidFunctionDeclarationException.java new file mode 100644 index 000000000..c2a908dd2 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidFunctionDeclarationException.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.addons.terrascript.exception.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.exception.CompilationException; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class InvalidFunctionDeclarationException extends CompilationException { + public InvalidFunctionDeclarationException(String message, SourcePosition position) { + super(message, position); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidTypeException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidTypeException.java new file mode 100644 index 000000000..379c2de15 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/InvalidTypeException.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.addons.terrascript.exception.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.exception.CompilationException; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class InvalidTypeException extends CompilationException { + public InvalidTypeException(String message, SourcePosition position) { + super(message, position); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/UndefinedReferenceException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/UndefinedReferenceException.java new file mode 100644 index 000000000..8df64df04 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/exception/semanticanalysis/UndefinedReferenceException.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.addons.terrascript.exception.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.exception.CompilationException; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class UndefinedReferenceException extends CompilationException { + public UndefinedReferenceException(String message, SourcePosition position) { + super(message, position); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/Parser.java new file mode 100644 index 000000000..c39e32acc --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/Parser.java @@ -0,0 +1,585 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.legacy.parser; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Function; + +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Executable; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.NumericConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.UserDefinedFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow.BreakKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow.ContinueKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow.FailKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow.ReturnKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike.ForKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike.IfKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike.WhileKeyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BooleanAndOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BooleanNotOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BooleanOrOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.ConcatenationOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.DivisionOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.ModuloOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.MultiplicationOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.NegationOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.NumberAdditionOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.SubtractionOperation; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.EqualsStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.GreaterOrEqualsThanStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.GreaterThanStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.LessThanOrEqualsStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.LessThanStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements.NotEqualsStatement; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign.BoolAssignmentNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign.NumAssignmentNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign.StrAssignmentNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign.VariableAssignmentNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference.BoolVariableReferenceNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference.NumVariableReferenceNode; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference.StrVariableReferenceNode; +import com.dfsek.terra.addons.terrascript.lexer.Lexer; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; +import com.dfsek.terra.addons.terrascript.lexer.Token; +import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class Parser { + private final List ignoredFunctions = new ArrayList<>(); + + private final Lexer lexer; + + public Parser(Lexer lexer) { + this.lexer = lexer; + } + + /** + * Parse input + * + * @return executable {@link Block} + * + * @throws ParseException If parsing fails. + */ + public Executable parse(Scope.ScopeBuilder scopeBuilder) { + return new Executable(parseBlock(scopeBuilder, Type.VOID), scopeBuilder); + } + + private WhileKeyword parseWhileLoop(Scope.ScopeBuilder scopeBuilder) { + SourcePosition start = lexer.consume("Expected 'while' keyword at beginning of while loop", TokenType.WHILE_LOOP).position(); + lexer.consume("Expected '(' proceeding 'while' keyword", TokenType.OPEN_PAREN); + scopeBuilder = scopeBuilder.innerLoopScope(); + Expression condition = parseExpression(scopeBuilder); + ParserUtil.ensureReturnType(condition, Type.BOOLEAN); + lexer.consume("Expected ')' proceeding while loop condition", TokenType.CLOSE_PAREN); + return new WhileKeyword(parseStatementBlock(scopeBuilder, Type.VOID), (Expression) condition, + start); // While loop + } + + private IfKeyword parseIfStatement(Scope.ScopeBuilder scopeBuilder) { + SourcePosition start = lexer.consume("Expected 'if' keyword at beginning of if statement", TokenType.IF_STATEMENT).position(); + lexer.consume("Expected '(' proceeding 'if' keyword", TokenType.OPEN_PAREN); + Expression condition = parseExpression(scopeBuilder); + ParserUtil.ensureReturnType(condition, Type.BOOLEAN); + + lexer.consume("Expected ')' proceeding if statement condition", TokenType.CLOSE_PAREN); + + Block elseBlock = null; + Block statement = parseStatementBlock(scopeBuilder, Type.VOID); + + List, Block>> elseIf = new ArrayList<>(); + + while(lexer.hasNext() && lexer.current().isType(TokenType.ELSE)) { + lexer.consumeUnchecked(); // Consume else. + if(lexer.current().isType(TokenType.IF_STATEMENT)) { + lexer.consumeUnchecked(); // Consume if. + Expression elseCondition = parseExpression(scopeBuilder); + ParserUtil.ensureReturnType(elseCondition, Type.BOOLEAN); + elseIf.add(Pair.of((Expression) elseCondition, parseStatementBlock(scopeBuilder, Type.VOID))); + } else { + elseBlock = parseStatementBlock(scopeBuilder, Type.VOID); + break; // Else must be last. + } + } + + return new IfKeyword(statement, (Expression) condition, elseIf, elseBlock, start); // If statement + } + + private Block parseStatementBlock(Scope.ScopeBuilder scopeBuilder, Type blockReturnType) { + if(lexer.current().isType(TokenType.BLOCK_BEGIN)) { + lexer.consumeUnchecked(); + Block block = parseBlock(scopeBuilder, blockReturnType); + lexer.consume("Expected block end '}' after block statements", TokenType.BLOCK_END); + return block; + } else { + SourcePosition position = lexer.current().position(); + return new Block(Collections.singletonList(parseStatement(scopeBuilder)), position, blockReturnType); + } + } + + private ForKeyword parseForLoop(Scope.ScopeBuilder scopeBuilder) { + SourcePosition start = lexer.consume("Expected 'for' keyword at beginning of for loop", TokenType.FOR_LOOP).position(); + lexer.consume("Expected '(' after 'for' keyword", TokenType.OPEN_PAREN); + scopeBuilder = scopeBuilder.innerLoopScope(); // new scope + + Expression initializer = switch(lexer.current().type()) { + case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN -> { + Token type = lexer.consume("Expected type before declaration", TokenType.TYPE_STRING, TokenType.TYPE_NUMBER, + TokenType.TYPE_BOOLEAN, TokenType.TYPE_VOID); + Token identifier = lexer.consume("Expected identifier after type", TokenType.IDENTIFIER); + Expression expr = parseVariableDeclaration(scopeBuilder, type, identifier); + lexer.consume("Expected ';' after initializer within for loop", TokenType.STATEMENT_END); + yield expr; + } + case IDENTIFIER -> { + Expression expr = parseAssignment(scopeBuilder); + lexer.consume("Expected ';' after initializer within for loop", TokenType.STATEMENT_END); + yield expr; + } + case STATEMENT_END -> { + lexer.consumeUnchecked(); + yield Expression.NOOP; + } + default -> throw new ParseException("Unexpected token '" + lexer.current() + "', expected variable declaration or assignment", + lexer.current().position()); + }; + + Expression conditional; + if(lexer.current().isType(TokenType.STATEMENT_END)) // If no conditional is provided, conditional defaults to true + conditional = new BooleanConstant(true, lexer.current().position()); + else + conditional = parseExpression(scopeBuilder); + ParserUtil.ensureReturnType(conditional, Type.BOOLEAN); + lexer.consume("Expected ';' separator after conditional within for loop", TokenType.STATEMENT_END); + + Expression incrementer; + if(lexer.current().isType(TokenType.CLOSE_PAREN)) + // If no incrementer is provided, do nothing + incrementer = Expression.NOOP; + else if(scopeBuilder.containsVariable(lexer.current().lexeme())) // Assume variable assignment + incrementer = parseAssignment(scopeBuilder); + else + incrementer = parseFunctionInvocation( + lexer.consume("Expected function call within for loop incrementer, found '" + lexer.current().lexeme() + "' instead", + TokenType.IDENTIFIER), scopeBuilder); + lexer.consume("Expected ')' after for loop incrementer", TokenType.CLOSE_PAREN); + + return new ForKeyword(parseStatementBlock(scopeBuilder, Type.VOID), initializer, (Expression) conditional, + incrementer, + start); + } + + private Expression parseExpression(Scope.ScopeBuilder scopeBuilder) { + return parseLogicOr(scopeBuilder); + } + + private Expression parseLogicOr(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseLogicAnd, scopeBuilder, (op) -> { + ParserUtil.ensureReturnType(op.left, Type.BOOLEAN); + ParserUtil.ensureReturnType(op.right, Type.BOOLEAN); + }, Map.of(TokenType.BOOLEAN_OR, + (op) -> new BooleanOrOperation((Expression) op.left, (Expression) op.right, op.operator.position()))); + } + + private Expression parseLogicAnd(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseEquality, scopeBuilder, (op) -> { + ParserUtil.ensureReturnType(op.left, Type.BOOLEAN); + ParserUtil.ensureReturnType(op.right, Type.BOOLEAN); + }, Map.of(TokenType.BOOLEAN_AND, + (op) -> new BooleanAndOperation((Expression) op.left, (Expression) op.right, op.operator.position()))); + } + + private Expression parseEquality(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseComparison, scopeBuilder, Map.of( + TokenType.EQUALS_EQUALS, + (op) -> new EqualsStatement((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.BANG_EQUALS, + (op) -> new NotEqualsStatement((Expression) op.left, (Expression) op.right, op.operator.position()) + )); + } + + private Expression parseComparison(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseTerm, scopeBuilder, (op) -> { + ParserUtil.ensureReturnType(op.left, Type.NUMBER); + ParserUtil.ensureReturnType(op.right, Type.NUMBER); + }, Map.of( + TokenType.LESS, + (op) -> new LessThanStatement((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.LESS_EQUALS, + (op) -> new LessThanOrEqualsStatement((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.GREATER, + (op) -> new GreaterThanStatement((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.GREATER_EQUAL, + (op) -> new GreaterOrEqualsThanStatement((Expression) op.left, (Expression) op.right, + op.operator.position()) + )); + } + + private Expression parseTerm(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseFactor, scopeBuilder, Map.of( + TokenType.MINUS, (op) -> { + ParserUtil.ensureReturnType(op.left, Type.NUMBER); + ParserUtil.ensureReturnType(op.right, Type.NUMBER); + return new SubtractionOperation((Expression) op.left, (Expression) op.right, op.operator.position()); + }, + TokenType.PLUS, (op) -> { + if(op.left.returnType() == Type.NUMBER && op.right.returnType() == Type.NUMBER) + return new NumberAdditionOperation((Expression) op.left, (Expression) op.right, + op.operator.position()); + else + return new ConcatenationOperation((Expression) op.left, (Expression) op.right, + op.operator.position()); + })); + } + + private Expression parseFactor(Scope.ScopeBuilder scopeBuilder) { + return parseLeftAssociativeBinaryOperation(this::parseUnary, scopeBuilder, (op) -> { + ParserUtil.ensureReturnType(op.left, Type.NUMBER); + ParserUtil.ensureReturnType(op.right, Type.NUMBER); + }, Map.of( + TokenType.STAR, + (op) -> new MultiplicationOperation((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.FORWARD_SLASH, + (op) -> new DivisionOperation((Expression) op.left, (Expression) op.right, op.operator.position()), + TokenType.MODULO_OPERATOR, + (op) -> new ModuloOperation((Expression) op.left, (Expression) op.right, op.operator.position()) + )); + } + + private Expression parseUnary(Scope.ScopeBuilder scopeBuilder) { + if(lexer.current().isType(TokenType.BANG, TokenType.MINUS)) { + Token operator = lexer.consumeUnchecked(); + Expression right = parseUnary(scopeBuilder); + return switch(operator.type()) { + case BANG -> { + ParserUtil.ensureReturnType(right, Type.BOOLEAN); + yield new BooleanNotOperation((Expression) right, operator.position()); + } + case MINUS -> { + ParserUtil.ensureReturnType(right, Type.NUMBER); + yield new NegationOperation((Expression) right, operator.position()); + } + default -> throw new IllegalStateException(); + }; + } + return parsePrimary(scopeBuilder); + } + + private Expression parsePrimary(Scope.ScopeBuilder scopeBuilder) { + Token token = lexer.consumeUnchecked(); + return switch(token.type()) { + case NUMBER -> { + String content = token.lexeme(); + yield new NumericConstant(content.contains(".") ? Double.parseDouble(content) : Integer.parseInt(content), + token.position()); + } + case STRING -> new StringConstant(token.lexeme(), token.position()); + case BOOLEAN -> new BooleanConstant(Boolean.parseBoolean(token.lexeme()), token.position()); + case OPEN_PAREN -> { + Expression expr = parseExpression(scopeBuilder); + lexer.consume("Missing ')' at end of expression group", TokenType.CLOSE_PAREN); + yield expr; + } + case IDENTIFIER -> { + if(scopeBuilder.containsFunction(token.lexeme())) + yield parseFunctionInvocation(token, scopeBuilder); + else if(scopeBuilder.containsVariable(token.lexeme())) { + Type variableType = scopeBuilder.getVaraibleType(token.lexeme()); + yield switch(variableType) { + case NUMBER -> new NumVariableReferenceNode(token.position(), variableType, scopeBuilder.getIndex(token.lexeme())); + case BOOLEAN -> new BoolVariableReferenceNode(token.position(), variableType, + scopeBuilder.getIndex(token.lexeme())); + case STRING -> new StrVariableReferenceNode(token.position(), variableType, scopeBuilder.getIndex(token.lexeme())); + default -> throw new ParseException("Illegal type for variable reference: " + variableType, token.position()); + }; + } + throw new ParseException("Identifier '" + token.lexeme() + "' is not defined in this scope", token.position()); + } + default -> throw new ParseException("Unexpected token '" + token.lexeme() + "' when parsing expression", token.position()); + }; + } + + /** + * Parses expressions of higher precedence, then sequentially parses any binary operators of the same + * precedence from left to right. Operands for each operation are parsed with the higher precedence rule first. + *

+ * E.g. for expression

'a * b + c - d * e + f'
where - and + are at same precedence, and * at a higher precedence: + *
+     * 1. Start parsing higher precedence:
+     *    a ...
+     *
+     * 2. Higher precedence stops because +:
+     *    (a * b) + ...
+     *
+     * 3. Parse right of + at higher precedence until current precedence operator or end:
+     *    (a * b) + (c) - ...
+     *
+     * 4. Group as one expression:
+     *    ((a * b) + (c)) - ...
+     *
+     * 5. Repeat 3-4 until end of expression:
+     *    ((((a * b) + (c)) - (d * e)) + (f))
+     * 
+ * + * @param higherPrecedence Parsing rule for expression of higher precedence + * @param scopeBuilder + * @param init Initial code to run for any matching operands + operator + * @param operators List of binary operators of this precedence mapped to how to parse them + * + * @return + */ + private Expression parseLeftAssociativeBinaryOperation(Function> higherPrecedence, + Scope.ScopeBuilder scopeBuilder, + Consumer init, + Map>> operators) { + Expression expr = higherPrecedence.apply(scopeBuilder); + TokenType[] opTypes = operators.keySet().toArray(new TokenType[0]); + while(lexer.current().isType(opTypes)) { // Parse binary operator if a matching token of this precedence + Token operator = lexer.consumeUnchecked(); + Expression right = higherPrecedence.apply(scopeBuilder); + BinaryOperationInfo op = new BinaryOperationInfo(expr, operator, right); + init.accept(op); + expr = operators.get(operator.type()).apply(op); + } + return expr; + } + + private Expression parseLeftAssociativeBinaryOperation(Function> higherPrecedence, + Scope.ScopeBuilder scopeBuilder, + Map>> operators) { + return parseLeftAssociativeBinaryOperation(higherPrecedence, scopeBuilder, (op) -> { }, operators); + } + + private record BinaryOperationInfo(Expression left, Token operator, Expression right) { + } + + private Expression parseDeclaration(Scope.ScopeBuilder scopeBuilder) { + Token type = lexer.consume("Expected type before declaration", TokenType.TYPE_STRING, TokenType.TYPE_NUMBER, TokenType.TYPE_BOOLEAN, + TokenType.TYPE_VOID); + Token identifier = lexer.consume("Expected identifier after type", TokenType.IDENTIFIER); + + return switch(lexer.current().type()) { + case ASSIGNMENT -> parseVariableDeclaration(scopeBuilder, type, identifier); + case OPEN_PAREN -> parseFunctionDeclaration(scopeBuilder, type, identifier); + default -> throw new ParseException( + "Expected '=' for variable assignment or '(' for function declaration after identifier '" + identifier.lexeme() + "'", + lexer.current().position()); + }; + } + + + private Expression parseVariableDeclaration(Scope.ScopeBuilder scopeBuilder, Token type, Token identifier) { + lexer.consume("Expected '=' after identifier '" + identifier.lexeme() + "' for variable declaration", TokenType.ASSIGNMENT); + + if(!type.isVariableDeclaration()) throw new ParseException("Expected type specification at beginning of variable declaration", + type.position()); + + if(scopeBuilder.containsVariable(identifier.lexeme())) + throw new ParseException(identifier.lexeme() + " is already defined in this scope", identifier.position()); + + Expression value = parseExpression(scopeBuilder); + ParserUtil.ensureReturnType(value, ParserUtil.getVariableReturnType(type)); + + String variableName = identifier.lexeme(); + return switch(value.returnType()) { + case NUMBER -> new NumAssignmentNode((Expression) value, identifier.position(), + scopeBuilder.declareNum(variableName)); + case STRING -> new StrAssignmentNode((Expression) value, identifier.position(), + scopeBuilder.declareStr(variableName)); + case BOOLEAN -> new BoolAssignmentNode((Expression) value, identifier.position(), + scopeBuilder.declareBool(variableName)); + default -> throw new ParseException("Illegal type for variable declaration: " + type, value.getPosition()); + }; + } + + private Expression parseFunctionDeclaration(Scope.ScopeBuilder scopeBuilder, Token type, Token identifier) { + lexer.consume("Expected '(' after identifier '" + identifier.lexeme() + "' for function declaration", TokenType.OPEN_PAREN); + + if(!(type.isType(TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER, TokenType.TYPE_VOID))) + throw new ParseException("Invalid function declaration return type specification " + type.type(), type.position()); + + if(scopeBuilder.containsVariable(identifier.lexeme())) + throw new ParseException(identifier.lexeme() + " is already defined in this scope", identifier.position()); + + Type returnType = ParserUtil.getVariableReturnType(type); + + Scope.ScopeBuilder functionBodyScope = scopeBuilder.functionScope(); + + // Declare parameter names into function body scope + List> parameterInfo = getFunctionParameterDeclaration().stream().map( + arg -> Pair.of(switch(arg.getRight()) { + case NUMBER -> functionBodyScope.declareNum(arg.getLeft()); + case BOOLEAN -> functionBodyScope.declareBool(arg.getLeft()); + case STRING -> functionBodyScope.declareStr(arg.getLeft()); + default -> throw new IllegalArgumentException("Unsupported parameter type: " + arg.getRight()); + }, arg.getRight())).toList(); + + Block body = parseStatementBlock(functionBodyScope, returnType); + + FunctionBuilder functionBuilder = new UserDefinedFunctionBuilder<>(returnType, parameterInfo, body, functionBodyScope); + + scopeBuilder.registerFunction(identifier.lexeme(), functionBuilder); + return Expression.NOOP; + } + + private List> getFunctionParameterDeclaration() { + List> parameters = new ArrayList<>(); + while(lexer.current().type() != TokenType.CLOSE_PAREN) { + // Parse parameter type + Token typeToken = lexer.consume("Expected function parameter type declaration", TokenType.TYPE_BOOLEAN, TokenType.TYPE_STRING, + TokenType.TYPE_NUMBER); + Type type = ParserUtil.getVariableReturnType(typeToken); + + // Parse parameter name + Token identifierToken = lexer.consume("Expected function parameter identifier", TokenType.IDENTIFIER); + String name = identifierToken.lexeme(); + + parameters.add(Pair.of(name, type)); + + // Consume separator if present, trailing separators are allowed + if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consumeUnchecked(); + } + lexer.consume("Expected ')' after function parameter declaration", TokenType.CLOSE_PAREN); + return parameters; + } + + private Block parseBlock(Scope.ScopeBuilder scopeBuilder, Type blockReturnType) { + List> expressions = new ArrayList<>(); + scopeBuilder = scopeBuilder.innerScope(); // Create new inner scope for the block + SourcePosition startPosition = lexer.current().position(); + + boolean hasReturn = false; + + // Parse each statement + while(lexer.hasNext() && !lexer.current().isType(TokenType.BLOCK_END)) { + Expression expression = parseStatement(scopeBuilder); + if(expression != Expression.NOOP) { + expressions.add(expression); + } + if(expression instanceof ReturnKeyword returnKeyword) { + hasReturn = true; + if(returnKeyword.dataReturnType() != blockReturnType) + throw new ParseException( + "Invalid return type, expected " + blockReturnType + ", found " + returnKeyword.dataReturnType(), + expression.getPosition()); + } + } + + if(blockReturnType != Type.VOID && !hasReturn) + throw new ParseException("Block does not contain a return statement, must return type " + blockReturnType, startPosition); + + return new Block(expressions, startPosition, blockReturnType); + } + + private Expression parseStatement(Scope.ScopeBuilder scopeBuilder) { + Token token = lexer.current(); + Expression expression = switch(token.type()) { + case FOR_LOOP -> parseForLoop(scopeBuilder); + case IF_STATEMENT -> parseIfStatement(scopeBuilder); + case WHILE_LOOP -> parseWhileLoop(scopeBuilder); + case IDENTIFIER -> { + if(scopeBuilder.containsVariable(token.lexeme())) yield parseAssignment(scopeBuilder); // Assume variable assignment + else yield parseFunctionInvocation(lexer.consumeUnchecked(), scopeBuilder); + } + case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_VOID -> parseDeclaration(scopeBuilder); + case RETURN -> parseReturn(scopeBuilder); + case BREAK -> { + if(!scopeBuilder.isInLoop()) throw new ParseException("Break statements can only be defined inside loops", + token.position()); + yield new BreakKeyword(lexer.consumeUnchecked().position()); + } + case CONTINUE -> { + if(!scopeBuilder.isInLoop()) throw new ParseException("Continue statements can only be defined inside loops", + token.position()); + yield new ContinueKeyword(lexer.consumeUnchecked().position()); + } + case FAIL -> new FailKeyword(lexer.consumeUnchecked().position()); + case STATEMENT_END -> Expression.NOOP; + default -> throw new ParseException("Unexpected token '" + token.lexeme() + "' while parsing statement", token.position()); + }; + if(!token.isControlStructure() && expression != Expression.NOOP) lexer.consume("Expected ';' at end of statement", + TokenType.STATEMENT_END); + return expression; + } + + private ReturnKeyword parseReturn(Scope.ScopeBuilder scopeBuilder) { + Token returnToken = lexer.consume("Expected 'return' keyword at beginning of return statement", TokenType.RETURN); + Expression data = null; + if(!lexer.current().isType(TokenType.STATEMENT_END)) { + data = parseExpression(scopeBuilder); + } + return new ReturnKeyword(data, returnToken.position()); + } + + private VariableAssignmentNode parseAssignment(Scope.ScopeBuilder scopeBuilder) { + Token identifier = lexer.consume("Expected identifier at beginning of assignment", TokenType.IDENTIFIER); + + lexer.consume("Expected '=' after identifier for variable assignment", TokenType.ASSIGNMENT); + + Expression value = parseExpression(scopeBuilder); + + String id = identifier.lexeme(); + + ParserUtil.ensureReturnType(value, scopeBuilder.getVaraibleType(id)); + + Type type = value.returnType(); + + return switch(type) { + case NUMBER -> new NumAssignmentNode((Expression) value, identifier.position(), scopeBuilder.getIndex(id)); + case STRING -> new StrAssignmentNode((Expression) value, identifier.position(), scopeBuilder.getIndex(id)); + case BOOLEAN -> new BoolAssignmentNode((Expression) value, identifier.position(), scopeBuilder.getIndex(id)); + default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition()); + }; + } + + private Expression parseFunctionInvocation(Token identifier, Scope.ScopeBuilder scopeBuilder) { + if(!scopeBuilder.containsFunction(identifier.lexeme())) + throw new ParseException("Function '" + identifier.lexeme() + "' is not defined in this scope", identifier.position()); + + FunctionBuilder builder = scopeBuilder.getFunction(identifier.lexeme()); + + lexer.consume("Expected '(' after identifier " + identifier.lexeme(), TokenType.OPEN_PAREN); // Invocation starts with open paren + + List> args = new ArrayList<>(); + while(!lexer.current().isType(TokenType.CLOSE_PAREN)) { + args.add(parseExpression(scopeBuilder)); + if(lexer.current().isType(TokenType.CLOSE_PAREN)) break; + lexer.consume("Expected ',' between function parameters", TokenType.SEPARATOR); + } + lexer.consume("Expected ')' after function parameters", TokenType.CLOSE_PAREN); + + if(ignoredFunctions.contains(identifier.lexeme())) { + return Expression.NOOP; + } + + if(builder.argNumber() != -1 && args.size() != builder.argNumber()) + throw new ParseException("Expected " + builder.argNumber() + " parameters, found " + args.size(), identifier.position()); + + for(int i = 0; i < args.size(); i++) { + Expression argument = args.get(i); + if(builder.getArgument(i) == null) + throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.lexeme(), + identifier.position()); + ParserUtil.ensureReturnType(argument, builder.getArgument(i)); + } + return builder.build(args, identifier.position()); + } + +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/ParserUtil.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/ParserUtil.java new file mode 100644 index 000000000..2a34507fa --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/ParserUtil.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020-2021 Polyhedral Development + * + * The Terra Core Addons are licensed under the terms of the MIT License. For more details, + * reference the LICENSE file in this module's root directory. + */ + +package com.dfsek.terra.addons.terrascript.legacy.parser; + +import java.util.Arrays; + +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.lexer.Token; + + +public class ParserUtil { + + // public static void ensureType(Token token, TokenType... expected) { + // for(TokenType type : expected) if(token.getType().equals(type)) return; + // throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition()); + // } + + public static void ensureReturnType(Expression returnable, Type... types) { + for(Type type : types) if(returnable.returnType().equals(type)) return; + throw new ParseException("Invalid type " + returnable.returnType() + ", expected " + + (types.length == 1 ? types[0].toString() : "one of " + Arrays.toString(types)), returnable.getPosition()); + } + + public static Type getVariableReturnType(Token varToken) { + return switch(varToken.type()) { + case TYPE_NUMBER -> Type.NUMBER; + case TYPE_STRING -> Type.STRING; + case TYPE_BOOLEAN -> Type.BOOLEAN; + case TYPE_VOID -> Type.VOID; + default -> throw new ParseException("Unexpected token " + varToken.type() + "; expected type", + varToken.position()); + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/exceptions/ParseException.java similarity index 93% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/exceptions/ParseException.java index 3a0956a1e..34286c9e9 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/exceptions/ParseException.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/exceptions/ParseException.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.exceptions; +package com.dfsek.terra.addons.terrascript.legacy.parser.exceptions; import java.io.Serial; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Block.java similarity index 82% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Block.java index f174d4ede..c1745d08f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Block.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Block.java @@ -5,27 +5,28 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; public class Block implements Expression> { private final List> items; private final SourcePosition position; - private final ReturnType returnType; + private final Type returnType; - public Block(List> items, SourcePosition position, ReturnType returnType) { + public Block(List> items, SourcePosition position, Type returnType) { this.items = items; this.position = position; this.returnType = returnType; } @Override - public ReturnType returnType() { + public Type returnType() { return returnType; } @@ -37,7 +38,7 @@ public class Block implements Expression> { if(!evalInfo.level().equals(EvaluationLevel.NONE)) return evalInfo; } } - return new EvaluationInfo<>(EvaluationLevel.NONE, Expression.NOOP); + return new EvaluationInfo<>(EvaluationLevel.NONE, NOOP); } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Executable.java similarity index 66% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Executable.java index 154e5747b..f2695bd8d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Executable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Executable.java @@ -1,14 +1,11 @@ -package com.dfsek.terra.addons.terrascript.parser.lang; - - -import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; public class Executable { private final Block script; private final ThreadLocal scope; - public Executable(Block script, ScopeBuilder scopeBuilder) { + public Executable(Block script, Scope.ScopeBuilder scopeBuilder) { this.script = script; this.scope = ThreadLocal.withInitial(scopeBuilder::build); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Expression.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Expression.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Expression.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Expression.java index c4d7dc239..a215bc77c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Expression.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Expression.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; public interface Expression { Expression NOOP = new Expression<>() { @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } @Override @@ -28,7 +29,7 @@ public interface Expression { } }; - ReturnType returnType(); + Type returnType(); T evaluate(ImplementationArguments implementationArguments, Scope scope); @@ -43,21 +44,4 @@ public interface Expression { SourcePosition getPosition(); - 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; - } - } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/ImplementationArguments.java similarity index 84% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/ImplementationArguments.java index bf6b6cda7..ef6277e12 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/ImplementationArguments.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/ImplementationArguments.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; /** * Arguments passed to {@link Expression}s by the implementation diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Keyword.java similarity index 81% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Keyword.java index 87306e1f0..56d313c6a 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Keyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Keyword.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; public interface Keyword extends Expression { } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Scope.java similarity index 88% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Scope.java index 045d11fcf..6f516f8d9 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/Scope.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/Scope.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.addons.terrascript.parser.lang; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang; import net.jafama.FastMath; @@ -6,9 +6,9 @@ import net.jafama.FastMath; import java.util.HashMap; import java.util.Map; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.util.generic.pair.Pair; @@ -50,7 +50,7 @@ public class Scope { public static final class ScopeBuilder { private final Map>> functions; - private final Map> indices; + private final Map> indices; private int numSize, boolSize, strSize = 0; private ScopeBuilder parent; @@ -114,7 +114,7 @@ public class Scope { public int declareNum(String id) { int num = numSize; - indices.put(check(id), Pair.of(num, ReturnType.NUMBER)); + indices.put(check(id), Pair.of(num, Type.NUMBER)); numSize++; updateNumSize(numSize); return num; @@ -122,7 +122,7 @@ public class Scope { public int declareStr(String id) { int str = strSize; - indices.put(check(id), Pair.of(str, ReturnType.STRING)); + indices.put(check(id), Pair.of(str, Type.STRING)); strSize++; updateStrSize(strSize); return str; @@ -130,7 +130,7 @@ public class Scope { public int declareBool(String id) { int bool = boolSize; - indices.put(check(id), Pair.of(bool, ReturnType.BOOLEAN)); + indices.put(check(id), Pair.of(bool, Type.BOOLEAN)); boolSize++; updateBoolSize(boolSize); return bool; @@ -161,7 +161,7 @@ public class Scope { return indices.get(id).getLeft(); } - public ReturnType getVaraibleType(String id) { + public Type getVaraibleType(String id) { return indices.get(id).getRight(); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/BooleanConstant.java similarity index 67% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/BooleanConstant.java index 98fc49823..5b32c3c8d 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/BooleanConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/BooleanConstant.java @@ -5,11 +5,12 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.constants; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BooleanConstant extends ConstantExpression { @@ -26,7 +27,7 @@ public class BooleanConstant extends ConstantExpression { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/ConstantExpression.java similarity index 74% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/ConstantExpression.java index 70877d551..fcfd0d6f5 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/ConstantExpression.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/ConstantExpression.java @@ -5,12 +5,12 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.constants; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public abstract class ConstantExpression implements Expression { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/NumericConstant.java similarity index 66% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/NumericConstant.java index 4713dd323..8df0d9b37 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/NumericConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/NumericConstant.java @@ -5,12 +5,12 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.constants; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class NumericConstant extends ConstantExpression { @@ -27,7 +27,7 @@ public class NumericConstant extends ConstantExpression { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/StringConstant.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/StringConstant.java index 89edc0b27..269dc97f1 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/constants/StringConstant.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/constants/StringConstant.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.constants; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public class StringConstant extends ConstantExpression { @@ -17,7 +17,7 @@ public class StringConstant extends ConstantExpression { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.STRING; + public Type returnType() { + return Type.STRING; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/Function.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/Function.java index f1970ff1a..a816ef3d7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/Function.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/Function.java @@ -5,11 +5,11 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.functions; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; public interface Function extends Expression { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/FunctionBuilder.java similarity index 60% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/FunctionBuilder.java index 9460601fa..5ea54c646 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/FunctionBuilder.java @@ -5,21 +5,22 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.functions; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public interface FunctionBuilder> { T build(List> argumentList, SourcePosition position); /** - * @return Number of function arguments, -1 if the function uses a vararg at the end + * @return Number of function parameters, -1 if the function uses a vararg at the end */ int argNumber(); - Expression.ReturnType getArgument(int position); + Type getArgument(int position); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/UserDefinedFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/UserDefinedFunctionBuilder.java similarity index 63% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/UserDefinedFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/UserDefinedFunctionBuilder.java index eb38f3f1e..25f939bdc 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/UserDefinedFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/functions/UserDefinedFunctionBuilder.java @@ -1,26 +1,25 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.functions; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; import com.dfsek.terra.api.util.generic.pair.Pair; public class UserDefinedFunctionBuilder> implements FunctionBuilder { - private final ReturnType returnType; - private final List> parameterInfo; - private final ScopeBuilder bodyScopeBuilder; + private final Type returnType; + private final List> parameterInfo; + private final Scope.ScopeBuilder bodyScopeBuilder; private final Block body; - public UserDefinedFunctionBuilder(ReturnType returnType, List> parameterInfo, Block body, - ScopeBuilder functionBodyScope) { + public UserDefinedFunctionBuilder(Type returnType, List> parameterInfo, Block body, + Scope.ScopeBuilder functionBodyScope) { this.returnType = returnType; this.bodyScopeBuilder = functionBodyScope; this.body = body; @@ -35,21 +34,22 @@ public class UserDefinedFunctionBuilder> implements Functi private final ThreadLocal threadLocalScope = ThreadLocal.withInitial(bodyScopeBuilder::build); @Override - public ReturnType returnType() { + public Type returnType() { return returnType; } @Override public Object evaluate(ImplementationArguments implementationArguments, Scope scope) { Scope bodyScope = threadLocalScope.get(); - // Pass arguments into scope of function body + // Pass parameters into scope of function body for(int i = 0; i < argumentList.size(); i++) { - Pair paramInfo = parameterInfo.get(i); + Pair paramInfo = parameterInfo.get(i); Expression argExpression = argumentList.get(i); switch(paramInfo.getRight()) { case NUMBER -> bodyScope.setNum(paramInfo.getLeft(), argExpression.applyDouble(implementationArguments, scope)); case BOOLEAN -> bodyScope.setBool(paramInfo.getLeft(), argExpression.applyBoolean(implementationArguments, scope)); - case STRING -> bodyScope.setStr(paramInfo.getLeft(), (String) argExpression.evaluate(implementationArguments, scope)); + case STRING -> bodyScope.setStr(paramInfo.getLeft(), + (String) argExpression.evaluate(implementationArguments, scope)); } } return body.evaluate(implementationArguments, bodyScope).data().evaluate(implementationArguments, scope); @@ -68,7 +68,7 @@ public class UserDefinedFunctionBuilder> implements Functi } @Override - public ReturnType getArgument(int position) { + public Type getArgument(int position) { return parameterInfo.get(position).getRight(); } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/BreakKeyword.java similarity index 58% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/BreakKeyword.java index be1d66c7b..4703a635c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/BreakKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/BreakKeyword.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BreakKeyword implements Keyword> { @@ -33,7 +34,7 @@ public class BreakKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ContinueKeyword.java similarity index 58% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ContinueKeyword.java index fe35c95e5..ffb786cbe 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ContinueKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ContinueKeyword.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class ContinueKeyword implements Keyword> { @@ -33,7 +34,7 @@ public class ContinueKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/FailKeyword.java similarity index 58% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/FailKeyword.java index e50c9de18..5634f7a5f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/FailKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/FailKeyword.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class FailKeyword implements Keyword> { @@ -33,7 +34,7 @@ public class FailKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ReturnKeyword.java similarity index 59% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ReturnKeyword.java index 1d86bf84f..70455fef6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/flow/ReturnKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/flow/ReturnKeyword.java @@ -5,17 +5,18 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.flow; import javax.annotation.Nullable; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class ReturnKeyword implements Keyword> { @@ -39,15 +40,15 @@ public class ReturnKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } - public ReturnType dataReturnType() { + public Type dataReturnType() { if(data != null) { return data.returnType(); } else { - return ReturnType.VOID; + return Type.VOID; } } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/ForKeyword.java similarity index 72% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/ForKeyword.java index adc83c369..bb3db72db 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/ForKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/ForKeyword.java @@ -5,15 +5,16 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class ForKeyword implements Keyword> { @@ -50,7 +51,7 @@ public class ForKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/IfKeyword.java similarity index 75% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/IfKeyword.java index 8fe1287c6..645cb60a6 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/IfKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/IfKeyword.java @@ -5,19 +5,20 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike; import org.jetbrains.annotations.Nullable; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.api.util.generic.pair.Pair; @@ -57,7 +58,7 @@ public class IfKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/WhileKeyword.java similarity index 64% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/WhileKeyword.java index fbdc3c8a9..bafe6b7ab 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/keywords/looplike/WhileKeyword.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/keywords/looplike/WhileKeyword.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.keywords.looplike; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationInfo; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Block.EvaluationLevel; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Keyword; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationInfo; -import com.dfsek.terra.addons.terrascript.parser.lang.Block.EvaluationLevel; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Keyword; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class WhileKeyword implements Keyword> { @@ -44,7 +45,7 @@ public class WhileKeyword implements Keyword> { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BinaryOperation.java similarity index 83% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BinaryOperation.java index f915029b8..bb866d926 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BinaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BinaryOperation.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public abstract class BinaryOperation implements Expression { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanAndOperation.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanAndOperation.java index a607794f5..bc09e4e33 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanAndOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanAndOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BooleanAndOperation extends BinaryOperation { @@ -19,8 +20,8 @@ public class BooleanAndOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanNotOperation.java similarity index 67% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanNotOperation.java index 15fb390ce..aeb132188 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanNotOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanNotOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BooleanNotOperation extends UnaryOperation { @@ -29,7 +30,7 @@ public class BooleanNotOperation extends UnaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanOrOperation.java similarity index 69% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanOrOperation.java index 5a9fac555..cd28e561f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/BooleanOrOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/BooleanOrOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BooleanOrOperation extends BinaryOperation { @@ -29,7 +30,7 @@ public class BooleanOrOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ConcatenationOperation.java similarity index 73% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ConcatenationOperation.java index 518ef130c..f0376cbb8 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ConcatenationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ConcatenationOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class ConcatenationOperation extends BinaryOperation { @@ -30,8 +31,8 @@ public class ConcatenationOperation extends BinaryOperation { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.STRING; + public Type returnType() { + return Type.STRING; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/DivisionOperation.java similarity index 69% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/DivisionOperation.java index 84bcfb5b7..f082d8571 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/DivisionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/DivisionOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class DivisionOperation extends BinaryOperation { @@ -19,8 +20,8 @@ public class DivisionOperation extends BinaryOperation { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ModuloOperation.java similarity index 69% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ModuloOperation.java index 500fdd256..350aa79e8 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/ModuloOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/ModuloOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class ModuloOperation extends BinaryOperation { @@ -29,7 +30,7 @@ public class ModuloOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/MultiplicationOperation.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/MultiplicationOperation.java index 553926a0a..48d1de55c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/MultiplicationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/MultiplicationOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class MultiplicationOperation extends BinaryOperation { @@ -29,7 +30,7 @@ public class MultiplicationOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NegationOperation.java similarity index 67% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NegationOperation.java index 0ce4443d2..a61b5d1b9 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NegationOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NegationOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class NegationOperation extends UnaryOperation { @@ -19,8 +20,8 @@ public class NegationOperation extends UnaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NumberAdditionOperation.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NumberAdditionOperation.java index 7c8bc5d0c..605731119 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/NumberAdditionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/NumberAdditionOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class NumberAdditionOperation extends BinaryOperation { @@ -29,7 +30,7 @@ public class NumberAdditionOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/SubtractionOperation.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/SubtractionOperation.java index bdd5c5615..44516ac07 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/SubtractionOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/SubtractionOperation.java @@ -5,12 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class SubtractionOperation extends BinaryOperation { @@ -29,7 +30,7 @@ public class SubtractionOperation extends BinaryOperation { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/UnaryOperation.java similarity index 82% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/UnaryOperation.java index f7032382a..d8a7c3864 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/UnaryOperation.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/UnaryOperation.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public abstract class UnaryOperation implements Expression { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/EqualsStatement.java similarity index 71% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/EqualsStatement.java index fe1e9e8ea..954afe30f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/EqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/EqualsStatement.java @@ -5,15 +5,16 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import static com.dfsek.terra.api.util.MathUtil.EPSILON; @@ -26,8 +27,8 @@ public class EqualsStatement extends BinaryOperation { @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java similarity index 65% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java index 2bb2b45c1..fa64d3165 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/GreaterOrEqualsThanStatement.java @@ -5,13 +5,14 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; public class GreaterOrEqualsThanStatement extends BinaryOperation { @@ -20,8 +21,8 @@ public class GreaterOrEqualsThanStatement extends BinaryOperation { @@ -31,7 +32,7 @@ public class GreaterThanStatement extends BinaryOperation { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanOrEqualsStatement.java similarity index 65% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanOrEqualsStatement.java index 0c8d8aa69..256edd558 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanOrEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanOrEqualsStatement.java @@ -5,13 +5,14 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; public class LessThanOrEqualsStatement extends BinaryOperation { @@ -31,7 +32,7 @@ public class LessThanOrEqualsStatement extends BinaryOperation } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanStatement.java similarity index 65% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanStatement.java index cea97f682..c55e6737c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/LessThanStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/LessThanStatement.java @@ -5,13 +5,14 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; public class LessThanStatement extends BinaryOperation { @@ -31,7 +32,7 @@ public class LessThanStatement extends BinaryOperation { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/NotEqualsStatement.java similarity index 71% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/NotEqualsStatement.java index 5d10209fd..dc51f299b 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/operations/statements/NotEqualsStatement.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/operations/statements/NotEqualsStatement.java @@ -5,15 +5,16 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.operations.statements; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.statements; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.operations.BinaryOperation; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BinaryOperation; import static com.dfsek.terra.api.util.MathUtil.EPSILON; @@ -40,7 +41,7 @@ public class NotEqualsStatement extends BinaryOperation { } @Override - public Expression.ReturnType returnType() { - return Expression.ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/BooleanVariable.java similarity index 79% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/BooleanVariable.java index 681c55cad..f34a699ea 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/BooleanVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/BooleanVariable.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public class BooleanVariable implements Variable { @@ -31,8 +31,8 @@ public class BooleanVariable implements Variable { } @Override - public Expression.ReturnType getType() { - return Expression.ReturnType.BOOLEAN; + public Type getType() { + return Type.BOOLEAN; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/NumberVariable.java similarity index 79% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/NumberVariable.java index c51b1d5c0..c7ce80df1 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/NumberVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/NumberVariable.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public class NumberVariable implements Variable { @@ -31,8 +31,8 @@ public class NumberVariable implements Variable { } @Override - public Expression.ReturnType getType() { - return Expression.ReturnType.NUMBER; + public Type getType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/StringVariable.java similarity index 79% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/StringVariable.java index 04990cbc4..d42e46d79 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/StringVariable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/StringVariable.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public class StringVariable implements Variable { @@ -31,8 +31,8 @@ public class StringVariable implements Variable { } @Override - public Expression.ReturnType getType() { - return Expression.ReturnType.STRING; + public Type getType() { + return Type.STRING; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/Variable.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/Variable.java index dc2ad5eea..1ab4c392f 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/Variable.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/Variable.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public interface Variable { @@ -16,7 +16,7 @@ public interface Variable { void setValue(T value); - Expression.ReturnType getType(); + Type getType(); SourcePosition getPosition(); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/BoolAssignmentNode.java similarity index 63% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/BoolAssignmentNode.java index e30ab0375..e8c07ce2a 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/BoolAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/BoolAssignmentNode.java @@ -1,9 +1,10 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BoolAssignmentNode extends VariableAssignmentNode { @@ -12,8 +13,8 @@ public class BoolAssignmentNode extends VariableAssignmentNode { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/NumAssignmentNode.java similarity index 63% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/NumAssignmentNode.java index 9e423ccd1..4ef508888 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/NumAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/NumAssignmentNode.java @@ -1,9 +1,10 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class NumAssignmentNode extends VariableAssignmentNode { @@ -12,8 +13,8 @@ public class NumAssignmentNode extends VariableAssignmentNode { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/StrAssignmentNode.java similarity index 56% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/StrAssignmentNode.java index 2650622f0..bef588be8 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/StrAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/StrAssignmentNode.java @@ -1,9 +1,10 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class StrAssignmentNode extends VariableAssignmentNode { @@ -12,8 +13,8 @@ public class StrAssignmentNode extends VariableAssignmentNode { } @Override - public ReturnType returnType() { - return ReturnType.STRING; + public Type returnType() { + return Type.STRING; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/VariableAssignmentNode.java similarity index 83% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/VariableAssignmentNode.java index eddf45461..0abcb076c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/assign/VariableAssignmentNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/assign/VariableAssignmentNode.java @@ -5,10 +5,10 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.assign; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.assign; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public abstract class VariableAssignmentNode implements Expression { diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/BoolVariableReferenceNode.java similarity index 57% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/BoolVariableReferenceNode.java index 20ef61bae..432a65c51 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/BoolVariableReferenceNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/BoolVariableReferenceNode.java @@ -1,12 +1,13 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class BoolVariableReferenceNode extends VariableReferenceNode { - public BoolVariableReferenceNode(SourcePosition position, ReturnType type, int index) { + public BoolVariableReferenceNode(SourcePosition position, Type type, int index) { super(position, type, index); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/NumVariableReferenceNode.java similarity index 57% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/NumVariableReferenceNode.java index 946d29c02..5afb2276e 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/NumVariableReferenceNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/NumVariableReferenceNode.java @@ -1,12 +1,13 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; public class NumVariableReferenceNode extends VariableReferenceNode { - public NumVariableReferenceNode(SourcePosition position, ReturnType type, int index) { + public NumVariableReferenceNode(SourcePosition position, Type type, int index) { super(position, type, index); } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/StrVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/StrVariableReferenceNode.java new file mode 100644 index 000000000..15b9417f8 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/StrVariableReferenceNode.java @@ -0,0 +1,18 @@ +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference; + +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; + + +public class StrVariableReferenceNode extends VariableReferenceNode { + public StrVariableReferenceNode(SourcePosition position, Type type, int index) { + super(position, type, index); + } + + @Override + public String evaluate(ImplementationArguments implementationArguments, Scope scope) { + return scope.getStr(index); + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/VariableReferenceNode.java similarity index 65% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/VariableReferenceNode.java index 9272dd554..437a1636c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/VariableReferenceNode.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/parser/lang/variables/reference/VariableReferenceNode.java @@ -5,25 +5,26 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; +package com.dfsek.terra.addons.terrascript.legacy.parser.lang.variables.reference; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; public abstract class VariableReferenceNode implements Expression { protected final int index; private final SourcePosition position; - private final ReturnType type; + private final Type type; - public VariableReferenceNode(SourcePosition position, ReturnType type, int index) { + public VariableReferenceNode(SourcePosition position, Type type, int index) { this.position = position; this.type = type; this.index = index; } @Override - public ReturnType returnType() { + public Type returnType() { return type; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/StructureScript.java similarity index 78% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/StructureScript.java index 72dae25c8..aafbffef7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/StructureScript.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/StructureScript.java @@ -5,9 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script; - -import com.dfsek.terra.addons.terrascript.lexer.Lexer; +package com.dfsek.terra.addons.terrascript.legacy.script; import net.jafama.FastMath; import org.apache.commons.io.IOUtils; @@ -19,28 +17,29 @@ import java.io.InputStream; import java.nio.charset.Charset; import java.util.Random; -import com.dfsek.terra.addons.terrascript.parser.Parser; -import com.dfsek.terra.addons.terrascript.parser.lang.Executable; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.BinaryNumberFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.BiomeFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.BlockFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.CheckBlockFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.EntityFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.GetMarkFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.LootFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.PullFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.RandomFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.RecursionsFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.SetMarkFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.StateFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.StructureFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.UnaryBooleanFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.UnaryNumberFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.UnaryStringFunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.builders.ZeroArgFunctionBuilder; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.Parser; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Executable; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope.ScopeBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.BinaryNumberFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.BiomeFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.BlockFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.CheckBlockFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.EntityFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.GetMarkFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.LootFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.PullFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.RandomFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.RecursionsFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.SetMarkFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.StateFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.StructureFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.UnaryBooleanFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.UnaryNumberFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.UnaryStringFunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.builders.ZeroArgFunctionBuilder; +import com.dfsek.terra.addons.terrascript.lexer.Lexer; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.registry.key.Keyed; @@ -82,7 +81,6 @@ public class StructureScript implements Structure, Keyed { .registerFunction("block", new BlockFunctionBuilder(platform)) .registerFunction("debugBlock", new BlockFunctionBuilder(platform)) .registerFunction("structure", new StructureFunctionBuilder(structureRegistry, platform)) - .registerFunction("randomInt", new RandomFunctionBuilder()) .registerFunction("recursions", new RecursionsFunctionBuilder()) .registerFunction("setMark", new SetMarkFunctionBuilder()) .registerFunction("getMark", new GetMarkFunctionBuilder()) @@ -94,17 +92,20 @@ public class StructureScript implements Structure, Keyed { .registerFunction("state", new StateFunctionBuilder(platform)) .registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog))) .registerFunction("originX", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getX(), - Expression.ReturnType.NUMBER)) + Type.NUMBER)) .registerFunction("originY", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getY(), - Expression.ReturnType.NUMBER)) + Type.NUMBER)) .registerFunction("originZ", new ZeroArgFunctionBuilder(arguments -> arguments.getOrigin().getZ(), - Expression.ReturnType.NUMBER)) + Type.NUMBER)) .registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), - Expression.ReturnType.STRING)) + Type.STRING)) .registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), - Expression.ReturnType.NUMBER)) + Type.NUMBER)) + + .registerFunction("print", new UnaryStringFunctionBuilder(string -> LOGGER.info("[TerraScript:{}] {}", id, string))) + .registerFunction("randomInt", new RandomFunctionBuilder()) .registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue()))) .registerFunction("pow2", new UnaryNumberFunctionBuilder(number -> FastMath.pow2(number.doubleValue()))) .registerFunction("pow", new BinaryNumberFunctionBuilder( diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/TerraImplementationArguments.java similarity index 92% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/TerraImplementationArguments.java index b9b9af058..d9280de35 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/TerraImplementationArguments.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/TerraImplementationArguments.java @@ -5,13 +5,13 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script; +package com.dfsek.terra.addons.terrascript.legacy.script; import java.util.HashMap; import java.util.Map; import java.util.Random; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3Int; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BinaryNumberFunctionBuilder.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BinaryNumberFunctionBuilder.java index 284764053..a5203e0d7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BinaryNumberFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BinaryNumberFunctionBuilder.java @@ -5,17 +5,18 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; import java.util.function.BiFunction; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; public class BinaryNumberFunctionBuilder implements FunctionBuilder> { @@ -30,8 +31,8 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder build(List> argumentList, SourcePosition position) { return new Function<>() { @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @SuppressWarnings("unchecked") @@ -54,8 +55,8 @@ public class BinaryNumberFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; + case 0, 1, 2 -> Type.NUMBER; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BlockFunctionBuilder.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BlockFunctionBuilder.java index fe6377bb8..241aea279 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/BlockFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/BlockFunctionBuilder.java @@ -5,17 +5,18 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.BooleanConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.BlockFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -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.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.BlockFunction; import com.dfsek.terra.api.Platform; @@ -48,11 +49,11 @@ public class BlockFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; - case 4 -> Expression.ReturnType.BOOLEAN; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; + case 4 -> Type.BOOLEAN; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/CheckBlockFunctionBuilder.java similarity index 67% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/CheckBlockFunctionBuilder.java index ca0b56427..fe0409546 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/CheckBlockFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.CheckBlockFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.CheckBlockFunction; public class CheckBlockFunctionBuilder implements FunctionBuilder { @@ -29,9 +30,9 @@ public class CheckBlockFunctionBuilder implements FunctionBuilder Expression.ReturnType.NUMBER; + case 0, 1, 2 -> Type.NUMBER; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/EntityFunctionBuilder.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/EntityFunctionBuilder.java index fba747650..16463a2ec 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/EntityFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/EntityFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.EntityFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.EntityFunction; import com.dfsek.terra.api.Platform; @@ -36,10 +37,10 @@ public class EntityFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/GetMarkFunctionBuilder.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/GetMarkFunctionBuilder.java index 59ec8804f..506ad2598 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/GetMarkFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/GetMarkFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.GetMarkFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.GetMarkFunction; public class GetMarkFunctionBuilder implements FunctionBuilder { @@ -33,9 +34,9 @@ public class GetMarkFunctionBuilder implements FunctionBuilder } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; + case 0, 1, 2 -> Type.NUMBER; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/LootFunctionBuilder.java similarity index 72% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/LootFunctionBuilder.java index 500491021..1997fbf95 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/LootFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/LootFunctionBuilder.java @@ -5,15 +5,16 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.StructureScript; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.LootFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.StructureScript; -import com.dfsek.terra.addons.terrascript.script.functions.LootFunction; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.structure.LootTable; @@ -44,10 +45,10 @@ public class LootFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/PullFunctionBuilder.java similarity index 70% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/PullFunctionBuilder.java index 3e7dd6f7e..d5f1ed71c 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/PullFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/PullFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.PullFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.PullFunction; import com.dfsek.terra.api.Platform; @@ -36,10 +37,10 @@ public class PullFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RandomFunctionBuilder.java similarity index 62% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RandomFunctionBuilder.java index 72fa5338e..8b5724f26 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RandomFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RandomFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.RandomFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.RandomFunction; public class RandomFunctionBuilder implements FunctionBuilder { @@ -28,8 +29,8 @@ public class RandomFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { - if(position == 0) return Expression.ReturnType.NUMBER; + public Type getArgument(int position) { + if(position == 0) return Type.NUMBER; return null; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RecursionsFunctionBuilder.java similarity index 62% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RecursionsFunctionBuilder.java index 9aad77048..75da0f5ee 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/RecursionsFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/RecursionsFunctionBuilder.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.RecursionsFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.RecursionsFunction; public class RecursionsFunctionBuilder implements FunctionBuilder { @@ -27,7 +28,7 @@ public class RecursionsFunctionBuilder implements FunctionBuilder { @@ -33,10 +34,10 @@ public class SetMarkFunctionBuilder implements FunctionBuilder } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StateFunctionBuilder.java similarity index 68% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StateFunctionBuilder.java index 7b4e193c7..d7b954047 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StateFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StateFunctionBuilder.java @@ -5,15 +5,16 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.StateFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.StateFunction; import com.dfsek.terra.api.Platform; @@ -38,10 +39,10 @@ public class StateFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; - case 3 -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + case 3 -> Type.STRING; default -> null; }; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StructureFunctionBuilder.java similarity index 74% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StructureFunctionBuilder.java index a464a3f2d..ebea4f053 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/StructureFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/StructureFunctionBuilder.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; import java.util.stream.Collectors; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.functions.StructureFunction; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.functions.StructureFunction; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.structure.Structure; @@ -46,10 +47,10 @@ public class StructureFunctionBuilder implements FunctionBuilder Expression.ReturnType.NUMBER; - default -> Expression.ReturnType.STRING; + case 0, 1, 2 -> Type.NUMBER; + default -> Type.STRING; }; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/UnaryBooleanFunctionBuilder.java similarity index 66% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/UnaryBooleanFunctionBuilder.java index 47ba20d53..4cc6a91cc 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/UnaryBooleanFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/builders/UnaryBooleanFunctionBuilder.java @@ -5,18 +5,19 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.builders; +package com.dfsek.terra.addons.terrascript.legacy.script.builders; import java.util.List; import java.util.function.BiConsumer; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; public class UnaryBooleanFunctionBuilder implements FunctionBuilder> { @@ -31,8 +32,8 @@ public class UnaryBooleanFunctionBuilder implements FunctionBuilder build(List> argumentList, SourcePosition position) { return new Function<>() { @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } @SuppressWarnings("unchecked") @@ -56,8 +57,8 @@ public class UnaryBooleanFunctionBuilder implements FunctionBuilder> { @@ -29,8 +30,8 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder build(List> argumentList, SourcePosition position) { return new Function<>() { @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @SuppressWarnings("unchecked") @@ -52,8 +53,8 @@ public class UnaryNumberFunctionBuilder implements FunctionBuilder> { @@ -29,8 +30,8 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder build(List> argumentList, SourcePosition position) { return new Function<>() { @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } @SuppressWarnings("unchecked") @@ -53,8 +54,8 @@ public class UnaryStringFunctionBuilder implements FunctionBuilder implements FunctionBuilder> { private final java.util.function.Function function; - private final Expression.ReturnType type; + private final Type type; - public ZeroArgFunctionBuilder(java.util.function.Function function, Expression.ReturnType type) { + public ZeroArgFunctionBuilder(java.util.function.Function function, Type type) { this.function = function; this.type = type; } @@ -31,7 +32,7 @@ public class ZeroArgFunctionBuilder implements FunctionBuilder> { public Function build(List> argumentList, SourcePosition position) { return new Function<>() { @Override - public ReturnType returnType() { + public Type returnType() { return type; } @@ -53,7 +54,7 @@ public class ZeroArgFunctionBuilder implements FunctionBuilder> { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { if(position == 0) return type; return null; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BiomeFunction.java similarity index 78% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BiomeFunction.java index 77341776b..dc878a289 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BiomeFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BiomeFunction.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector3; @@ -59,7 +60,7 @@ public class BiomeFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.STRING; + public Type returnType() { + return Type.STRING; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BlockFunction.java similarity index 86% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BlockFunction.java index 9299177f9..d193093b2 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/BlockFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/BlockFunction.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; import org.slf4j.Logger; @@ -14,13 +14,14 @@ import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Map; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -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; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.util.RotationUtil; @@ -62,8 +63,8 @@ public class BlockFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } void setBlock(ImplementationArguments implementationArguments, Scope scope, diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/CheckBlockFunction.java similarity index 79% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/CheckBlockFunction.java index c61c038ff..2ab7b4d8b 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/CheckBlockFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/CheckBlockFunction.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector3; @@ -59,7 +60,7 @@ public class CheckBlockFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.STRING; + public Type returnType() { + return Type.STRING; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/EntityFunction.java similarity index 78% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/EntityFunction.java index a168d3a36..39db160b7 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/EntityFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/EntityFunction.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.EntityType; @@ -65,7 +66,7 @@ public class EntityFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/GetMarkFunction.java similarity index 78% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/GetMarkFunction.java index 042f82a0f..342f47fbb 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/GetMarkFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/GetMarkFunction.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector3; @@ -53,7 +54,7 @@ public class GetMarkFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.STRING; + public Type returnType() { + return Type.STRING; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/LootFunction.java similarity index 88% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/LootFunction.java index 04f8f49de..666172f25 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/LootFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/LootFunction.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; import org.slf4j.Logger; @@ -13,13 +13,14 @@ import org.slf4j.LoggerFactory; import java.util.Random; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.StructureScript; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.StructureScript; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.Container; @@ -102,7 +103,7 @@ public class LootFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/PullFunction.java similarity index 76% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/PullFunction.java index ebcde348b..e4c72abc3 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/PullFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/PullFunction.java @@ -5,18 +5,19 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.ConstantExpression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.ConstantExpression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.util.RotationUtil; @@ -65,7 +66,7 @@ public class PullFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RandomFunction.java similarity index 64% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RandomFunction.java index d1ed7d26b..e31f5db88 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RandomFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RandomFunction.java @@ -5,14 +5,15 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; public class RandomFunction implements Function { @@ -26,8 +27,8 @@ public class RandomFunction implements Function { @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RecursionsFunction.java similarity index 62% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RecursionsFunction.java index de6d1e030..7ade76541 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/RecursionsFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/RecursionsFunction.java @@ -5,13 +5,14 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; public class RecursionsFunction implements Function { @@ -22,8 +23,8 @@ public class RecursionsFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/SetMarkFunction.java similarity index 78% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/SetMarkFunction.java index 373b5f727..067706dff 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/SetMarkFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/SetMarkFunction.java @@ -5,16 +5,17 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector3; @@ -56,7 +57,7 @@ public class SetMarkFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StateFunction.java similarity index 80% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StateFunction.java index ffa69b338..9c686589b 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StateFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StateFunction.java @@ -5,18 +5,19 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; @@ -65,7 +66,7 @@ public class StateFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StructureFunction.java similarity index 87% rename from common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java rename to common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StructureFunction.java index 8effdd60a..9c3860839 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/functions/StructureFunction.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/legacy/script/functions/StructureFunction.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package com.dfsek.terra.addons.terrascript.script.functions; +package com.dfsek.terra.addons.terrascript.legacy.script.functions; import net.jafama.FastMath; import org.slf4j.Logger; @@ -13,13 +13,14 @@ import org.slf4j.LoggerFactory; import java.util.List; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.StructureScript; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.StructureScript; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.registry.Registry; import com.dfsek.terra.api.structure.Structure; @@ -50,8 +51,8 @@ public class StructureFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.BOOLEAN; + public Type returnType() { + return Type.BOOLEAN; } @Override diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Lexer.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Lexer.java index 3698a9a0d..db4ea3f94 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Lexer.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Lexer.java @@ -9,22 +9,23 @@ package com.dfsek.terra.addons.terrascript.lexer; import com.google.common.collect.Sets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Set; -import java.util.Stack; +import com.dfsek.terra.addons.terrascript.exception.lexer.EOFException; +import com.dfsek.terra.addons.terrascript.exception.lexer.FormatException; +import com.dfsek.terra.addons.terrascript.exception.lexer.TokenizerException; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; -import com.dfsek.terra.addons.terrascript.lexer.exceptions.EOFException; -import com.dfsek.terra.addons.terrascript.lexer.exceptions.FormatException; -import com.dfsek.terra.addons.terrascript.lexer.exceptions.TokenizerException; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; public class Lexer { - public static final Set syntaxSignificant = Sets.newHashSet(';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', '/', + public static final Set syntaxSignificant = Sets.newHashSet(':', ';', '(', ')', '"', ',', '\\', '=', '{', '}', '+', '-', '*', + '/', '>', '<', '!'); // Reserved chars private final LookaheadStream reader; - private final Stack bracketStack = new Stack<>(); private Token current; public Lexer(String data) { @@ -32,6 +33,15 @@ public class Lexer { current = tokenize(); } + public List analyze() { + List tokens = new ArrayList<>(); + while(hasNext()) { + tokens.add(consumeUnchecked()); + } + tokens.add(current()); // Add EOF token + return tokens; + } + /** * Get the first token. * @@ -51,12 +61,13 @@ public class Lexer { * @throws ParseException If token does not exist */ public Token consume(String wrongTypeMessage, TokenType expected, TokenType... more) { - if(!current.isType(expected) && Arrays.stream(more).noneMatch(t -> t == current.getType())) throw new ParseException(wrongTypeMessage, current.getPosition()); + if(!current.isType(expected) && Arrays.stream(more).noneMatch(t -> t == current.type())) throw new ParseException(wrongTypeMessage, + current.position()); return consumeUnchecked(); } public Token consumeUnchecked() { - if(current.getType() == TokenType.END_OF_FILE) return current; + if(current.type() == TokenType.END_OF_FILE) return current; Token temp = current; current = tokenize(); return temp; @@ -68,7 +79,7 @@ public class Lexer { * @return {@code true} if more tokens are present, otherwise {@code false} */ public boolean hasNext() { - return current.getType() != TokenType.END_OF_FILE; + return current.type() != TokenType.END_OF_FILE; } private Token tokenize() throws TokenizerException { @@ -82,10 +93,7 @@ public class Lexer { if(reader.matchesString("/*", true)) skipTo("*/"); // Reached end of file - if(reader.current().isEOF()) { - if(!bracketStack.isEmpty()) throw new ParseException("Dangling open brace", bracketStack.peek().getPosition()); - return new Token(reader.consume().toString(), TokenType.END_OF_FILE, position); - } + if(reader.current().isEOF()) return new Token(reader.consume().toString(), TokenType.END_OF_FILE, position); // Check if operator token if(reader.matchesString("==", true)) @@ -140,21 +148,15 @@ public class Lexer { return new Token(reader.consume().toString(), TokenType.OPEN_PAREN, position); if(reader.current().is(')')) return new Token(reader.consume().toString(), TokenType.CLOSE_PAREN, position); + if(reader.current().is(':')) + return new Token(reader.consume().toString(), TokenType.COLON, position); if(reader.current().is(';')) return new Token(reader.consume().toString(), TokenType.STATEMENT_END, position); if(reader.current().is(',')) return new Token(reader.consume().toString(), TokenType.SEPARATOR, position); - if(reader.current().is('{')) { - Token token = new Token(reader.consume().toString(), TokenType.BLOCK_BEGIN, position); - bracketStack.push(token); - return token; - } - if(reader.current().is('}')) { - if(bracketStack.isEmpty()) throw new ParseException("Dangling close brace", position); - bracketStack.pop(); - return new Token(reader.consume().toString(), TokenType.BLOCK_END, position); - } + if(reader.current().is('{')) return new Token(reader.consume().toString(), TokenType.BLOCK_BEGIN, position); + if(reader.current().is('}')) return new Token(reader.consume().toString(), TokenType.BLOCK_END, position); if(reader.current().is('=')) return new Token(reader.consume().toString(), TokenType.ASSIGNMENT, position); @@ -197,6 +199,9 @@ public class Lexer { if(tokenString.equals("void")) return new Token(tokenString, TokenType.TYPE_VOID, position); + if(tokenString.equals("fun")) + return new Token(tokenString, TokenType.FUNCTION, position); + if(tokenString.equals("if")) return new Token(tokenString, TokenType.IF_STATEMENT, position); if(tokenString.equals("else")) diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/LookaheadStream.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/LookaheadStream.java index 0d0186d3a..49d2882cb 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/LookaheadStream.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/LookaheadStream.java @@ -1,7 +1,6 @@ package com.dfsek.terra.addons.terrascript.lexer; - public class LookaheadStream { private final String source; @@ -39,20 +38,21 @@ public class LookaheadStream { */ public Char peek() { int index = this.index + 1; - if (index + 1 >= source.length()) return null; + if(index + 1 >= source.length()) return null; return new Char(source.charAt(index), getPositionAfter(1)); } /** * Determines if the contained sequence of characters matches the string * - * @param check Input string to check against + * @param check Input string to check against * @param consumeIfMatched Whether to consume the string if there is a match + * * @return If the string matches */ public boolean matchesString(String check, boolean consumeIfMatched) { boolean matches = check.equals(source.substring(index, Math.min(index + check.length(), source.length()))); - if (matches && consumeIfMatched) incrementIndex(check.length()); + if(matches && consumeIfMatched) incrementIndex(check.length()); return matches; } @@ -69,11 +69,11 @@ public class LookaheadStream { } private SourcePosition getPositionAfter(int chars) { - if (chars < 0) throw new IllegalArgumentException("Negative values are not allowed"); + if(chars < 0) throw new IllegalArgumentException("Negative values are not allowed"); int line = position.line(); int column = position.column(); - for (int i = index; i < Math.min(index + chars, source.length() - 1); i++) { - if (source.charAt(i) == '\n') { + for(int i = index; i < Math.min(index + chars, source.length() - 1); i++) { + if(source.charAt(i) == '\n') { line++; column = 0; } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Token.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Token.java index 94a003580..93650d003 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Token.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/lexer/Token.java @@ -7,44 +7,65 @@ package com.dfsek.terra.addons.terrascript.lexer; +import java.util.Objects; + +import com.dfsek.terra.addons.terrascript.parser.BinaryOperator; +import com.dfsek.terra.addons.terrascript.parser.UnaryOperator; + + public class Token { - private final String content; + private final String lexeme; private final TokenType type; private final SourcePosition start; - public Token(String content, TokenType type, SourcePosition start) { - this.content = content; + public Token(String lexeme, TokenType type, SourcePosition start) { + this.lexeme = type == TokenType.END_OF_FILE ? "END OF FILE" : lexeme; this.type = type; this.start = start; } @Override - public String toString() { - return type + ": '" + content + "'"; + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + Token token = (Token) o; + return Objects.equals(lexeme, token.lexeme) && type == token.type && Objects.equals(start, token.start); } - public TokenType getType() { + @Override + public int hashCode() { + return Objects.hash(lexeme, type, start); + } + + @Override + public String toString() { + return type + ": '" + lexeme + "'"; + } + + public TokenType type() { return type; } - public String getContent() { - return content; + public String lexeme() { + return lexeme; } - public SourcePosition getPosition() { + public SourcePosition position() { return start; } - public boolean isConstant() { - return this.type.equals(TokenType.NUMBER) || this.type.equals(TokenType.STRING) || this.type.equals(TokenType.BOOLEAN); - } - - public boolean isType(TokenType type) { - return type == getType(); - } - public boolean isType(TokenType... types) { - for (TokenType t : types) if (isType(t)) return true; + for(TokenType t : types) if(t == type) return true; + return false; + } + + public boolean isOperator(BinaryOperator... operators) { + for(BinaryOperator o : operators) if(o.tokenType == type) return true; + return false; + } + + public boolean isOperator(UnaryOperator... operators) { + for(UnaryOperator o : operators) if(o.tokenType == type) return true; return false; } @@ -210,6 +231,11 @@ public class Token { * Void type declaration */ TYPE_VOID, + /** + * Function declaration + */ + FUNCTION, + COLON, /** * If statement declaration */ diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/BinaryOperator.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/BinaryOperator.java new file mode 100644 index 000000000..a70137915 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/BinaryOperator.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.addons.terrascript.parser; + + +import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; + + +public enum BinaryOperator { + BOOLEAN_OR(TokenType.BOOLEAN_OR), + BOOLEAN_AND(TokenType.BOOLEAN_AND), + EQUALS(TokenType.EQUALS_EQUALS), + NOT_EQUALS(TokenType.BANG_EQUALS), + GREATER(TokenType.GREATER), + GREATER_EQUALS(TokenType.GREATER_EQUAL), + LESS(TokenType.LESS), + LESS_EQUALS(TokenType.LESS_EQUALS), + ADD(TokenType.PLUS), + SUBTRACT(TokenType.MINUS), + MULTIPLY(TokenType.STAR), + DIVIDE(TokenType.FORWARD_SLASH), + MODULO(TokenType.MODULO_OPERATOR); + + public final TokenType tokenType; + + BinaryOperator(TokenType tokenType) { this.tokenType = tokenType; } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java index 5412c4c65..68c03b790 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/Parser.java @@ -1,524 +1,373 @@ -/* - * Copyright (c) 2020-2021 Polyhedral Development - * - * The Terra Core Addons are licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in this module's root directory. - */ - package com.dfsek.terra.addons.terrascript.parser; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Function; +import java.util.Objects; +import java.util.function.Supplier; -import com.dfsek.terra.addons.terrascript.lexer.Lexer; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.ast.Expr; +import com.dfsek.terra.addons.terrascript.ast.Expr.Variable; +import com.dfsek.terra.addons.terrascript.ast.Stmt; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Block; +import com.dfsek.terra.addons.terrascript.legacy.parser.ParserUtil; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; import com.dfsek.terra.addons.terrascript.lexer.Token; import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Block; -import com.dfsek.terra.addons.terrascript.parser.lang.Executable; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.BooleanConstant; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.NumericConstant; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.UserDefinedFunctionBuilder; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.BreakKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.ContinueKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.FailKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.flow.ReturnKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.ForKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.IfKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.keywords.looplike.WhileKeyword; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanAndOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanNotOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.BooleanOrOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.ConcatenationOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.DivisionOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.ModuloOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.MultiplicationOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.NegationOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.NumberAdditionOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.SubtractionOperation; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.EqualsStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.GreaterOrEqualsThanStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.GreaterThanStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanOrEqualsStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.LessThanStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.operations.statements.NotEqualsStatement; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.BoolAssignmentNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.NumAssignmentNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.StrAssignmentNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.assign.VariableAssignmentNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.BoolVariableReferenceNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.NumVariableReferenceNode; -import com.dfsek.terra.addons.terrascript.parser.lang.variables.reference.StrVariableReferenceNode; import com.dfsek.terra.api.util.generic.pair.Pair; +/** + * TerraScript recursive descent parser + */ public class Parser { - private final List ignoredFunctions = new ArrayList<>(); - private final Lexer lexer; + private final List tokens; - public Parser(Lexer lexer) { - this.lexer = lexer; + private int index = 0; + + private Parser(List tokens) { + if(tokens.stream().noneMatch(t -> t.isType(TokenType.END_OF_FILE))) + throw new IllegalArgumentException("Token list must contain at least one token of type " + TokenType.END_OF_FILE); + this.tokens = tokens; } - /** - * Parse input - * - * @return executable {@link Block} - * - * @throws ParseException If parsing fails. - */ - public Executable parse(ScopeBuilder scopeBuilder) { - return new Executable(parseBlock(scopeBuilder, ReturnType.VOID), scopeBuilder); + public static Block parse(List tokens) { + return new Parser(tokens).parseTokens(); } - private WhileKeyword parseWhileLoop(ScopeBuilder scopeBuilder) { - SourcePosition start = lexer.consume("Expected 'while' keyword at beginning of while loop", TokenType.WHILE_LOOP).getPosition(); - lexer.consume("Expected '(' proceeding 'while' keyword", TokenType.OPEN_PAREN); - scopeBuilder = scopeBuilder.innerLoopScope(); - Expression condition = parseExpression(scopeBuilder); - ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN); - lexer.consume("Expected ')' proceeding while loop condition", TokenType.CLOSE_PAREN); - return new WhileKeyword(parseStatementBlock(scopeBuilder, ReturnType.VOID), (Expression) condition, - start); // While loop + private Block parseTokens() { + List statements = new ArrayList<>(); + while(hasNext()) { + statements.add(statement()); + } + if(hasNext()) throw new ParseException("Tokens were remaining after parsing", current().position()); + return new Stmt.Block(statements, new SourcePosition(0, 0)); } - private IfKeyword parseIfStatement(ScopeBuilder scopeBuilder) { - SourcePosition start = lexer.consume("Expected 'if' keyword at beginning of if statement", TokenType.IF_STATEMENT).getPosition(); - lexer.consume("Expected '(' proceeding 'if' keyword", TokenType.OPEN_PAREN); - Expression condition = parseExpression(scopeBuilder); - ParserUtil.ensureReturnType(condition, Expression.ReturnType.BOOLEAN); + private Token current() { + return tokens.get(index); + } + + private boolean hasNext() { + return !current().isType(TokenType.END_OF_FILE); + } + + private Token consume(String wrongTypeMessage, TokenType expected, TokenType... more) { + if(!current().isType(expected) && Arrays.stream(more).noneMatch(t -> t == current().type())) throw new ParseException( + wrongTypeMessage, current().position()); + return consumeUnchecked(); + } + + public Token consumeUnchecked() { + if(!hasNext()) return current(); + Token temp = current(); + index++; + return temp; + } + + private void consumeStatementEnd(String after) { + consume("Expected ';' after " + after + ", found '" + current().lexeme() + "'", TokenType.STATEMENT_END); + } + + private Stmt statement() { + return switch(current().type()) { + case BLOCK_BEGIN -> block(); + case FUNCTION -> functionDeclaration(); + case TYPE_STRING, TYPE_BOOLEAN, TYPE_NUMBER -> variableDeclaration(); + case RETURN -> returnStmt(); + case IF_STATEMENT -> ifStmt(); + case FOR_LOOP -> forLoop(); + case WHILE_LOOP -> whileLoop(); + case BREAK -> breakStmt(); + case CONTINUE -> continueStmt(); + case STATEMENT_END -> new Stmt.NoOp(consumeUnchecked().position()); + default -> expressionStatement(); + }; + } + + private Stmt functionDeclaration() { + SourcePosition position = consume("Expected 'fun' keyword at start of function declaration", TokenType.FUNCTION).position(); + String id = consume("Expected identifier after 'fun' keyword for function declaration", TokenType.IDENTIFIER).lexeme(); + consume("Expected '(' after function identifier '" + id + "'", TokenType.OPEN_PAREN); - lexer.consume("Expected ')' proceeding if statement condition", TokenType.CLOSE_PAREN); - - Block elseBlock = null; - Block statement = parseStatementBlock(scopeBuilder, ReturnType.VOID); - - List, Block>> elseIf = new ArrayList<>(); - - while(lexer.hasNext() && lexer.current().isType(TokenType.ELSE)) { - lexer.consumeUnchecked(); // Consume else. - if(lexer.current().isType(TokenType.IF_STATEMENT)) { - lexer.consumeUnchecked(); // Consume if. - Expression elseCondition = parseExpression(scopeBuilder); - ParserUtil.ensureReturnType(elseCondition, Expression.ReturnType.BOOLEAN); - elseIf.add(Pair.of((Expression) elseCondition, parseStatementBlock(scopeBuilder, ReturnType.VOID))); - } else { - elseBlock = parseStatementBlock(scopeBuilder, ReturnType.VOID); - break; // Else must be last. - } + // Parse parameters + List> params = new ArrayList<>(); + while(!current().isType(TokenType.CLOSE_PAREN)) { + Token paramToken = consume("Expected parameter name or ')', found '" + current().lexeme() + "'", TokenType.IDENTIFIER); + String paramId = paramToken.lexeme(); + if(params.stream().anyMatch(p -> Objects.equals(p.getLeft(), paramId))) + throw new ParseException("Parameter '" + paramId + "' has already been declared in function '" + id + "'", + paramToken.position()); + + consume("Expected type declaration after parameter name. Example: '" + paramId + ": '", TokenType.COLON); + Type paramType = ParserUtil.getVariableReturnType(consumeUnchecked()); + + params.add(Pair.of(paramId, paramType)); + + if(current().isType(TokenType.CLOSE_PAREN)) break; + consume("Expected ',' or ')' after parameter declaration '" + paramId + "' in function '" + id + "'", TokenType.SEPARATOR); } - return new IfKeyword(statement, (Expression) condition, elseIf, elseBlock, start); // If statement + Type funcReturn = Type.VOID; + + consume("Expected ')' after " + (params.size() == 0 ? "')'" : "parameters") + " in declaration of function '" + id + "'", + TokenType.CLOSE_PAREN); + if(current().isType(TokenType.COLON)) { + consumeUnchecked(); + funcReturn = ParserUtil.getVariableReturnType(consumeUnchecked()); + } + + Stmt.Block body = blockOrSingleStatement(); + + return new Stmt.FunctionDeclaration(id, params, funcReturn, body, position); } - private Block parseStatementBlock(ScopeBuilder scopeBuilder, ReturnType blockReturnType) { - if(lexer.current().isType(TokenType.BLOCK_BEGIN)) { - lexer.consumeUnchecked(); - Block block = parseBlock(scopeBuilder, blockReturnType); - lexer.consume("Expected block end '}' after block statements", TokenType.BLOCK_END); - return block; + private Stmt.VariableDeclaration variableDeclaration() { + Token typeToken = consumeUnchecked(); + SourcePosition position = typeToken.position(); + Type type = switch(typeToken.type()) { + case TYPE_BOOLEAN -> Type.BOOLEAN; + case TYPE_NUMBER -> Type.NUMBER; + case TYPE_STRING -> Type.STRING; + default -> throw new ParseException("Invalid token '" + typeToken.lexeme() + "' specified as variable type", position); + }; + String id = consume("Expected variable name after type for variable declaration", TokenType.IDENTIFIER).lexeme(); + consume("Expected '=' following variable name '" + id + "' for variable declaration", TokenType.ASSIGNMENT); + Expr expr = expression(); + consumeStatementEnd("variable declaration"); + + return new Stmt.VariableDeclaration(type, id, expr, position); + } + + private Stmt.Return returnStmt() { + SourcePosition position = consume("Expected 'return' keyword, found '" + current().lexeme() + "'", TokenType.RETURN).position(); + Expr value = new Expr.Void(position); + if(!current().isType(TokenType.STATEMENT_END)) + value = expression(); + consumeStatementEnd("return statement"); + return new Stmt.Return(value, position); + } + + private Stmt.If ifStmt() { + // Parse main if clause + SourcePosition position = consume("Expected 'if' keyword at beginning of if statement", TokenType.IF_STATEMENT).position(); + consume("Expected '(' after 'if' keyword", TokenType.OPEN_PAREN); + Expr condition = expression(); + consume("Expected ')' after if statement condition", TokenType.CLOSE_PAREN); + Stmt.Block trueBody = blockOrSingleStatement(); + + // Parse any else clauses + Stmt.Block elseBody = null; + List> elseIfClauses = new ArrayList<>(); + while(current().isType(TokenType.ELSE)) { + consumeUnchecked(); // Consume else + + if(!current().isType(TokenType.IF_STATEMENT)) { + elseBody = blockOrSingleStatement(); + break; // Else clause should be last in if statement + } + + consumeUnchecked(); // Consume if + consume("Expected '(' after 'else if', e.g. 'if else () ...'", TokenType.OPEN_PAREN); + Expr elseIfCondition = expression(); + consume("Expected ')' after 'else if' clause, e.g. 'else if () ...'", TokenType.CLOSE_PAREN); + Stmt.Block elseIfBody = blockOrSingleStatement(); + elseIfClauses.add(Pair.of(elseIfCondition, elseIfBody)); + } + + return new Stmt.If(condition, trueBody, elseIfClauses, elseBody, position); + } + + private Stmt.For forLoop() { + SourcePosition position = consume("Expected 'for' keyword at beginning of for loop", TokenType.FOR_LOOP).position(); + consume("Expected '(' after 'for' keyword", TokenType.OPEN_PAREN); + Stmt initializer = statement(); + Expr condition; + if(current().isType(TokenType.STATEMENT_END)) { + condition = new Expr.Literal(true, Type.BOOLEAN, + current().position()); // If no condition is provided, set condition = true + consumeUnchecked(); } else { - SourcePosition position = lexer.current().getPosition(); - return new Block(Collections.singletonList(parseStatement(scopeBuilder)), position, blockReturnType); + condition = expression(); + consumeStatementEnd("loop condition"); } - } - - private ForKeyword parseForLoop(ScopeBuilder scopeBuilder) { - SourcePosition start = lexer.consume("Expected 'for' keyword at beginning of for loop", TokenType.FOR_LOOP).getPosition(); - lexer.consume("Expected '(' after 'for' keyword", TokenType.OPEN_PAREN); - scopeBuilder = scopeBuilder.innerLoopScope(); // new scope - - Expression initializer = switch(lexer.current().getType()) { - case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN -> { - Token type = lexer.consume("Expected type before declaration", TokenType.TYPE_STRING, TokenType.TYPE_NUMBER, TokenType.TYPE_BOOLEAN, TokenType.TYPE_VOID); - Token identifier = lexer.consume("Expected identifier after type", TokenType.IDENTIFIER); - Expression expr = parseVariableDeclaration(scopeBuilder, type, identifier); - lexer.consume("Expected ';' after initializer within for loop", TokenType.STATEMENT_END); - yield expr; - } - case IDENTIFIER -> { - Expression expr = parseAssignment(scopeBuilder); - lexer.consume("Expected ';' after initializer within for loop", TokenType.STATEMENT_END); - yield expr; - } - case STATEMENT_END -> { - lexer.consumeUnchecked(); - yield Expression.NOOP; - } - default -> throw new ParseException("Unexpected token '" + lexer.current() + "', expected variable declaration or assignment", lexer.current().getPosition()); - }; - - Expression conditional; - if (lexer.current().isType(TokenType.STATEMENT_END)) // If no conditional is provided, conditional defaults to true - conditional = new BooleanConstant(true, lexer.current().getPosition()); - else - conditional = parseExpression(scopeBuilder); - ParserUtil.ensureReturnType(conditional, Expression.ReturnType.BOOLEAN); - lexer.consume("Expected ';' separator after conditional within for loop", TokenType.STATEMENT_END); - - Expression incrementer; - if(lexer.current().isType(TokenType.CLOSE_PAREN)) - // If no incrementer is provided, do nothing - incrementer = Expression.NOOP; - else if(scopeBuilder.containsVariable(lexer.current().getContent())) // Assume variable assignment - incrementer = parseAssignment(scopeBuilder); - else - incrementer = parseFunctionInvocation(lexer.consume("Expected function call within for loop incrementer", TokenType.IDENTIFIER), scopeBuilder); - lexer.consume("Expected ')' after for loop incrementer", TokenType.CLOSE_PAREN); - - return new ForKeyword(parseStatementBlock(scopeBuilder, ReturnType.VOID), initializer, (Expression) conditional, - incrementer, - start); - } - - private Expression parseExpression(ScopeBuilder scopeBuilder) { - return parseLogicOr(scopeBuilder); - } - - private Expression parseLogicOr(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseLogicAnd, scopeBuilder, (op) -> { - ParserUtil.ensureReturnType(op.left, ReturnType.BOOLEAN); - ParserUtil.ensureReturnType(op.right, ReturnType.BOOLEAN); - }, Map.of(TokenType.BOOLEAN_OR, (op) -> new BooleanOrOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()))); - } - - private Expression parseLogicAnd(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseEquality, scopeBuilder, (op) -> { - ParserUtil.ensureReturnType(op.left, ReturnType.BOOLEAN); - ParserUtil.ensureReturnType(op.right, ReturnType.BOOLEAN); - }, Map.of(TokenType.BOOLEAN_AND, (op) -> new BooleanAndOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()))); - } - - private Expression parseEquality(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseComparison, scopeBuilder, Map.of( - TokenType.EQUALS_EQUALS, (op) -> new EqualsStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.BANG_EQUALS, (op) -> new NotEqualsStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()) - )); - } - - private Expression parseComparison(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseTerm, scopeBuilder, (op) -> { - ParserUtil.ensureReturnType(op.left, ReturnType.NUMBER); - ParserUtil.ensureReturnType(op.right, ReturnType.NUMBER); - }, Map.of( - TokenType.LESS, (op) -> new LessThanStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.LESS_EQUALS, (op) -> new LessThanOrEqualsStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.GREATER, (op) -> new GreaterThanStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.GREATER_EQUAL, (op) -> new GreaterOrEqualsThanStatement((Expression) op.left, (Expression) op.right, op.operator.getPosition()) - )); - } - - private Expression parseTerm(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseFactor, scopeBuilder, Map.of( - TokenType.MINUS, (op) -> { - ParserUtil.ensureReturnType(op.left, ReturnType.NUMBER); - ParserUtil.ensureReturnType(op.right, ReturnType.NUMBER); - return new SubtractionOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()); - }, - TokenType.PLUS, (op) -> { - if (op.left.returnType() == ReturnType.NUMBER && op.right.returnType() == ReturnType.NUMBER) - return new NumberAdditionOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()); - else - return new ConcatenationOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()); - })); - } - - private Expression parseFactor(ScopeBuilder scopeBuilder) { - return parseLeftAssociativeBinaryOperation(this::parseUnary, scopeBuilder, (op) -> { - ParserUtil.ensureReturnType(op.left, ReturnType.NUMBER); - ParserUtil.ensureReturnType(op.right, ReturnType.NUMBER); - }, Map.of( - TokenType.STAR, (op) -> new MultiplicationOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.FORWARD_SLASH, (op) -> new DivisionOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()), - TokenType.MODULO_OPERATOR, (op) -> new ModuloOperation((Expression) op.left, (Expression) op.right, op.operator.getPosition()) - )); - } - - private Expression parseUnary(ScopeBuilder scopeBuilder) { - if (lexer.current().isType(TokenType.BANG, TokenType.MINUS)) { - Token operator = lexer.consumeUnchecked(); - Expression right = parseUnary(scopeBuilder); - return switch(operator.getType()) { - case BANG -> { - ParserUtil.ensureReturnType(right, ReturnType.BOOLEAN); - yield new BooleanNotOperation((Expression) right, operator.getPosition()); - } - case MINUS -> { - ParserUtil.ensureReturnType(right, ReturnType.NUMBER); - yield new NegationOperation((Expression) right, operator.getPosition()); - } - default -> throw new IllegalStateException(); - }; + Expr incrementer; + if(current().isType(TokenType.CLOSE_PAREN)) { + incrementer = null; + consumeUnchecked(); + } else { + incrementer = expression(); + consume("Expected ')' after for loop incrementer", TokenType.CLOSE_PAREN); } - return parsePrimary(scopeBuilder); + Stmt.Block body = blockOrSingleStatement(); + return new Stmt.For(initializer, condition, incrementer, body, position); } - private Expression parsePrimary(ScopeBuilder scopeBuilder) { - Token token = lexer.consumeUnchecked(); - return switch(token.getType()) { - case NUMBER -> { - String content = token.getContent(); - yield new NumericConstant(content.contains(".") ? Double.parseDouble(content) : Integer.parseInt(content), token.getPosition()); - } - case STRING -> new StringConstant(token.getContent(), token.getPosition()); - case BOOLEAN -> new BooleanConstant(Boolean.parseBoolean(token.getContent()), token.getPosition()); - case OPEN_PAREN -> { - Expression expr = parseExpression(scopeBuilder); - lexer.consume("Missing ')' at end of expression group", TokenType.CLOSE_PAREN); - yield expr; - } - case IDENTIFIER -> { - if (scopeBuilder.containsFunction(token.getContent())) - yield parseFunctionInvocation(token, scopeBuilder); - else if (scopeBuilder.containsVariable(token.getContent())) { - ReturnType variableType = scopeBuilder.getVaraibleType(token.getContent()); - yield switch(variableType) { - case NUMBER -> new NumVariableReferenceNode(token.getPosition(), variableType, scopeBuilder.getIndex(token.getContent())); - case BOOLEAN -> new BoolVariableReferenceNode(token.getPosition(), variableType, scopeBuilder.getIndex(token.getContent())); - case STRING -> new StrVariableReferenceNode(token.getPosition(), variableType, scopeBuilder.getIndex(token.getContent())); - default -> throw new ParseException("Illegal type for variable reference: " + variableType, token.getPosition()); - }; + private Stmt.While whileLoop() { + SourcePosition position = consume("Expected 'for' keyword at beginning of while loop", TokenType.WHILE_LOOP).position(); + consume("Expected '(' after 'while' keyword", TokenType.OPEN_PAREN); + Expr condition = expression(); + consume("Expected ')' after while loop condition", TokenType.CLOSE_PAREN); + Stmt.Block body = blockOrSingleStatement(); + return new Stmt.While(condition, body, position); + } + + private Stmt.Break breakStmt() { + SourcePosition position = consume("Expected 'break' keyword for break statement", TokenType.BREAK).position(); + consumeStatementEnd("'break' keyword"); + return new Stmt.Break(position); + } + + private Stmt.Continue continueStmt() { + SourcePosition position = consume("Expected 'continue' keyword for continue statement", TokenType.CONTINUE).position(); + consumeStatementEnd("'continue' keyword"); + return new Stmt.Continue(position); + } + + private Stmt.Block blockOrSingleStatement() { + if(!current().isType(TokenType.BLOCK_BEGIN)) return new Stmt.Block(List.of(statement()), current().position()); + return block(); + } + + private Stmt.Block block() { + SourcePosition position = consume("Expected '{' at start of block", TokenType.BLOCK_BEGIN).position(); + List statements = new ArrayList<>(); + while(!current().isType(TokenType.BLOCK_END)) { + statements.add(statement()); + } + consume("Expected '}' at end of block", TokenType.BLOCK_END); + return new Stmt.Block(statements, position); + } + + private Stmt expressionStatement() { + Expr expression = expression(); + consumeStatementEnd("expression statement"); + return new Stmt.Expression(expression, expression.position); + } + + private Expr expression() { + return assignment(); + } + + private Expr leftAssociativeBinaryExpression(Supplier higherPrecedence, BinaryOperator... operators) { + Expr expr = higherPrecedence.get(); + loop: + while(true) { + for(BinaryOperator operator : operators) { + if(current().isType(operator.tokenType)) { + SourcePosition position = consumeUnchecked().position(); // Consume operator token + expr = new Expr.Binary(expr, operator, higherPrecedence.get(), position); + continue loop; } - throw new ParseException("Identifier '" + token.getContent() + "' is not defined in this scope", token.getPosition()); } - default -> throw new ParseException("Unexpected token '" + token.getContent() + "' when parsing expression", token.getPosition()); - }; - } - - private Expression parseLeftAssociativeBinaryOperation(Function> higherPrecedence, ScopeBuilder scopeBuilder, - Consumer init, - Map>> operators) { - Expression expr = higherPrecedence.apply(scopeBuilder); - TokenType[] opTypes = operators.keySet().toArray(new TokenType[0]); - while (lexer.current().isType(opTypes)) { - Token operator = lexer.consumeUnchecked(); - Expression right = higherPrecedence.apply(scopeBuilder); - BinaryOperationInfo op = new BinaryOperationInfo(expr, operator, right); - init.accept(op); - expr = operators.get(operator.getType()).apply(op); + break; // Break if not any operator } return expr; } - private Expression parseLeftAssociativeBinaryOperation(Function> higherPrecedence, ScopeBuilder scopeBuilder, Map>> operators) { - return parseLeftAssociativeBinaryOperation(higherPrecedence, scopeBuilder, (op) -> {}, operators); - } - - private record BinaryOperationInfo(Expression left, Token operator, Expression right) {} - - private Expression parseDeclaration(ScopeBuilder scopeBuilder) { - Token type = lexer.consume("Expected type before declaration", TokenType.TYPE_STRING, TokenType.TYPE_NUMBER, TokenType.TYPE_BOOLEAN, TokenType.TYPE_VOID); - Token identifier = lexer.consume("Expected identifier after type", TokenType.IDENTIFIER); - - return switch(lexer.current().getType()) { - case ASSIGNMENT -> parseVariableDeclaration(scopeBuilder, type, identifier); - case OPEN_PAREN -> parseFunctionDeclaration(scopeBuilder, type, identifier); - default -> throw new ParseException("Expected '=' for variable assignment or '(' for function declaration after identifier '" + identifier.getContent() + "'", lexer.current().getPosition()); - }; - } - - - private Expression parseVariableDeclaration(ScopeBuilder scopeBuilder, Token type, Token identifier) { - lexer.consume("Expected '=' after identifier '" + identifier.getContent() + "' for variable declaration", TokenType.ASSIGNMENT); - - if (!type.isVariableDeclaration()) throw new ParseException("Expected type specification at beginning of variable declaration", type.getPosition()); - - if(scopeBuilder.containsVariable(identifier.getContent())) - throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition()); - - Expression value = parseExpression(scopeBuilder); - ParserUtil.ensureReturnType(value, ParserUtil.getVariableReturnType(type)); - - String variableName = identifier.getContent(); - return switch(value.returnType()) { - case NUMBER -> new NumAssignmentNode((Expression) value, identifier.getPosition(), - scopeBuilder.declareNum(variableName)); - case STRING -> new StrAssignmentNode((Expression) value, identifier.getPosition(), - scopeBuilder.declareStr(variableName)); - case BOOLEAN -> new BoolAssignmentNode((Expression) value, identifier.getPosition(), - scopeBuilder.declareBool(variableName)); - default -> throw new ParseException("Illegal type for variable declaration: " + type, value.getPosition()); - }; - } - - private Expression parseFunctionDeclaration(ScopeBuilder scopeBuilder, Token type, Token identifier) { - lexer.consume("Expected '(' after identifier '" + identifier.getContent() + "' for function declaration", TokenType.OPEN_PAREN); - - if(!(type.isType(TokenType.TYPE_STRING, TokenType.TYPE_BOOLEAN, TokenType.TYPE_NUMBER, TokenType.TYPE_VOID))) - throw new ParseException("Invalid function declaration return type specification " + type.getType(), type.getPosition()); - - if(scopeBuilder.containsVariable(identifier.getContent())) - throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition()); - - ReturnType returnType = ParserUtil.getVariableReturnType(type); - - ScopeBuilder functionBodyScope = scopeBuilder.functionScope(); - - // Declare parameter names into function body scope - List> parameterInfo = getFunctionParameterDeclaration().stream().map( - arg -> Pair.of(switch(arg.getRight()) { - case NUMBER -> functionBodyScope.declareNum(arg.getLeft()); - case BOOLEAN -> functionBodyScope.declareBool(arg.getLeft()); - case STRING -> functionBodyScope.declareStr(arg.getLeft()); - default -> throw new IllegalArgumentException("Unsupported parameter type: " + arg.getRight()); - }, arg.getRight())).toList(); - - Block body = parseStatementBlock(functionBodyScope, returnType); - - FunctionBuilder functionBuilder = new UserDefinedFunctionBuilder<>(returnType, parameterInfo, body, functionBodyScope); - - scopeBuilder.registerFunction(identifier.getContent(), functionBuilder); - return Expression.NOOP; - } - - private List> getFunctionParameterDeclaration() { - List> parameters = new ArrayList<>(); - while(lexer.current().getType() != TokenType.CLOSE_PAREN) { - // Parse parameter type - Token typeToken = lexer.consume("Expected function parameter type declaration", TokenType.TYPE_BOOLEAN, TokenType.TYPE_STRING, TokenType.TYPE_NUMBER); - ReturnType type = ParserUtil.getVariableReturnType(typeToken); - - // Parse parameter name - Token identifierToken = lexer.consume("Expected function parameter identifier", TokenType.IDENTIFIER); - String name = identifierToken.getContent(); - - parameters.add(Pair.of(name, type)); - - // Consume separator if present, trailing separators are allowed - if(lexer.current().isType(TokenType.SEPARATOR)) lexer.consumeUnchecked(); - } - lexer.consume("Expected ')' after function parameter declaration", TokenType.CLOSE_PAREN); - return parameters; - } - - private Block parseBlock(ScopeBuilder scopeBuilder, ReturnType blockReturnType) { - List> expressions = new ArrayList<>(); - scopeBuilder = scopeBuilder.innerScope(); // Create new inner scope for the block - SourcePosition startPosition = lexer.current().getPosition(); - - boolean hasReturn = false; - - // Parse each statement - while(lexer.hasNext() && !lexer.current().isType(TokenType.BLOCK_END)) { - Expression expression = parseStatement(scopeBuilder); - if(expression != Expression.NOOP) { - expressions.add(expression); - } - if(expression instanceof ReturnKeyword returnKeyword) { - hasReturn = true; - if(returnKeyword.dataReturnType() != blockReturnType) - throw new ParseException( - "Invalid return type, expected " + blockReturnType + ", found " + returnKeyword.dataReturnType(), - expression.getPosition()); + private Expr rightAssociativeBinaryExpression(Supplier higherPrecedence, BinaryOperator... operators) { + Expr expr = higherPrecedence.get(); + for(BinaryOperator operator : operators) { + if(current().isType(operator.tokenType)) { + SourcePosition position = consumeUnchecked().position(); // Consume operator token + return new Expr.Binary(expr, operator, rightAssociativeBinaryExpression(higherPrecedence, operators), position); } } - - if(blockReturnType != ReturnType.VOID && !hasReturn) - throw new ParseException("Block does not contain a return statement, must return type " + blockReturnType, startPosition); - - return new Block(expressions, startPosition, blockReturnType); + return expr; } - private Expression parseStatement(ScopeBuilder scopeBuilder) { - Token token = lexer.current(); - Expression expression = switch(token.getType()) { - case FOR_LOOP -> parseForLoop(scopeBuilder); - case IF_STATEMENT -> parseIfStatement(scopeBuilder); - case WHILE_LOOP -> parseWhileLoop(scopeBuilder); + private Expr assignment() { + Expr expr = logicOr(); + if(current().isType(TokenType.ASSIGNMENT)) { + SourcePosition position = consumeUnchecked().position(); // Consume operator token + if(!(expr instanceof Variable variable)) throw new ParseException("Invalid assignment target", position); + return new Expr.Assignment(variable, assignment(), position); + } + return expr; + } + + private Expr logicOr() { + return leftAssociativeBinaryExpression(this::logicAnd, BinaryOperator.BOOLEAN_OR); + } + + private Expr logicAnd() { + return leftAssociativeBinaryExpression(this::equality, BinaryOperator.BOOLEAN_AND); + } + + private Expr equality() { + return leftAssociativeBinaryExpression(this::comparison, BinaryOperator.EQUALS, BinaryOperator.NOT_EQUALS); + } + + private Expr comparison() { + return leftAssociativeBinaryExpression(this::term, BinaryOperator.GREATER, BinaryOperator.GREATER_EQUALS, BinaryOperator.LESS, + BinaryOperator.LESS_EQUALS); + } + + private Expr term() { + return leftAssociativeBinaryExpression(this::factor, BinaryOperator.ADD, BinaryOperator.SUBTRACT); + } + + private Expr factor() { + return leftAssociativeBinaryExpression(this::unary, BinaryOperator.MULTIPLY, BinaryOperator.DIVIDE, BinaryOperator.MODULO); + } + + private Expr unary() { + UnaryOperator[] operators = { UnaryOperator.NOT, UnaryOperator.NEGATE }; + for(UnaryOperator operator : operators) { + if(current().isType(operator.tokenType)) { + SourcePosition position = consumeUnchecked().position(); + return new Expr.Unary(operator, unary(), position); + } + } + return primary(); + } + + private Expr primary() { + Token token = consumeUnchecked(); + SourcePosition position = token.position(); + return switch(token.type()) { + case NUMBER -> new Expr.Literal(Double.parseDouble(token.lexeme()), Type.NUMBER, position); + case STRING -> new Expr.Literal(token.lexeme(), Type.STRING, position); + case BOOLEAN -> new Expr.Literal(Boolean.parseBoolean(token.lexeme()), Type.BOOLEAN, position); case IDENTIFIER -> { - if(scopeBuilder.containsVariable(token.getContent())) yield parseAssignment(scopeBuilder); // Assume variable assignment - else yield parseFunctionInvocation(lexer.consumeUnchecked(), scopeBuilder); + if(current().isType(TokenType.OPEN_PAREN)) yield call(token); + else yield variable(token); } - case TYPE_NUMBER, TYPE_STRING, TYPE_BOOLEAN, TYPE_VOID -> parseDeclaration(scopeBuilder); - case RETURN -> parseReturn(scopeBuilder); - case BREAK -> { - if (!scopeBuilder.isInLoop()) throw new ParseException("Break statements can only be defined inside loops", token.getPosition()); - yield new BreakKeyword(lexer.consumeUnchecked().getPosition()); + case OPEN_PAREN -> { + if(current().isType(TokenType.CLOSE_PAREN)) { + consumeUnchecked(); // Consume ')' + yield new Expr.Void(position); // () evaluates to void + } + Expr expr = expression(); + consume("Expected ')' to close '(' located at " + position, TokenType.CLOSE_PAREN); + yield new Expr.Grouping(expr, position); } - case CONTINUE -> { - if (!scopeBuilder.isInLoop()) throw new ParseException("Continue statements can only be defined inside loops", token.getPosition()); - yield new ContinueKeyword(lexer.consumeUnchecked().getPosition()); - } - case FAIL -> new FailKeyword(lexer.consumeUnchecked().getPosition()); - case STATEMENT_END -> Expression.NOOP; - default -> throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition()); - }; - if(!token.isControlStructure() && expression != Expression.NOOP) lexer.consume("Expected ';' at end of statement", TokenType.STATEMENT_END); - return expression; - } - - private ReturnKeyword parseReturn(ScopeBuilder scopeBuilder) { - Token returnToken = lexer.consume("Expected 'return' keyword at beginning of return statement", TokenType.RETURN); - Expression data = null; - if(!lexer.current().isType(TokenType.STATEMENT_END)) { - data = parseExpression(scopeBuilder); - } - return new ReturnKeyword(data, returnToken.getPosition()); - } - - private VariableAssignmentNode parseAssignment(ScopeBuilder scopeBuilder) { - Token identifier = lexer.consume("Expected identifier at beginning of assignment", TokenType.IDENTIFIER); - - lexer.consume("Expected '=' after identifier for variable assignment", TokenType.ASSIGNMENT); - - Expression value = parseExpression(scopeBuilder); - - String id = identifier.getContent(); - - ParserUtil.ensureReturnType(value, scopeBuilder.getVaraibleType(id)); - - ReturnType type = value.returnType(); - - return switch(type) { - case NUMBER -> new NumAssignmentNode((Expression) value, identifier.getPosition(), scopeBuilder.getIndex(id)); - case STRING -> new StrAssignmentNode((Expression) value, identifier.getPosition(), scopeBuilder.getIndex(id)); - case BOOLEAN -> new BoolAssignmentNode((Expression) value, identifier.getPosition(), scopeBuilder.getIndex(id)); - default -> throw new ParseException("Illegal type for variable assignment: " + type, value.getPosition()); + default -> throw new ParseException("Unexpected token '" + token.lexeme() + "'", position); }; } - private Expression parseFunctionInvocation(Token identifier, ScopeBuilder scopeBuilder) { - if(!scopeBuilder.containsFunction(identifier.getContent())) - throw new ParseException("Function '" + identifier.getContent() + "' is not defined in this scope", identifier.getPosition()); + private Expr call(Token identifier) { + String id = identifier.lexeme(); + SourcePosition position = consume("Expected '(' to initiate function call on function '" + id + "'", + TokenType.OPEN_PAREN).position(); - FunctionBuilder builder = scopeBuilder.getFunction(identifier.getContent()); - - lexer.consume("Expected '(' after identifier " + identifier.getContent(), TokenType.OPEN_PAREN); // Invocation starts with open paren - - List> args = new ArrayList<>(); - while(!lexer.current().isType(TokenType.CLOSE_PAREN)) { - args.add(parseExpression(scopeBuilder)); - if (lexer.current().isType(TokenType.CLOSE_PAREN)) break; - lexer.consume("Expected ',' between function arguments", TokenType.SEPARATOR); - } - lexer.consume("Expected ')' after function arguments", TokenType.CLOSE_PAREN); - - if(ignoredFunctions.contains(identifier.getContent())) { - return Expression.NOOP; + List args = new ArrayList<>(); + while(!current().isType(TokenType.CLOSE_PAREN)) { + args.add(expression()); + if(current().isType(TokenType.CLOSE_PAREN)) break; + consume("Expected ',' or ')' after passed argument in function call of '" + id + "'", TokenType.SEPARATOR); } - if(builder.argNumber() != -1 && args.size() != builder.argNumber()) - throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition()); + consume("Expected ')' after " + (args.size() == 0 ? "')'" : "arguments") + " in function call of '" + id + "'", + TokenType.CLOSE_PAREN); - for(int i = 0; i < args.size(); i++) { - Expression argument = args.get(i); - if(builder.getArgument(i) == null) - throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), - identifier.getPosition()); - ParserUtil.ensureReturnType(argument, builder.getArgument(i)); - } - return builder.build(args, identifier.getPosition()); + return new Expr.Call(id, args, position); } + private Expr variable(Token identifier) { + return new Expr.Variable(identifier.lexeme(), identifier.position()); + } } diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java deleted file mode 100644 index 6703f3708..000000000 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/ParserUtil.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2020-2021 Polyhedral Development - * - * The Terra Core Addons are licensed under the terms of the MIT License. For more details, - * reference the LICENSE file in this module's root directory. - */ - -package com.dfsek.terra.addons.terrascript.parser; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.dfsek.terra.addons.terrascript.lexer.Token; -import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; - - -public class ParserUtil { - -// public static void ensureType(Token token, TokenType... expected) { -// for(TokenType type : expected) if(token.getType().equals(type)) return; -// throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition()); -// } - - public static void ensureReturnType(Expression returnable, Expression.ReturnType... types) { - for(Expression.ReturnType type : types) if(returnable.returnType().equals(type)) return; - throw new ParseException("Invalid type " + returnable.returnType() + ", expected " + (types.length == 1 ? types[0].toString() : "one of " + Arrays.toString(types)), returnable.getPosition()); - } - - public static Expression.ReturnType getVariableReturnType(Token varToken) { - return switch(varToken.getType()) { - case TYPE_NUMBER -> Expression.ReturnType.NUMBER; - case TYPE_STRING -> Expression.ReturnType.STRING; - case TYPE_BOOLEAN -> Expression.ReturnType.BOOLEAN; - case TYPE_VOID -> Expression.ReturnType.VOID; - default -> throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", - varToken.getPosition()); - }; - } -} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/UnaryOperator.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/UnaryOperator.java new file mode 100644 index 000000000..cc3fcf2c4 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/UnaryOperator.java @@ -0,0 +1,13 @@ +package com.dfsek.terra.addons.terrascript.parser; + +import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; + + +public enum UnaryOperator { + NOT(TokenType.BANG), + NEGATE(TokenType.MINUS); + + public final TokenType tokenType; + + UnaryOperator(TokenType tokenType) { this.tokenType = tokenType; } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionSignature.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionSignature.java deleted file mode 100644 index 3a4e8833b..000000000 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/functions/FunctionSignature.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.functions; - -import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType; -import com.dfsek.terra.api.util.generic.pair.Pair; - - -public record FunctionSignature(ReturnType returnType, Pair[] arguments) { -} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java deleted file mode 100644 index 66aa63d9b..000000000 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/parser/lang/variables/reference/StrVariableReferenceNode.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.dfsek.terra.addons.terrascript.parser.lang.variables.reference; - -import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; - - -public class StrVariableReferenceNode extends VariableReferenceNode { - public StrVariableReferenceNode(SourcePosition position, ReturnType type, int index) { - super(position, type, index); - } - - @Override - public String evaluate(ImplementationArguments implementationArguments, Scope scope) { - return scope.getStr(index); - } -} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/FunctionReferenceAnalyzer.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/FunctionReferenceAnalyzer.java new file mode 100644 index 000000000..2983af853 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/FunctionReferenceAnalyzer.java @@ -0,0 +1,168 @@ +package com.dfsek.terra.addons.terrascript.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.NonexistentSymbolException; +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.SymbolTypeMismatchException; +import com.dfsek.terra.addons.terrascript.ErrorHandler; +import com.dfsek.terra.addons.terrascript.ast.Expr; +import com.dfsek.terra.addons.terrascript.ast.Expr.Assignment; +import com.dfsek.terra.addons.terrascript.ast.Expr.Binary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Call; +import com.dfsek.terra.addons.terrascript.ast.Expr.Grouping; +import com.dfsek.terra.addons.terrascript.ast.Expr.Literal; +import com.dfsek.terra.addons.terrascript.ast.Expr.Unary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Variable; +import com.dfsek.terra.addons.terrascript.ast.Expr.Void; +import com.dfsek.terra.addons.terrascript.ast.Stmt; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Block; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Break; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Continue; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Expression; +import com.dfsek.terra.addons.terrascript.ast.Stmt.For; +import com.dfsek.terra.addons.terrascript.ast.Stmt.FunctionDeclaration; +import com.dfsek.terra.addons.terrascript.ast.Stmt.If; +import com.dfsek.terra.addons.terrascript.ast.Stmt.NoOp; +import com.dfsek.terra.addons.terrascript.ast.Stmt.Return; +import com.dfsek.terra.addons.terrascript.ast.Stmt.VariableDeclaration; +import com.dfsek.terra.addons.terrascript.ast.Stmt.While; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class FunctionReferenceAnalyzer implements Expr.Visitor, Stmt.Visitor { + + private final ErrorHandler errorHandler; + + public FunctionReferenceAnalyzer(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } + + @Override + public Void visitBinaryExpr(Binary expr) { + expr.left.accept(this); + expr.right.accept(this); + return null; + } + + @Override + public Void visitGroupingExpr(Grouping expr) { + expr.expression.accept(this); + return null; + } + + @Override + public Void visitLiteralExpr(Literal expr) { + return null; + } + + @Override + public Void visitUnaryExpr(Unary expr) { + expr.operand.accept(this); + return null; + } + + @Override + public Void visitCallExpr(Call expr) { + String id = expr.identifier; + try { + expr.getEnvironment().getFunction(id); + } catch(NonexistentSymbolException e) { + errorHandler.add( + new UndefinedReferenceException("No function by the name '" + id + "' is defined in this scope", expr.position)); + } catch(SymbolTypeMismatchException e) { + errorHandler.add(new ParseException("Identifier '" + id + "' is not defined as a function", expr.position)); + } + expr.arguments.forEach(e -> e.accept(this)); + return null; + } + + @Override + public Void visitVariableExpr(Variable expr) { + return null; + } + + @Override + public Void visitAssignmentExpr(Assignment expr) { + expr.lValue.accept(this); + expr.rValue.accept(this); + return null; + } + + @Override + public Void visitVoidExpr(Void expr) { + return null; + } + + @Override + public Void visitExpressionStmt(Expression stmt) { + stmt.expression.accept(this); + return null; + } + + @Override + public Void visitBlockStmt(Block stmt) { + stmt.statements.forEach(s -> s.accept(this)); + return null; + } + + @Override + public Void visitFunctionDeclarationStmt(FunctionDeclaration stmt) { + stmt.body.accept(this); + return null; + } + + @Override + public Void visitVariableDeclarationStmt(VariableDeclaration stmt) { + stmt.value.accept(this); + return null; + } + + @Override + public Void visitReturnStmt(Return stmt) { + stmt.value.accept(this); + return null; + } + + @Override + public Void visitIfStmt(If stmt) { + stmt.condition.accept(this); + stmt.trueBody.accept(this); + for(Pair clause : stmt.elseIfClauses) { + clause.getLeft().accept(this); + clause.getRight().accept(this); + } + if(stmt.elseBody != null) { + stmt.elseBody.accept(this); + } + return null; + } + + @Override + public Void visitForStmt(For stmt) { + stmt.initializer.accept(this); + stmt.condition.accept(this); + stmt.incrementer.accept(this); + stmt.body.accept(this); + return null; + } + + @Override + public Void visitWhileStmt(While stmt) { + stmt.condition.accept(this); + stmt.body.accept(this); + return null; + } + + @Override + public Void visitNoOpStmt(NoOp stmt) { + return null; + } + + @Override + public Void visitBreakStmt(Break stmt) { + return null; + } + + @Override + public Void visitContinueStmt(Continue stmt) { + return null; + } +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/ScopeAnalyzer.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/ScopeAnalyzer.java new file mode 100644 index 000000000..adeed6a06 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/ScopeAnalyzer.java @@ -0,0 +1,200 @@ +package com.dfsek.terra.addons.terrascript.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.Environment; +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.NonexistentSymbolException; +import com.dfsek.terra.addons.terrascript.Environment.ScopeException.SymbolTypeMismatchException; +import com.dfsek.terra.addons.terrascript.ErrorHandler; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.ast.Expr; +import com.dfsek.terra.addons.terrascript.ast.Expr.Assignment; +import com.dfsek.terra.addons.terrascript.ast.Expr.Binary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Call; +import com.dfsek.terra.addons.terrascript.ast.Expr.Grouping; +import com.dfsek.terra.addons.terrascript.ast.Expr.Literal; +import com.dfsek.terra.addons.terrascript.ast.Expr.Unary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Variable; +import com.dfsek.terra.addons.terrascript.ast.Expr.Visitor; +import com.dfsek.terra.addons.terrascript.ast.Expr.Void; +import com.dfsek.terra.addons.terrascript.ast.Stmt; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.IdentifierAlreadyDeclaredException; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.api.util.generic.pair.Pair; + + +public class ScopeAnalyzer implements Visitor, Stmt.Visitor { + + private Environment currentScope; + + private final ErrorHandler errorHandler; + + + public ScopeAnalyzer(Environment globalScope, ErrorHandler errorHandler) { + this.currentScope = globalScope; + this.errorHandler = errorHandler; + } + + @Override + public Void visitBinaryExpr(Binary expr) { + expr.right.accept(this); + expr.left.accept(this); + return null; + } + + @Override + public Void visitGroupingExpr(Grouping expr) { + expr.expression.accept(this); + return null; + } + + @Override + public Void visitLiteralExpr(Literal expr) { + return null; + } + + @Override + public Void visitUnaryExpr(Unary expr) { + expr.operand.accept(this); + return null; + } + + @Override + public Void visitCallExpr(Call expr) { + expr.setEnvironment(currentScope); + expr.arguments.forEach(e -> e.accept(this)); + return null; + } + + @Override + public Void visitVariableExpr(Variable expr) { + String id = expr.identifier; + try { + currentScope.getVariable(id); // Ensure variable has been declared in current scope + } catch(NonexistentSymbolException e) { + errorHandler.add( + new UndefinedReferenceException("No variable by the name '" + id + "' is defined in this scope", expr.position)); + } catch(SymbolTypeMismatchException e) { + errorHandler.add(new ParseException("Identifier '" + id + "' is not defined as a variable", expr.position)); + } + expr.setEnvironment(currentScope); + return null; + } + + @Override + public Void visitAssignmentExpr(Assignment expr) { + expr.lValue.accept(this); + expr.rValue.accept(this); + return null; + } + + @Override + public Void visitVoidExpr(Void expr) { + return null; + } + + @Override + public Void visitExpressionStmt(Stmt.Expression stmt) { + stmt.expression.accept(this); + return null; + } + + @Override + public Void visitBlockStmt(Stmt.Block stmt) { + currentScope = currentScope.lexicalInner(); + stmt.statements.forEach(s -> s.accept(this)); + currentScope = currentScope.outer(); + return null; + } + + @Override + public Void visitFunctionDeclarationStmt(Stmt.FunctionDeclaration stmt) { + currentScope = currentScope.functionalInner(); + for(Pair param : stmt.parameters) { + try { + currentScope.put(param.getLeft(), new Environment.Symbol.Variable(param.getRight())); + } catch(Environment.ScopeException.SymbolAlreadyExistsException e) { + throw new IllegalStateException("Formal parameter '" + param.getLeft() + "' defined in '" + stmt.identifier + + "' already exists in the function scope"); + } + } + stmt.body.accept(this); + currentScope = currentScope.outer(); + try { + currentScope.put(stmt.identifier, new Environment.Symbol.Function(stmt.type, stmt.parameters)); + } catch(Environment.ScopeException.SymbolAlreadyExistsException e) { + errorHandler.add(new IdentifierAlreadyDeclaredException("Name '" + stmt.identifier + "' is already defined in this scope", + stmt.position)); + } + return null; + } + + @Override + public Void visitVariableDeclarationStmt(Stmt.VariableDeclaration stmt) { + try { + currentScope.put(stmt.identifier, new Environment.Symbol.Variable(stmt.type)); + } catch(Environment.ScopeException.SymbolAlreadyExistsException e) { + errorHandler.add(new IdentifierAlreadyDeclaredException("Name '" + stmt.identifier + "' is already defined in this scope", + stmt.position)); + } + stmt.setEnvironment(currentScope); + return null; + } + + @Override + public Void visitReturnStmt(Stmt.Return stmt) { + stmt.value.accept(this); + return null; + } + + @Override + public Void visitIfStmt(Stmt.If stmt) { + stmt.condition.accept(this); + stmt.trueBody.accept(this); + for(Pair clause : stmt.elseIfClauses) { + clause.getLeft().accept(this); + clause.getRight().accept(this); + } + if(stmt.elseBody != null) { + stmt.elseBody.accept(this); + } + return null; + } + + @Override + public Expr.Void visitForStmt(Stmt.For stmt) { + currentScope = currentScope.loopInner(); // Loop initializer, condition, and incrementer belong to inner scope + + stmt.initializer.accept(this); + stmt.condition.accept(this); + stmt.incrementer.accept(this); + stmt.body.accept(this); + + currentScope = currentScope.outer(); + return null; + } + + @Override + public Expr.Void visitWhileStmt(Stmt.While stmt) { + stmt.condition.accept(this); + currentScope = currentScope.loopInner(); + stmt.body.accept(this); + currentScope = currentScope.outer(); + return null; + } + + @Override + public Expr.Void visitNoOpStmt(Stmt.NoOp stmt) { + return null; + } + + @Override + public Expr.Void visitBreakStmt(Stmt.Break stmt) { + return null; + } + + @Override + public Expr.Void visitContinueStmt(Stmt.Continue stmt) { + return null; + } + +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/SemanticAnalyzer.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/SemanticAnalyzer.java new file mode 100644 index 000000000..3fc19707d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/SemanticAnalyzer.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.addons.terrascript.semanticanalysis; + +import com.dfsek.terra.addons.terrascript.Environment; +import com.dfsek.terra.addons.terrascript.ErrorHandler; +import com.dfsek.terra.addons.terrascript.ast.Stmt; + + +public class SemanticAnalyzer { + + public static void analyze(Stmt.Block root, ErrorHandler errorHandler) throws Exception { + new ScopeAnalyzer(Environment.global(), errorHandler).visitBlockStmt(root); + errorHandler.throwAny(); + + new FunctionReferenceAnalyzer(errorHandler).visitBlockStmt(root); + errorHandler.throwAny(); + + new TypeChecker(errorHandler).visitBlockStmt(root); + errorHandler.throwAny(); + } + +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/TypeChecker.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/TypeChecker.java new file mode 100644 index 000000000..106ea096d --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/semanticanalysis/TypeChecker.java @@ -0,0 +1,234 @@ +package com.dfsek.terra.addons.terrascript.semanticanalysis; + +import java.util.List; + +import com.dfsek.terra.addons.terrascript.Environment; +import com.dfsek.terra.addons.terrascript.ErrorHandler; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.ast.Expr; +import com.dfsek.terra.addons.terrascript.ast.Expr.Assignment; +import com.dfsek.terra.addons.terrascript.ast.Expr.Binary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Call; +import com.dfsek.terra.addons.terrascript.ast.Expr.Grouping; +import com.dfsek.terra.addons.terrascript.ast.Expr.Literal; +import com.dfsek.terra.addons.terrascript.ast.Expr.Unary; +import com.dfsek.terra.addons.terrascript.ast.Expr.Variable; +import com.dfsek.terra.addons.terrascript.ast.Expr.Visitor; +import com.dfsek.terra.addons.terrascript.ast.Expr.Void; +import com.dfsek.terra.addons.terrascript.ast.Stmt; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidFunctionDeclarationException; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidTypeException; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.api.util.generic.pair.Pair; + +import static com.dfsek.terra.addons.terrascript.util.OrdinalUtil.ordinalOf; + + +public class TypeChecker implements Visitor, Stmt.Visitor { + + private final ErrorHandler errorHandler; + + TypeChecker(ErrorHandler errorHandler) { this.errorHandler = errorHandler; } + + @Override + public Type visitBinaryExpr(Binary expr) { + Type left = expr.left.accept(this); + Type right = expr.right.accept(this); + + return switch(expr.operator) { + case BOOLEAN_OR, BOOLEAN_AND -> { + if(left != Type.BOOLEAN || right != Type.BOOLEAN) + throw new RuntimeException(); + yield Type.BOOLEAN; + } + case EQUALS, NOT_EQUALS -> { + if(left != right) throw new RuntimeException(); + yield Type.BOOLEAN; + } + case GREATER, GREATER_EQUALS, LESS, LESS_EQUALS -> { + if(left != Type.NUMBER || right != Type.NUMBER) + throw new RuntimeException(); + yield Type.BOOLEAN; + } + case ADD -> { + if(left == Type.NUMBER && right == Type.NUMBER) yield Type.NUMBER; + if(left == Type.STRING || right == Type.STRING) yield Type.STRING; + throw new RuntimeException("Addition operands must be either both numbers, or one of type string"); + } + case SUBTRACT, MULTIPLY, DIVIDE, MODULO -> { + if(left != Type.NUMBER || right != Type.NUMBER) + throw new RuntimeException(); + yield Type.NUMBER; + } + }; + } + + @Override + public Type visitGroupingExpr(Grouping expr) { + return expr.expression.accept(this); + } + + @Override + public Type visitLiteralExpr(Literal expr) { + return expr.type; + } + + @Override + public Type visitUnaryExpr(Unary expr) { + Type right = expr.operand.accept(this); + return switch(expr.operator) { + case NOT -> { + if(right != Type.BOOLEAN) throw new RuntimeException(); + yield Type.BOOLEAN; + } + case NEGATE -> { + if(right != Type.NUMBER) throw new RuntimeException(); + yield Type.NUMBER; + } + }; + } + + @Override + public Type visitCallExpr(Call expr) { + String id = expr.identifier; + + Environment.Symbol.Function signature = expr.getEnvironment().getFunction(id); + + List argumentTypes = expr.arguments.stream().map(a -> a.accept(this)).toList(); + List> parameters = signature.parameters; + + if(argumentTypes.size() != parameters.size()) + errorHandler.add(new ParseException( + "Provided " + argumentTypes.size() + " arguments to function call of '" + id + "', expected " + parameters.size() + + " arguments", expr.position)); + + for(int i = 0; i < parameters.size(); i++) { + Type expectedType = parameters.get(i).getRight(); + Type providedType = argumentTypes.get(i); + if(expectedType != providedType) + errorHandler.add(new InvalidTypeException( + ordinalOf(i + 1) + " argument provided for function '" + id + "' expects type " + expectedType + ", found " + + providedType + " instead", expr.position)); + } + + return signature.type; + } + + @Override + public Type visitVariableExpr(Variable expr) { + return expr.getEnvironment().getVariable(expr.identifier).type; + } + + @Override + public Type visitAssignmentExpr(Assignment expr) { + Type right = expr.rValue.accept(this); + Type expected = expr.lValue.accept(this); + String id = expr.lValue.identifier; + if(right != expected) + errorHandler.add(new InvalidTypeException( + "Cannot assign variable '" + id + "' to type " + right + ", '" + id + "' is declared with type " + expected, + expr.position)); + return right; + } + + @Override + public Type visitVoidExpr(Void expr) { + return Type.VOID; + } + + @Override + public Type visitExpressionStmt(Stmt.Expression stmt) { + stmt.expression.accept(this); + return Type.VOID; + } + + @Override + public Type visitBlockStmt(Stmt.Block stmt) { + stmt.statements.forEach(s -> s.accept(this)); + return Type.VOID; + } + + @Override + public Type visitFunctionDeclarationStmt(Stmt.FunctionDeclaration stmt) { + boolean hasReturn = false; + for(Stmt s : stmt.body.statements) { + if(s instanceof Stmt.Return ret) { + hasReturn = true; + Type provided = ret.value.accept(this); + if(provided != stmt.type) + errorHandler.add(new InvalidTypeException( + "Return statement must match function's return type. Function '" + stmt.identifier + "' expects " + + stmt.type + ", found " + provided + " instead", s.position)); + } + s.accept(this); + } + if(stmt.type != Type.VOID && !hasReturn) { + errorHandler.add( + new InvalidFunctionDeclarationException("Function body for '" + stmt.identifier + "' does not contain return statement", + stmt.position)); + } + return Type.VOID; + } + + @Override + public Type visitVariableDeclarationStmt(Stmt.VariableDeclaration stmt) { + Type valueType = stmt.value.accept(this); + if(stmt.type != valueType) + errorHandler.add(new InvalidTypeException( + "Type " + stmt.type + " declared for variable '" + stmt.identifier + "' does not match assigned value type " + + valueType, stmt.position)); + return Type.VOID; + } + + @Override + public Type visitReturnStmt(Stmt.Return stmt) { + stmt.value.accept(this); + return Type.VOID; + } + + @Override + public Type visitIfStmt(Stmt.If stmt) { + if(stmt.condition.accept(this) != Type.BOOLEAN) throw new RuntimeException(); + stmt.trueBody.accept(this); + for(Pair clause : stmt.elseIfClauses) { + if(clause.getLeft().accept(this) != Type.BOOLEAN) throw new RuntimeException(); + clause.getRight().accept(this); + } + if(stmt.elseBody != null) { + stmt.elseBody.accept(this); + } + return Type.VOID; + } + + @Override + public Type visitForStmt(Stmt.For stmt) { + stmt.initializer.accept(this); + if(stmt.condition.accept(this) != Type.BOOLEAN) throw new RuntimeException(); + stmt.incrementer.accept(this); + stmt.body.accept(this); + return Type.VOID; + } + + @Override + public Type visitWhileStmt(Stmt.While stmt) { + if(stmt.condition.accept(this) != Type.BOOLEAN) throw new RuntimeException(); + stmt.body.accept(this); + return Type.VOID; + } + + @Override + public Type visitNoOpStmt(Stmt.NoOp stmt) { + return Type.VOID; + } + + @Override + public Type visitBreakStmt(Stmt.Break stmt) { + return Type.VOID; + } + + @Override + public Type visitContinueStmt(Stmt.Continue stmt) { + return Type.VOID; + } + +} diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/util/OrdinalUtil.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/util/OrdinalUtil.java new file mode 100644 index 000000000..28d9f50d5 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/util/OrdinalUtil.java @@ -0,0 +1,11 @@ +package com.dfsek.terra.addons.terrascript.util; + +public class OrdinalUtil { + public static String ordinalOf(int i) { + String[] suffixes = new String[]{ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" }; + return switch(i % 100) { + case 11, 12, 13 -> i + "th"; + default -> i + suffixes[i % 10]; + }; + } +} diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java b/common/addons/structure-terrascript-loader/src/test/java/legacy/ParserTest.java similarity index 72% rename from common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java rename to common/addons/structure-terrascript-loader/src/test/java/legacy/ParserTest.java index c93c1ebc3..af0be2eb8 100644 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/ParserTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/legacy/ParserTest.java @@ -5,11 +5,12 @@ * reference the LICENSE file in this module's root directory. */ -package structure; +package legacy; +import com.dfsek.terra.addons.terrascript.Type; import com.dfsek.terra.addons.terrascript.lexer.Lexer; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope.ScopeBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope.ScopeBuilder; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.Test; @@ -19,14 +20,14 @@ import java.nio.charset.Charset; import java.util.List; import java.util.Objects; -import com.dfsek.terra.addons.terrascript.parser.Parser; -import com.dfsek.terra.addons.terrascript.parser.exceptions.ParseException; -import com.dfsek.terra.addons.terrascript.parser.lang.Executable; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.Parser; +import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Executable; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; @@ -49,10 +50,10 @@ public class ParserTest { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0 -> Expression.ReturnType.STRING; - case 1 -> Expression.ReturnType.NUMBER; + case 0 -> Type.STRING; + case 1 -> Type.NUMBER; default -> null; }; } @@ -93,8 +94,8 @@ public class ParserTest { } @Override - public ReturnType returnType() { - return ReturnType.VOID; + public Type returnType() { + return Type.VOID; } } } diff --git a/common/addons/structure-terrascript-loader/src/test/java/lexer/LexerTest.java b/common/addons/structure-terrascript-loader/src/test/java/lexer/LexerTest.java new file mode 100644 index 000000000..6da293121 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/test/java/lexer/LexerTest.java @@ -0,0 +1,34 @@ +package lexer; + +import com.dfsek.terra.addons.terrascript.lexer.Lexer; + +import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; +import com.dfsek.terra.addons.terrascript.lexer.Token; + +import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType; + +import org.junit.jupiter.api.Test; + + +import static org.junit.jupiter.api.Assertions.*; + +public class LexerTest { + + private static void tokenTypeTest(String input, TokenType type) { + Lexer lexer = new Lexer(input); + assertEquals(new Token(input, type, new SourcePosition(1, 1)), lexer.current()); + } + + @Test + public void typeTest() { + tokenTypeTest("identifier", TokenType.IDENTIFIER); + tokenTypeTest("(", TokenType.OPEN_PAREN); + tokenTypeTest(")", TokenType.CLOSE_PAREN); + } + + @Test + public void multipleTokensTest() { + Lexer lexer = new Lexer("(3 + 2)"); + lexer.analyze().forEach(System.out::println); + } +} diff --git a/common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadStreamTest.java b/common/addons/structure-terrascript-loader/src/test/java/lexer/LookaheadStreamTest.java similarity index 99% rename from common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadStreamTest.java rename to common/addons/structure-terrascript-loader/src/test/java/lexer/LookaheadStreamTest.java index 2816da706..8910f1f81 100644 --- a/common/addons/structure-terrascript-loader/src/test/java/structure/LookaheadStreamTest.java +++ b/common/addons/structure-terrascript-loader/src/test/java/lexer/LookaheadStreamTest.java @@ -5,7 +5,7 @@ * reference the LICENSE file in this module's root directory. */ -package structure; +package lexer; import com.dfsek.terra.addons.terrascript.lexer.LookaheadStream; import com.dfsek.terra.addons.terrascript.lexer.Char; diff --git a/common/addons/structure-terrascript-loader/src/test/java/semanticanalysis/SemanticAnalyzerTest.java b/common/addons/structure-terrascript-loader/src/test/java/semanticanalysis/SemanticAnalyzerTest.java new file mode 100644 index 000000000..8639898c2 --- /dev/null +++ b/common/addons/structure-terrascript-loader/src/test/java/semanticanalysis/SemanticAnalyzerTest.java @@ -0,0 +1,270 @@ +package semanticanalysis; + +import com.dfsek.terra.addons.terrascript.ErrorHandler; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.IdentifierAlreadyDeclaredException; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException; +import com.dfsek.terra.addons.terrascript.semanticanalysis.SemanticAnalyzer; +import com.dfsek.terra.addons.terrascript.lexer.Lexer; +import com.dfsek.terra.addons.terrascript.parser.Parser; + +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidFunctionDeclarationException; +import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidTypeException; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + + +public class SemanticAnalyzerTest { + + @Test + public void testVariableReference() { + // Use of declared variable + testValid("num a = 1; a + a;"); + + // Can't use undeclared variable + testInvalid("a + a;", UndefinedReferenceException.class); + + // Can't reference variable before declaration + testInvalid("a + a; num a = 1;", UndefinedReferenceException.class); + + // Variable declarations shouldn't be accessible from inner scopes + testInvalid("{ num a = 1; } a + a;", UndefinedReferenceException.class); + + // Can access variables declared in outer scope + testValid("num a = 3; { a + a; }"); + + // Should not be able to use variables from outer scope if they're declared after scope + testInvalid("{ a + a; } num a = 2;", UndefinedReferenceException.class); + + // Can't use undeclared variable as function argument + testInvalid("fun test(p: str) {} test(a);", UndefinedReferenceException.class); + + // Same as above, but in inner scope + testInvalid("fun test(p: str) {} { test(a); }", UndefinedReferenceException.class); + + // Cannot assign undeclared variable + testInvalid("a = 1;", UndefinedReferenceException.class); + + // Cannot assign to variable declared after assignment + testInvalid("a = 2; num a = 1;", UndefinedReferenceException.class); + } + + @Test + public void testAssignment() { + // Simple assignment + testValid("num a = 1; a = 2;"); + + // Can assign variables declared in outer scope + testValid(""" + num a = 1; + { a = 2; } + """); + + // Cannot assign variables declared in inner scope + testInvalid(""" + { num a = 1; } + a = 2; + """, UndefinedReferenceException.class); + + // Cannot assign variables declared in outer scope after reference + testInvalid(""" + { a = 2; } + num a = 1; + """, UndefinedReferenceException.class); + + // Cannot assign variable to expression of different type + testInvalid("num a = 1; a = true;", InvalidTypeException.class); + } + + @Test + public void testReturnStatement() { + // Function return must match signature + testInvalid("fun returnBool(): bool {}", InvalidFunctionDeclarationException.class); + testInvalid("fun returnNum(): num { return \"Not num\"; }", InvalidTypeException.class); + + // Return statements can be empty for void return + testValid("fun returnVoid() { return; }"); + + // Return statement returns type matching function signature + testValid("fun returnNum(): num { return 3; }"); + + testValid("fun returnVoid() { return (); }"); + } + + @Test + public void testControlFlowAnalysis() { + + testValid(""" + fun returnsNum(p: bool): num { + if (p) { + return 1; + } else { + return 0; + } + } + """); + + + // All paths of execution must return a value if return type is not void + testInvalid(""" + fun returnsNum(p: bool): num { + if (p) { + return 1; + } + } + """, null); + + // Not all paths require explicit return for void functions, implicitly returns void at end of execution + testValid(""" + fun returnsNum(p: bool) { + if (p) { + return; + } + } + """); + + // Static analysis of if statement always being true + testValid(""" + fun returnsNum(): num { + if (true) { + return 1; + } + """); + } + + @Test + public void testFunctionCall() { + // Simple function declaration then call + testValid("fun test() {}; test();"); + + // Can be used before declaration + testValid("test(); fun test() {};"); + + // Can be used from outer scope + testValid("fun test() {}; { test(); }"); + + // Can be used from outer scope before declaration + testValid("{ test(); } fun test() {};"); + + // Can be used in many outer scopes + testValid("{{{{{ test(); }}}}} fun test() {};"); + + // Calling function that hasn't been declared + testInvalid("test();", UndefinedReferenceException.class); + + // Cannot use functions declared in inner scopes + testInvalid("{ fun test() {} } test();", UndefinedReferenceException.class); + testInvalid("test(); { fun test() {} }", UndefinedReferenceException.class); + + // Mutual recursion supported + testValid("fun a() { b(); } fun b() { a(); }"); + } + + @Test + public void testFunctionArgumentPassing() { + // Simple argument passing + testValid("fun test(p: num); test(1);"); + + // Passing multiple arguments + testValid("fun test(p1: num, p2: bool); test(1, false);"); + + // Argument type must match parameter type + testInvalid("fun test(p: num); test(false);", InvalidTypeException.class); + + // Function return + testValid(""" + fun returnBool(): bool { + return true; + } + fun takeBool(p: bool) {} + takeBool(returnBool()); + """); + + // Should not be able to pass argument of type not matching parameter type + testInvalid(""" + fun returnBool(): bool { + return true; + } + fun takeNum(p: num) {} + takeNum(returnBool()); + """, InvalidTypeException.class); + } + + @Test + public void testParameterUse() { + // Function bodies should be able to use parameter names + testValid("fun test(a: num, b: num) { a + b; }"); + testInvalid("fun test(a: num, b: num) { a + c; }", UndefinedReferenceException.class); + + // Function bodies can't use variables from outer scope + testInvalid("num a = 1; fun doStuff() { a + 2; }", UndefinedReferenceException.class); + testInvalid("fun doStuff() { a + 2; } num a = 1;", UndefinedReferenceException.class); + + // Type checking parameters + testValid("fun takesNum(a: num) {} fun test(numberParam: num) { takesNum(numberParam); }"); + testInvalid("fun takesNum(a: num) {} fun test(boolParam: bool) { takesNum(boolParam); }", InvalidTypeException.class); + } + + @Test + public void testShadowing() { + // Can't shadow variable in immediate scope + testInvalid("num a = 1; num a = 2;", IdentifierAlreadyDeclaredException.class); + + // Can shadow variable from outer scope + testValid("num a = 1; { num a = 2; }"); + + // Can declare variable after same identifier is used previously in an inner scope + testValid("{ num a = 2; } num a = 1;"); + + // Ensure shadowed variable type is used + testValid(""" + fun takesNum(p: num) {} + bool a = false; + { + num a = 1; + takesNum(a); + } + """); + + // Should not be able to use type of shadowed variable in use of shadowing variable + testInvalid(""" + fun takesNum(p: num) {} + num a = false; + { + bool a = 1; + takesNum(a); + } + """, InvalidTypeException.class); + + // Functions can be shadowed in inner scopes + testValid(""" + fun test() {} + { + fun test() {} + } + { + fun test() {} + } + """); + + // Functions can't be shadowed in the same immediate scope + testInvalid(""" + fun test() {} + fun test() {} + """, IdentifierAlreadyDeclaredException.class); + + // Can't use function name that is already declared as a variable + testInvalid("num id = 1; fun id() {}", IdentifierAlreadyDeclaredException.class); + } + + private void testInvalid(String invalidSource, Class exceptionType) { + ErrorHandler errorHandler = new ErrorHandler(); + assertThrows(exceptionType, () -> SemanticAnalyzer.analyze(Parser.parse(new Lexer(invalidSource).analyze()), errorHandler)); + } + + private void testValid(String validSource) { + ErrorHandler errorHandler = new ErrorHandler(); + assertDoesNotThrow(() -> SemanticAnalyzer.analyze(Parser.parse(new Lexer(validSource).analyze()), errorHandler)); + } +} diff --git a/common/addons/structure-terrascript-loader/src/test/resources/test.tesf b/common/addons/structure-terrascript-loader/src/test/resources/test.tesf index e30635c9c..2368bd948 100644 --- a/common/addons/structure-terrascript-loader/src/test/resources/test.tesf +++ b/common/addons/structure-terrascript-loader/src/test/resources/test.tesf @@ -1,6 +1,6 @@ -str myFunction(str functionString, num functionNumber) { +fun myFunction(functionString: str, functionNumber: num): str { test(functionString, functionNumber); - void nestedFunction() { + fun nestedFunction() { test("Hello from nested function", 69); } nestedFunction(); @@ -11,7 +11,7 @@ str functionResult = myFunction("Hello from myFunction", 535); test(functionResult, 58); -void noReturn() test("Single statement function", 42); +fun noReturn() test("Single statement function", 42); noReturn(); diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java index acbb5da06..dcb20edc5 100644 --- a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunction.java @@ -7,15 +7,17 @@ package com.dfsek.terra.addon.terrascript.check; +import com.dfsek.terra.addons.terrascript.Type; + import net.jafama.FastMath; import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.vector.Vector2; @@ -61,8 +63,8 @@ public class CheckFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.STRING; + public Type returnType() { + return Type.STRING; } private String apply(Vector3 vector, WritableWorld world) { diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java index f38ae10ce..880bcf122 100644 --- a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/CheckFunctionBuilder.java @@ -9,8 +9,9 @@ package com.dfsek.terra.addon.terrascript.check; import java.util.List; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; import com.dfsek.terra.api.Platform; @@ -35,9 +36,9 @@ public class CheckFunctionBuilder implements FunctionBuilder { } @Override - public Expression.ReturnType getArgument(int position) { + public Type getArgument(int position) { return switch(position) { - case 0, 1, 2 -> Expression.ReturnType.NUMBER; + case 0, 1, 2 -> Type.NUMBER; default -> null; }; } diff --git a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java index 26a1ca358..ad3b345eb 100644 --- a/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java +++ b/common/addons/terrascript-function-check-noise-3d/src/main/java/com/dfsek/terra/addon/terrascript/check/TerraScriptCheckFunctionAddon.java @@ -1,7 +1,7 @@ package com.dfsek.terra.addon.terrascript.check; import com.dfsek.terra.addons.manifest.api.AddonInitializer; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java index d3e241a88..1505660fe 100644 --- a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/ConstantSamplerFunction.java @@ -1,10 +1,11 @@ package com.dfsek.terra.addons.terrascript.sampler; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; import com.dfsek.terra.api.noise.NoiseSampler; @@ -52,7 +53,7 @@ public class ConstantSamplerFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java index 538df8432..23376b58a 100644 --- a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunction.java @@ -2,11 +2,12 @@ package com.dfsek.terra.addons.terrascript.sampler; import java.util.function.Supplier; -import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Scope; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; -import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.ImplementationArguments; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Scope; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; import com.dfsek.terra.api.noise.NoiseSampler; @@ -58,7 +59,7 @@ public class SamplerFunction implements Function { } @Override - public ReturnType returnType() { - return ReturnType.NUMBER; + public Type returnType() { + return Type.NUMBER; } } diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java index 612497450..a82864198 100644 --- a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/SamplerFunctionBuilder.java @@ -6,15 +6,16 @@ import java.util.Map; import java.util.Objects; import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression; -import com.dfsek.terra.addons.terrascript.parser.lang.Expression.ReturnType; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.NumericConstant; -import com.dfsek.terra.addons.terrascript.parser.lang.constants.StringConstant; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.Function; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression; +import com.dfsek.terra.addons.terrascript.Type; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.NumericConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.constants.StringConstant; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.addons.terrascript.lexer.SourcePosition; -public class SamplerFunctionBuilder implements FunctionBuilder> { +public class SamplerFunctionBuilder implements FunctionBuilder> { private final Map samplers2d; private final Map samplers3d; @@ -33,8 +34,8 @@ public class SamplerFunctionBuilder implements FunctionBuilder build(List> argumentList, - SourcePosition position) { + public Function build(List> argumentList, + SourcePosition position) { Expression arg = (Expression) argumentList.get(0); if(argumentList.size() == 3) { // 2D @@ -87,10 +88,10 @@ public class SamplerFunctionBuilder implements FunctionBuilder ReturnType.STRING; - case 1, 2, 3 -> ReturnType.NUMBER; + case 0 -> Type.STRING; + case 1, 2, 3 -> Type.NUMBER; default -> null; }; } diff --git a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java index cdb4b92bd..f2d9821d3 100644 --- a/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java +++ b/common/addons/terrascript-function-sampler/src/main/java/com/dfsek/terra/addons/terrascript/sampler/TerraScriptSamplerFunctionAddon.java @@ -2,7 +2,7 @@ package com.dfsek.terra.addons.terrascript.sampler; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.addons.noise.NoiseConfigPackTemplate; -import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; +import com.dfsek.terra.addons.terrascript.legacy.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;