mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-10-27 14:30:23 +00:00
Change Type enum to interface
Also removes legacy v1 code from v2
This commit is contained in:
1 parent
433d695e8b
commit
375f0ba60f
97 files changed
+329
-4731
No files matched your search
+3
-3
@@ -8,9 +8,6 @@
|
|||||||
package com.dfsek.terra.addons.terrascript;
|
package com.dfsek.terra.addons.terrascript;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||||
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.Platform;
|
||||||
import com.dfsek.terra.api.addon.BaseAddon;
|
import com.dfsek.terra.api.addon.BaseAddon;
|
||||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
||||||
@@ -38,6 +35,7 @@ public class TerraScriptAddon implements AddonInitializer {
|
|||||||
.then(event -> {
|
.then(event -> {
|
||||||
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
|
CheckedRegistry<Structure> structureRegistry = event.getPack().getOrCreateRegistry(Structure.class);
|
||||||
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
|
CheckedRegistry<LootTable> lootRegistry = event.getPack().getOrCreateRegistry(LootTable.class);
|
||||||
|
/*
|
||||||
event.getPack().getLoader().open("", ".tesf").thenEntries(
|
event.getPack().getLoader().open("", ".tesf").thenEntries(
|
||||||
entries ->
|
entries ->
|
||||||
entries.stream()
|
entries.stream()
|
||||||
@@ -58,6 +56,8 @@ public class TerraScriptAddon implements AddonInitializer {
|
|||||||
.toList()
|
.toList()
|
||||||
.forEach(structureRegistry::register))
|
.forEach(structureRegistry::register))
|
||||||
.close();
|
.close();
|
||||||
|
|
||||||
|
*/
|
||||||
})
|
})
|
||||||
.priority(100)
|
.priority(100)
|
||||||
.failThrough();
|
.failThrough();
|
||||||
|
|||||||
+81
-15
@@ -2,25 +2,26 @@ package com.dfsek.terra.addons.terrascript;
|
|||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface Type {
|
||||||
|
|
||||||
// TODO - Make not enum
|
static Type fromString(String lexeme) throws TypeException {
|
||||||
// TODO - Add integer type
|
return switch(lexeme) {
|
||||||
public enum Type {
|
case "num" -> NUMBER;
|
||||||
NUMBER,
|
case "int" -> INTEGER;
|
||||||
STRING,
|
case "str" -> STRING;
|
||||||
BOOLEAN,
|
case "bool" -> BOOLEAN;
|
||||||
VOID;
|
case "()" -> VOID;
|
||||||
|
default -> throw new TypeException();
|
||||||
public java.lang.reflect.Type javaType() {
|
|
||||||
return switch(this) {
|
|
||||||
case NUMBER -> double.class;
|
|
||||||
case STRING -> String.class;
|
|
||||||
case BOOLEAN -> boolean.class;
|
|
||||||
case VOID -> void.class;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<Type> from(Class<?> clazz) {
|
java.lang.reflect.Type javaType();
|
||||||
|
|
||||||
|
default boolean typeOf(Type type) {
|
||||||
|
return this.equals(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Optional<Type> from(Class<?> clazz) {
|
||||||
return Optional.ofNullable(
|
return Optional.ofNullable(
|
||||||
clazz == double.class ? NUMBER :
|
clazz == double.class ? NUMBER :
|
||||||
clazz == String.class ? STRING :
|
clazz == String.class ? STRING :
|
||||||
@@ -28,4 +29,69 @@ public enum Type {
|
|||||||
clazz == void.class ? VOID :
|
clazz == void.class ? VOID :
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type NUMBER = new Type() {
|
||||||
|
@Override
|
||||||
|
public java.lang.reflect.Type javaType() {
|
||||||
|
return double.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "num";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Type INTEGER = new Type() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.lang.reflect.Type javaType() {
|
||||||
|
return int.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "int";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Type STRING = new Type() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.lang.reflect.Type javaType() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "str";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Type BOOLEAN = new Type() {
|
||||||
|
@Override
|
||||||
|
public java.lang.reflect.Type javaType() {
|
||||||
|
return boolean.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "bool";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Type VOID = new Type() {
|
||||||
|
@Override
|
||||||
|
public java.lang.reflect.Type javaType() {
|
||||||
|
return void.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "()";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TypeException extends Exception {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
package com.dfsek.terra.addons.terrascript.codegen;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.Type;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.exception.CompilerBugException;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
public class CodegenType {
|
||||||
|
|
||||||
|
private final InstructionType instructionType;
|
||||||
|
|
||||||
|
private final String descriptor;
|
||||||
|
|
||||||
|
public CodegenType(InstructionType instructionType, String descriptor) {
|
||||||
|
this.instructionType = instructionType;
|
||||||
|
this.descriptor = descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InstructionType bytecodeType() {
|
||||||
|
return instructionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final CodegenType BOOLEAN_PRIMITIVE = new CodegenType(InstructionType.INTEGER, "Z");
|
||||||
|
|
||||||
|
private static final Map<Type, CodegenType> TYPE_MAP = Map.of(
|
||||||
|
Type.BOOLEAN, BOOLEAN_PRIMITIVE,
|
||||||
|
Type.STRING, new CodegenType(InstructionType.OBJECT, "Ljava/lang/String;"),
|
||||||
|
Type.NUMBER, new CodegenType(InstructionType.DOUBLE, "D"),
|
||||||
|
Type.VOID, new CodegenType(InstructionType.VOID, "V")
|
||||||
|
);
|
||||||
|
|
||||||
|
public static CodegenType codegenType(Type type) {
|
||||||
|
CodegenType out = TYPE_MAP.get(type);
|
||||||
|
if(out == null)
|
||||||
|
throw new CompilerBugException();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum InstructionType {
|
||||||
|
DOUBLE {
|
||||||
|
@Override
|
||||||
|
public int slotSize() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int returnInsn() {
|
||||||
|
return Opcodes.DRETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int loadInsn() {
|
||||||
|
return Opcodes.DLOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int storeInsn() {
|
||||||
|
return Opcodes.DSTORE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
OBJECT {
|
||||||
|
@Override
|
||||||
|
public int slotSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int returnInsn() {
|
||||||
|
return Opcodes.ARETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int loadInsn() {
|
||||||
|
return Opcodes.ALOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int storeInsn() {
|
||||||
|
return Opcodes.ASTORE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
INTEGER {
|
||||||
|
@Override
|
||||||
|
public int slotSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int returnInsn() {
|
||||||
|
return Opcodes.IRETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int loadInsn() {
|
||||||
|
return Opcodes.ILOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int storeInsn() {
|
||||||
|
return Opcodes.ISTORE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
VOID {
|
||||||
|
@Override
|
||||||
|
public int slotSize() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int returnInsn() {
|
||||||
|
return Opcodes.RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int loadInsn() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int storeInsn() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public abstract int slotSize();
|
||||||
|
|
||||||
|
public abstract int returnInsn();
|
||||||
|
|
||||||
|
public abstract int loadInsn();
|
||||||
|
|
||||||
|
public abstract int storeInsn();
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
-50
@@ -23,6 +23,8 @@ import com.dfsek.terra.addons.terrascript.ast.TypedStmt.Return;
|
|||||||
import com.dfsek.terra.addons.terrascript.ast.TypedStmt.VariableDeclaration;
|
import com.dfsek.terra.addons.terrascript.ast.TypedStmt.VariableDeclaration;
|
||||||
import com.dfsek.terra.addons.terrascript.ast.TypedStmt.While;
|
import com.dfsek.terra.addons.terrascript.ast.TypedStmt.While;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.codegen.CodegenType;
|
||||||
|
import com.dfsek.terra.addons.terrascript.codegen.CodegenType.InstructionType;
|
||||||
import com.dfsek.terra.addons.terrascript.codegen.NativeFunction;
|
import com.dfsek.terra.addons.terrascript.codegen.NativeFunction;
|
||||||
import com.dfsek.terra.addons.terrascript.codegen.TerraScript;
|
import com.dfsek.terra.addons.terrascript.codegen.TerraScript;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.CompilerBugException;
|
import com.dfsek.terra.addons.terrascript.exception.CompilerBugException;
|
||||||
@@ -45,7 +47,10 @@ import java.util.Deque;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.dfsek.terra.addons.terrascript.codegen.CodegenType.BOOLEAN_PRIMITIVE;
|
||||||
|
import static com.dfsek.terra.addons.terrascript.codegen.CodegenType.codegenType;
|
||||||
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.CMP_EQUALS;
|
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.CMP_EQUALS;
|
||||||
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.BOOL_FALSE;
|
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.BOOL_FALSE;
|
||||||
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.CMP_GREATER_EQUALS;
|
import static com.dfsek.terra.addons.terrascript.codegen.asm.OpcodeAlias.CMP_GREATER_EQUALS;
|
||||||
@@ -175,12 +180,13 @@ public class TerraScriptClassGenerator {
|
|||||||
case EQUALS, NOT_EQUALS, BOOLEAN_AND, BOOLEAN_OR, GREATER, GREATER_EQUALS, LESS, LESS_EQUALS -> pushComparisonBool(expr);
|
case EQUALS, NOT_EQUALS, BOOLEAN_AND, BOOLEAN_OR, GREATER, GREATER_EQUALS, LESS, LESS_EQUALS -> pushComparisonBool(expr);
|
||||||
case ADD -> {
|
case ADD -> {
|
||||||
pushBinaryOperands(expr);
|
pushBinaryOperands(expr);
|
||||||
switch(expr.type) {
|
CodegenType codegenType = codegenType(expr.type);
|
||||||
case NUMBER -> method.visitInsn(Opcodes.DADD);
|
if(codegenType.bytecodeType() == InstructionType.DOUBLE)
|
||||||
|
method.visitInsn(Opcodes.DADD);
|
||||||
|
else if (Objects.equals(codegenType.getDescriptor(), "Ljava/lang/String;"))
|
||||||
// TODO - Optimize string concatenation
|
// TODO - Optimize string concatenation
|
||||||
case STRING -> method.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;", false);
|
method.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "concat", "(Ljava/lang/String;)Ljava/lang/String;", false);
|
||||||
default -> throw new RuntimeException("Could not generate bytecode for ADD binary operator returning type " + expr.type);
|
else throw new RuntimeException("Could not generate bytecode for ADD binary operator returning type " + expr.type);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case SUBTRACT -> binaryInsn(expr, Opcodes.DSUB);
|
case SUBTRACT -> binaryInsn(expr, Opcodes.DSUB);
|
||||||
case MULTIPLY -> binaryInsn(expr, Opcodes.DMUL);
|
case MULTIPLY -> binaryInsn(expr, Opcodes.DMUL);
|
||||||
@@ -198,10 +204,9 @@ public class TerraScriptClassGenerator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitLiteralTypedExpr(Literal expr) {
|
public Void visitLiteralTypedExpr(Literal expr) {
|
||||||
switch (expr.type) {
|
if(codegenType(expr.type) == BOOLEAN_PRIMITIVE)
|
||||||
case BOOLEAN -> { if ((boolean) expr.value) pushTrue(); else pushFalse(); }
|
if ((boolean) expr.value) pushTrue(); else pushFalse();
|
||||||
case NUMBER, STRING -> method.visitLdcInsn(expr.value);
|
else method.visitLdcInsn(expr.value);
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,12 +238,7 @@ public class TerraScriptClassGenerator {
|
|||||||
@Override
|
@Override
|
||||||
public Void visitVariableTypedExpr(Variable expr) {
|
public Void visitVariableTypedExpr(Variable expr) {
|
||||||
Type varType = expr.type;
|
Type varType = expr.type;
|
||||||
method.visitVarInsn(switch(varType) {
|
method.visitVarInsn(codegenType(varType).bytecodeType().loadInsn(), lvTable.get(expr.identifier));
|
||||||
case NUMBER -> Opcodes.DLOAD;
|
|
||||||
case STRING -> Opcodes.ALOAD;
|
|
||||||
case BOOLEAN -> Opcodes.ILOAD;
|
|
||||||
default -> throw new RuntimeException("Unable to load local variable, unhandled type '" + varType + "'");
|
|
||||||
}, lvTable.get(expr.identifier));
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,12 +246,7 @@ public class TerraScriptClassGenerator {
|
|||||||
public Void visitAssignmentTypedExpr(Assignment expr) {
|
public Void visitAssignmentTypedExpr(Assignment expr) {
|
||||||
expr.rValue.accept(this);
|
expr.rValue.accept(this);
|
||||||
Type type = expr.lValue.type;
|
Type type = expr.lValue.type;
|
||||||
method.visitVarInsn(switch(type) {
|
method.visitVarInsn(codegenType(type).bytecodeType().storeInsn(), lvTable.get(expr.lValue.identifier));
|
||||||
case NUMBER -> Opcodes.DSTORE;
|
|
||||||
case STRING -> Opcodes.ASTORE;
|
|
||||||
case BOOLEAN -> Opcodes.ISTORE;
|
|
||||||
default -> throw new RuntimeException("Unable to assign local variable, unhandled type '" + type + "'");
|
|
||||||
}, lvTable.get(expr.lValue.identifier));
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,11 +288,7 @@ public class TerraScriptClassGenerator {
|
|||||||
int lvidx = 0;
|
int lvidx = 0;
|
||||||
for (Pair<String, Type> parameter : stmt.parameters) {
|
for (Pair<String, Type> parameter : stmt.parameters) {
|
||||||
funcGenerator.lvTable.put(parameter.getLeft(), lvidx);
|
funcGenerator.lvTable.put(parameter.getLeft(), lvidx);
|
||||||
lvidx += switch(parameter.getRight()) { // Increment by how many slots data type takes
|
lvidx += codegenType(parameter.getRight()).bytecodeType().slotSize(); // Increment by how many slots data type takes
|
||||||
case NUMBER -> 2;
|
|
||||||
case STRING, BOOLEAN -> 1;
|
|
||||||
default -> throw new RuntimeException("Unable to register local variable index for parameter, unknown parameter type '" + parameter.getRight() + "'");
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate method bytecode
|
// Generate method bytecode
|
||||||
@@ -315,24 +306,14 @@ public class TerraScriptClassGenerator {
|
|||||||
public Void visitVariableDeclarationTypedStmt(VariableDeclaration stmt) {
|
public Void visitVariableDeclarationTypedStmt(VariableDeclaration stmt) {
|
||||||
stmt.value.accept(this);
|
stmt.value.accept(this);
|
||||||
lvTable.put(stmt.identifier, lvs.newLocal(ASMUtil.tsTypeToAsmType(stmt.type)));
|
lvTable.put(stmt.identifier, lvs.newLocal(ASMUtil.tsTypeToAsmType(stmt.type)));
|
||||||
method.visitVarInsn(switch(stmt.type) {
|
method.visitVarInsn(codegenType(stmt.type).bytecodeType().storeInsn(), lvTable.get(stmt.identifier));
|
||||||
case NUMBER -> Opcodes.DSTORE;
|
|
||||||
case STRING -> Opcodes.ASTORE;
|
|
||||||
case BOOLEAN -> Opcodes.ISTORE;
|
|
||||||
default -> throw new RuntimeException("Unable to declare local variable, unknown parameter type '" + stmt.type + "'");
|
|
||||||
}, lvTable.get(stmt.identifier));
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visitReturnTypedStmt(Return stmt) {
|
public Void visitReturnTypedStmt(Return stmt) {
|
||||||
stmt.value.accept(this);
|
stmt.value.accept(this);
|
||||||
switch(stmt.value.type) {
|
method.visitInsn(codegenType(stmt.value.type).bytecodeType().returnInsn());
|
||||||
case NUMBER -> method.visitInsn(Opcodes.DRETURN);
|
|
||||||
case STRING -> method.visitInsn(Opcodes.ARETURN);
|
|
||||||
case BOOLEAN -> method.visitInsn(Opcodes.IRETURN);
|
|
||||||
default -> throw new CompilerBugException();
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,19 +538,9 @@ public class TerraScriptClassGenerator {
|
|||||||
|
|
||||||
private String getFunctionDescriptor(List<Type> parameters, Type returnType) {
|
private String getFunctionDescriptor(List<Type> parameters, Type returnType) {
|
||||||
StringBuilder sb = new StringBuilder().append("(");
|
StringBuilder sb = new StringBuilder().append("(");
|
||||||
parameters.stream().map(p -> switch (p) {
|
parameters.stream().map(parameter -> codegenType(parameter).getDescriptor()).forEach(sb::append);
|
||||||
case NUMBER -> "D";
|
|
||||||
case STRING -> "Ljava/lang/String;";
|
|
||||||
case BOOLEAN -> "Z";
|
|
||||||
default -> throw new RuntimeException("Unable to generate method descriptor, unknown parameter type '" + p + "'");
|
|
||||||
}).forEach(sb::append);
|
|
||||||
sb.append(")");
|
sb.append(")");
|
||||||
sb.append(switch (returnType) {
|
sb.append(codegenType(returnType).getDescriptor());
|
||||||
case NUMBER -> "D";
|
|
||||||
case STRING -> "Ljava/lang/String;";
|
|
||||||
case BOOLEAN -> "Z";
|
|
||||||
case VOID -> "V";
|
|
||||||
});
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,8 +9,8 @@ package com.dfsek.terra.addons.terrascript.exception.lexer;
|
|||||||
|
|
||||||
import java.io.Serial;
|
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.lexer.SourcePosition;
|
||||||
|
import com.dfsek.terra.addons.terrascript.parser.ParseException;
|
||||||
|
|
||||||
|
|
||||||
public abstract class TokenizerException extends ParseException {
|
public abstract class TokenizerException extends ParseException {
|
||||||
|
|||||||
-589
@@ -1,589 +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.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<String> 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<Boolean>) 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<Pair<Expression<Boolean>, 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<Boolean>) elseCondition, parseStatementBlock(scopeBuilder, Type.VOID)));
|
|
||||||
} else {
|
|
||||||
elseBlock = parseStatementBlock(scopeBuilder, Type.VOID);
|
|
||||||
break; // Else must be last.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new IfKeyword(statement, (Expression<Boolean>) 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<Boolean>) 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<Boolean>) op.left, (Expression<Boolean>) 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<Boolean>) op.left, (Expression<Boolean>) 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<Object>) op.left, (Expression<Object>) op.right, op.operator.position()),
|
|
||||||
TokenType.BANG_EQUALS,
|
|
||||||
(op) -> new NotEqualsStatement((Expression<Object>) op.left, (Expression<Object>) 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<Number>) op.left, (Expression<Number>) op.right, op.operator.position()),
|
|
||||||
TokenType.LESS_EQUALS,
|
|
||||||
(op) -> new LessThanOrEqualsStatement((Expression<Number>) op.left, (Expression<Number>) op.right, op.operator.position()),
|
|
||||||
TokenType.GREATER,
|
|
||||||
(op) -> new GreaterThanStatement((Expression<Number>) op.left, (Expression<Number>) op.right, op.operator.position()),
|
|
||||||
TokenType.GREATER_EQUAL,
|
|
||||||
(op) -> new GreaterOrEqualsThanStatement((Expression<Number>) op.left, (Expression<Number>) 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<Number>) op.left, (Expression<Number>) op.right, op.operator.position());
|
|
||||||
},
|
|
||||||
TokenType.PLUS, (op) -> {
|
|
||||||
if(op.left.returnType() == Type.NUMBER && op.right.returnType() == Type.NUMBER)
|
|
||||||
return new NumberAdditionOperation((Expression<Number>) op.left, (Expression<Number>) op.right,
|
|
||||||
op.operator.position());
|
|
||||||
else
|
|
||||||
return new ConcatenationOperation((Expression<Object>) op.left, (Expression<Object>) 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<Number>) op.left, (Expression<Number>) op.right, op.operator.position()),
|
|
||||||
TokenType.FORWARD_SLASH,
|
|
||||||
(op) -> new DivisionOperation((Expression<Number>) op.left, (Expression<Number>) op.right, op.operator.position()),
|
|
||||||
TokenType.MODULO_OPERATOR,
|
|
||||||
(op) -> new ModuloOperation((Expression<Number>) op.left, (Expression<Number>) 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<Boolean>) right, operator.position());
|
|
||||||
}
|
|
||||||
case MINUS -> {
|
|
||||||
ParserUtil.ensureReturnType(right, Type.NUMBER);
|
|
||||||
yield new NegationOperation((Expression<Number>) 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.
|
|
||||||
* <p>
|
|
||||||
* E.g. for expression <pre>'a * b + c - d * e + f'</pre> where - and + are at same precedence, and * at a higher precedence:
|
|
||||||
* <pre>
|
|
||||||
* 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))
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @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<Scope.ScopeBuilder, Expression<?>> higherPrecedence,
|
|
||||||
Scope.ScopeBuilder scopeBuilder,
|
|
||||||
Consumer<BinaryOperationInfo> init,
|
|
||||||
Map<TokenType, Function<BinaryOperationInfo, Expression<?>>> 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<Scope.ScopeBuilder, Expression<?>> higherPrecedence,
|
|
||||||
Scope.ScopeBuilder scopeBuilder,
|
|
||||||
Map<TokenType, Function<BinaryOperationInfo, Expression<?>>> 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.isType(TokenType.TYPE_STRING)
|
|
||||||
|| type.isType(TokenType.TYPE_BOOLEAN)
|
|
||||||
|| type.isType(TokenType.TYPE_NUMBER))) 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<Number>) value, identifier.position(),
|
|
||||||
scopeBuilder.declareNum(variableName));
|
|
||||||
case STRING -> new StrAssignmentNode((Expression<String>) value, identifier.position(),
|
|
||||||
scopeBuilder.declareStr(variableName));
|
|
||||||
case BOOLEAN -> new BoolAssignmentNode((Expression<Boolean>) 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<Pair<Integer, Type>> 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<Pair<String, Type>> getFunctionParameterDeclaration() {
|
|
||||||
List<Pair<String, Type>> 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<Expression<?>> 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.isType(TokenType.IF_STATEMENT)
|
|
||||||
|| token.isType(TokenType.WHILE_LOOP)
|
|
||||||
|| token.isType(TokenType.FOR_LOOP)) && 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<Number>) value, identifier.position(), scopeBuilder.getIndex(id));
|
|
||||||
case STRING -> new StrAssignmentNode((Expression<String>) value, identifier.position(), scopeBuilder.getIndex(id));
|
|
||||||
case BOOLEAN -> new BoolAssignmentNode((Expression<Boolean>) 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<Expression<?>> 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-41
@@ -1,41 +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.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());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-70
@@ -1,70 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class Block implements Expression<EvaluationInfo<?>> {
|
|
||||||
private final List<Expression<?>> items;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Type returnType;
|
|
||||||
|
|
||||||
public Block(List<Expression<?>> items, SourcePosition position, Type returnType) {
|
|
||||||
this.items = items;
|
|
||||||
this.position = position;
|
|
||||||
this.returnType = returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
for(Expression<?> item : items) {
|
|
||||||
Object result = item.evaluate(implementationArguments, scope);
|
|
||||||
if(result instanceof EvaluationInfo<?> evalInfo) {
|
|
||||||
if(!evalInfo.level().equals(EvaluationLevel.NONE)) return evalInfo;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.NONE, NOOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum EvaluationLevel {
|
|
||||||
NONE(false),
|
|
||||||
BREAK(false),
|
|
||||||
CONTINUE(false),
|
|
||||||
RETURN(true),
|
|
||||||
FAIL(true);
|
|
||||||
|
|
||||||
private final boolean returnFast;
|
|
||||||
|
|
||||||
EvaluationLevel(boolean returnFast) {
|
|
||||||
this.returnFast = returnFast;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReturnFast() {
|
|
||||||
return returnFast;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public record EvaluationInfo<T extends Expression<?>>(EvaluationLevel level, T data) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-16
@@ -1,16 +0,0 @@
|
|||||||
package com.dfsek.terra.addons.terrascript.legacy.parser.lang;
|
|
||||||
|
|
||||||
|
|
||||||
public class Executable {
|
|
||||||
private final Block script;
|
|
||||||
private final ThreadLocal<Scope> scope;
|
|
||||||
|
|
||||||
public Executable(Block script, Scope.ScopeBuilder scopeBuilder) {
|
|
||||||
this.script = script;
|
|
||||||
this.scope = ThreadLocal.withInitial(scopeBuilder::build);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean execute(ImplementationArguments arguments) {
|
|
||||||
return script.evaluate(arguments, scope.get()).level() != Block.EvaluationLevel.FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +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.legacy.parser.lang;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public interface Expression<T> {
|
|
||||||
Expression<Void> NOOP = new Expression<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Type returnType();
|
|
||||||
|
|
||||||
T evaluate(ImplementationArguments implementationArguments, Scope scope);
|
|
||||||
|
|
||||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
throw new UnsupportedOperationException("Cannot apply " + this + " as double");
|
|
||||||
}
|
|
||||||
|
|
||||||
SourcePosition getPosition();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
-14
@@ -1,14 +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.legacy.parser.lang;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Arguments passed to {@link Expression}s by the implementation
|
|
||||||
*/
|
|
||||||
public interface ImplementationArguments {
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +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.legacy.parser.lang;
|
|
||||||
|
|
||||||
public interface Keyword<T> extends Expression<T> {
|
|
||||||
}
|
|
||||||
-172
@@ -1,172 +0,0 @@
|
|||||||
package com.dfsek.terra.addons.terrascript.legacy.parser.lang;
|
|
||||||
|
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public class Scope {
|
|
||||||
private final double[] num;
|
|
||||||
private final boolean[] bool;
|
|
||||||
private final String[] str;
|
|
||||||
|
|
||||||
private Scope(int numSize, int boolSize, int strSize) {
|
|
||||||
this.num = new double[numSize];
|
|
||||||
this.bool = new boolean[boolSize];
|
|
||||||
this.str = new String[strSize];
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getNum(int index) {
|
|
||||||
return num[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBool(int index) {
|
|
||||||
return bool[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStr(int index) {
|
|
||||||
return str[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNum(int index, double value) {
|
|
||||||
num[index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBool(int index, boolean value) {
|
|
||||||
bool[index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStr(int index, String value) {
|
|
||||||
str[index] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ScopeBuilder {
|
|
||||||
|
|
||||||
private final Map<String, FunctionBuilder<? extends Function<?>>> functions;
|
|
||||||
private final Map<String, Pair<Integer, Type>> indices;
|
|
||||||
private int numSize, boolSize, strSize = 0;
|
|
||||||
private ScopeBuilder parent;
|
|
||||||
|
|
||||||
private boolean inLoop;
|
|
||||||
|
|
||||||
public ScopeBuilder() {
|
|
||||||
this.functions = new HashMap<>();
|
|
||||||
this.indices = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScopeBuilder(ScopeBuilder parent, boolean inLoop) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.numSize = parent.numSize;
|
|
||||||
this.boolSize = parent.boolSize;
|
|
||||||
this.strSize = parent.strSize;
|
|
||||||
this.functions = new HashMap<>(parent.functions);
|
|
||||||
this.indices = new HashMap<>(parent.indices);
|
|
||||||
this.inLoop = inLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScopeBuilder(Map<String, FunctionBuilder<? extends Function<?>>> functions) {
|
|
||||||
this.functions = new HashMap<>(functions);
|
|
||||||
this.indices = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Scope build() {
|
|
||||||
return new Scope(numSize, boolSize, strSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScopeBuilder innerScope() {
|
|
||||||
return new ScopeBuilder(this, inLoop);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScopeBuilder innerLoopScope() { return new ScopeBuilder(this, true); }
|
|
||||||
|
|
||||||
public ScopeBuilder functionScope() { return new ScopeBuilder(functions); }
|
|
||||||
|
|
||||||
public ScopeBuilder registerFunction(String name, FunctionBuilder<? extends Function<?>> functionBuilder) {
|
|
||||||
functions.put(name, functionBuilder);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsFunction(String functionName) {
|
|
||||||
return functions.containsKey(functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FunctionBuilder<?> getFunction(String functionName) {
|
|
||||||
return functions.get(functionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String check(String id) {
|
|
||||||
if(indices.containsKey(id)) {
|
|
||||||
throw new IllegalArgumentException("Variable with ID " + id + " already registered.");
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInLoop() {
|
|
||||||
return inLoop;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int declareNum(String id) {
|
|
||||||
int num = numSize;
|
|
||||||
indices.put(check(id), Pair.of(num, Type.NUMBER));
|
|
||||||
numSize++;
|
|
||||||
updateNumSize(numSize);
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int declareStr(String id) {
|
|
||||||
int str = strSize;
|
|
||||||
indices.put(check(id), Pair.of(str, Type.STRING));
|
|
||||||
strSize++;
|
|
||||||
updateStrSize(strSize);
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int declareBool(String id) {
|
|
||||||
int bool = boolSize;
|
|
||||||
indices.put(check(id), Pair.of(bool, Type.BOOLEAN));
|
|
||||||
boolSize++;
|
|
||||||
updateBoolSize(boolSize);
|
|
||||||
return bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateBoolSize(int size) {
|
|
||||||
this.boolSize = FastMath.max(boolSize, size);
|
|
||||||
if(parent != null) {
|
|
||||||
parent.updateBoolSize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateNumSize(int size) {
|
|
||||||
this.numSize = FastMath.max(numSize, size);
|
|
||||||
if(parent != null) {
|
|
||||||
parent.updateNumSize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateStrSize(int size) {
|
|
||||||
this.strSize = FastMath.max(strSize, size);
|
|
||||||
if(parent != null) {
|
|
||||||
parent.updateStrSize(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndex(String id) {
|
|
||||||
return indices.get(id).getLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getVaraibleType(String id) {
|
|
||||||
return indices.get(id).getRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsVariable(String id) {
|
|
||||||
return indices.containsKey(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-33
@@ -1,33 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BooleanConstant extends ConstantExpression<Boolean> {
|
|
||||||
private final boolean constant;
|
|
||||||
|
|
||||||
public BooleanConstant(Boolean constant, SourcePosition position) {
|
|
||||||
super(constant, position);
|
|
||||||
this.constant = constant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class ConstantExpression<T> implements Expression<T> {
|
|
||||||
private final T constant;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public ConstantExpression(T constant, SourcePosition position) {
|
|
||||||
this.constant = constant;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getConstant() {
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-33
@@ -1,33 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class NumericConstant extends ConstantExpression<Number> {
|
|
||||||
private final double constant;
|
|
||||||
|
|
||||||
public NumericConstant(Number constant, SourcePosition position) {
|
|
||||||
super(constant, position);
|
|
||||||
this.constant = constant.doubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return constant;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +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.legacy.parser.lang.constants;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public class StringConstant extends ConstantExpression<String> {
|
|
||||||
public StringConstant(String constant, SourcePosition position) {
|
|
||||||
super(constant, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-26
@@ -1,26 +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.legacy.parser.lang.functions;
|
|
||||||
|
|
||||||
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<T> extends Expression<T> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return ((Number) evaluate(implementationArguments, scope)).doubleValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
default boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return (Boolean) evaluate(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-26
@@ -1,26 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public interface FunctionBuilder<T extends Function<?>> {
|
|
||||||
T build(List<Expression<?>> argumentList, SourcePosition position);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Number of function parameters, -1 if the function uses a vararg at the end
|
|
||||||
*/
|
|
||||||
int argNumber();
|
|
||||||
|
|
||||||
Type getArgument(int position);
|
|
||||||
}
|
|
||||||
-74
@@ -1,74 +0,0 @@
|
|||||||
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.api.util.generic.pair.Pair;
|
|
||||||
|
|
||||||
|
|
||||||
public class UserDefinedFunctionBuilder<T extends Function<?>> implements FunctionBuilder<T> {
|
|
||||||
|
|
||||||
private final Type returnType;
|
|
||||||
private final List<Pair<Integer, Type>> parameterInfo;
|
|
||||||
private final Scope.ScopeBuilder bodyScopeBuilder;
|
|
||||||
private final Block body;
|
|
||||||
|
|
||||||
public UserDefinedFunctionBuilder(Type returnType, List<Pair<Integer, Type>> parameterInfo, Block body,
|
|
||||||
Scope.ScopeBuilder functionBodyScope) {
|
|
||||||
this.returnType = returnType;
|
|
||||||
this.bodyScopeBuilder = functionBodyScope;
|
|
||||||
this.body = body;
|
|
||||||
this.parameterInfo = parameterInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
//noinspection unchecked
|
|
||||||
return (T) new Function() {
|
|
||||||
|
|
||||||
private final ThreadLocal<Scope> threadLocalScope = ThreadLocal.withInitial(bodyScopeBuilder::build);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
Scope bodyScope = threadLocalScope.get();
|
|
||||||
// Pass parameters into scope of function body
|
|
||||||
for(int i = 0; i < argumentList.size(); i++) {
|
|
||||||
Pair<Integer, Type> 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return body.evaluate(implementationArguments, bodyScope).data().evaluate(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return parameterInfo.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return parameterInfo.get(position).getRight();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-40
@@ -1,40 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BreakKeyword implements Keyword<EvaluationInfo<?>> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public BreakKeyword(SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.BREAK, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-40
@@ -1,40 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ContinueKeyword implements Keyword<EvaluationInfo<?>> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public ContinueKeyword(SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.CONTINUE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-40
@@ -1,40 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class FailKeyword implements Keyword<EvaluationInfo<?>> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public FailKeyword(SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.FAIL, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-54
@@ -1,54 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ReturnKeyword implements Keyword<EvaluationInfo<?>> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
private final Expression<?> data;
|
|
||||||
|
|
||||||
public ReturnKeyword(@Nullable Expression<?> data, SourcePosition position) {
|
|
||||||
this.data = data;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.RETURN, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type dataReturnType() {
|
|
||||||
if(data != null) {
|
|
||||||
return data.returnType();
|
|
||||||
} else {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-57
@@ -1,57 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ForKeyword implements Keyword<Block.EvaluationInfo<?>> {
|
|
||||||
private final Block conditional;
|
|
||||||
private final Expression<?> initializer;
|
|
||||||
private final Expression<Boolean> statement;
|
|
||||||
private final Expression<?> incrementer;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public ForKeyword(Block conditional, Expression<?> initializer, Expression<Boolean> statement, Expression<?> incrementer,
|
|
||||||
SourcePosition position) {
|
|
||||||
this.conditional = conditional;
|
|
||||||
this.initializer = initializer;
|
|
||||||
this.statement = statement;
|
|
||||||
this.incrementer = incrementer;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block.EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
for(initializer.evaluate(implementationArguments, scope);
|
|
||||||
statement.evaluate(implementationArguments, scope);
|
|
||||||
incrementer.evaluate(implementationArguments, scope)) {
|
|
||||||
Block.EvaluationInfo<?> level = conditional.evaluate(implementationArguments, scope);
|
|
||||||
if(level.level().equals(EvaluationLevel.BREAK)) break;
|
|
||||||
if(level.level().isReturnFast()) return level;
|
|
||||||
}
|
|
||||||
return new Block.EvaluationInfo<>(EvaluationLevel.NONE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-64
@@ -1,64 +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.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.api.util.generic.pair.Pair;
|
|
||||||
|
|
||||||
|
|
||||||
public class IfKeyword implements Keyword<Block.EvaluationInfo<?>> {
|
|
||||||
private final Block conditional;
|
|
||||||
private final Expression<Boolean> statement;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final List<Pair<Expression<Boolean>, Block>> elseIf;
|
|
||||||
private final Block elseBlock;
|
|
||||||
|
|
||||||
public IfKeyword(Block conditional, Expression<Boolean> statement, List<Pair<Expression<Boolean>, Block>> elseIf,
|
|
||||||
@Nullable Block elseBlock, SourcePosition position) {
|
|
||||||
this.conditional = conditional;
|
|
||||||
this.statement = statement;
|
|
||||||
this.position = position;
|
|
||||||
this.elseIf = elseIf;
|
|
||||||
this.elseBlock = elseBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Block.EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
if(statement.evaluate(implementationArguments, scope)) return conditional.evaluate(implementationArguments, scope);
|
|
||||||
else {
|
|
||||||
for(Pair<Expression<Boolean>, Block> pair : elseIf) {
|
|
||||||
if(pair.getLeft().evaluate(implementationArguments, scope)) {
|
|
||||||
return pair.getRight().evaluate(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(elseBlock != null) return elseBlock.evaluate(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
return new Block.EvaluationInfo<>(EvaluationLevel.NONE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-51
@@ -1,51 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class WhileKeyword implements Keyword<EvaluationInfo<?>> {
|
|
||||||
private final Block conditional;
|
|
||||||
private final Expression<Boolean> statement;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public WhileKeyword(Block conditional, Expression<Boolean> statement, SourcePosition position) {
|
|
||||||
this.conditional = conditional;
|
|
||||||
this.statement = statement;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public EvaluationInfo<?> evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
while(statement.evaluate(implementationArguments, scope)) {
|
|
||||||
EvaluationInfo<?> level = conditional.evaluate(implementationArguments, scope);
|
|
||||||
if(level.level().equals(EvaluationLevel.BREAK)) break;
|
|
||||||
if(level.level().isReturnFast()) return level;
|
|
||||||
}
|
|
||||||
return new EvaluationInfo<>(EvaluationLevel.NONE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-29
@@ -1,29 +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.legacy.parser.lang.operations;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class BinaryOperation<I, O> implements Expression<O> {
|
|
||||||
protected final Expression<I> left;
|
|
||||||
protected final Expression<I> right;
|
|
||||||
private final SourcePosition start;
|
|
||||||
|
|
||||||
public BinaryOperation(Expression<I> left, Expression<I> right, SourcePosition start) {
|
|
||||||
this.left = left;
|
|
||||||
this.right = right;
|
|
||||||
this.start = start;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BooleanAndOperation extends BinaryOperation<Boolean, Boolean> {
|
|
||||||
public BooleanAndOperation(Expression<Boolean> left, Expression<Boolean> right, SourcePosition start) {
|
|
||||||
super(left, right, start);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyBoolean(implementationArguments, scope) && right.applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BooleanNotOperation extends UnaryOperation<Boolean> {
|
|
||||||
public BooleanNotOperation(Expression<Boolean> input, SourcePosition position) {
|
|
||||||
super(input, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return !input.applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BooleanOrOperation extends BinaryOperation<Boolean, Boolean> {
|
|
||||||
public BooleanOrOperation(Expression<Boolean> left, Expression<Boolean> right, SourcePosition start) {
|
|
||||||
super(left, right, start);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyBoolean(implementationArguments, scope) || right.applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ConcatenationOperation extends BinaryOperation<Object, Object> {
|
|
||||||
public ConcatenationOperation(Expression<Object> left, Expression<Object> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toString(Object object) {
|
|
||||||
String s = object.toString();
|
|
||||||
if(object instanceof Double) {
|
|
||||||
int l = s.length();
|
|
||||||
if(s.charAt(l - 2) == '.' && s.charAt(l - 1) == '0') {
|
|
||||||
s = s.substring(0, s.length() - 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return toString(left.evaluate(implementationArguments, scope)) + toString(right.evaluate(implementationArguments, scope));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class DivisionOperation extends BinaryOperation<Number, Number> {
|
|
||||||
public DivisionOperation(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) / right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ModuloOperation extends BinaryOperation<Number, Number> {
|
|
||||||
public ModuloOperation(Expression<Number> left, Expression<Number> right, SourcePosition start) {
|
|
||||||
super(left, right, start);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) % right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class MultiplicationOperation extends BinaryOperation<Number, Number> {
|
|
||||||
public MultiplicationOperation(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) * right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class NegationOperation extends UnaryOperation<Number> {
|
|
||||||
public NegationOperation(Expression<Number> input, SourcePosition position) {
|
|
||||||
super(input, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return -input.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
|
|
||||||
public NumberAdditionOperation(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) + right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class SubtractionOperation extends BinaryOperation<Number, Number> {
|
|
||||||
public SubtractionOperation(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) - right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +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.legacy.parser.lang.operations;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class UnaryOperation<T> implements Expression<T> {
|
|
||||||
protected final Expression<T> input;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public UnaryOperation(Expression<T> input, SourcePosition position) {
|
|
||||||
this.input = input;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +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.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 static com.dfsek.terra.api.util.MathUtil.EPSILON;
|
|
||||||
|
|
||||||
|
|
||||||
public class EqualsStatement extends BinaryOperation<Object, Boolean> {
|
|
||||||
|
|
||||||
public EqualsStatement(Expression<Object> left, Expression<Object> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
Object leftValue = left.evaluate(implementationArguments, scope);
|
|
||||||
Object rightValue = right.evaluate(implementationArguments, scope);
|
|
||||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
|
||||||
return FastMath.abs(l.doubleValue() - r.doubleValue()) <= EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
return leftValue.equals(rightValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-37
@@ -1,37 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolean> {
|
|
||||||
public GreaterOrEqualsThanStatement(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) >= right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
|
|
||||||
public GreaterThanStatement(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) > right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean> {
|
|
||||||
public LessThanOrEqualsStatement(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) <= right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-38
@@ -1,38 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class LessThanStatement extends BinaryOperation<Number, Boolean> {
|
|
||||||
public LessThanStatement(Expression<Number> left, Expression<Number> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return left.applyDouble(implementationArguments, scope) < right.applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +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.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 static com.dfsek.terra.api.util.MathUtil.EPSILON;
|
|
||||||
|
|
||||||
|
|
||||||
public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
|
|
||||||
public NotEqualsStatement(Expression<Object> left, Expression<Object> right, SourcePosition position) {
|
|
||||||
super(left, right, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
Object leftValue = left.evaluate(implementationArguments, scope);
|
|
||||||
Object rightValue = right.evaluate(implementationArguments, scope);
|
|
||||||
if(leftValue instanceof Number l && rightValue instanceof Number r) {
|
|
||||||
return FastMath.abs(l.doubleValue() - r.doubleValue()) > EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !leftValue.equals(rightValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +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.legacy.parser.lang.variables;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public class BooleanVariable implements Variable<Boolean> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
private Boolean value;
|
|
||||||
|
|
||||||
public BooleanVariable(Boolean value, SourcePosition position) {
|
|
||||||
this.value = value;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(Boolean value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +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.legacy.parser.lang.variables;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public class NumberVariable implements Variable<Number> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
private Number value;
|
|
||||||
|
|
||||||
public NumberVariable(Number value, SourcePosition position) {
|
|
||||||
this.value = value;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(Number value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +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.legacy.parser.lang.variables;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public class StringVariable implements Variable<String> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
public StringVariable(String value, SourcePosition position) {
|
|
||||||
this.value = value;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setValue(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-22
@@ -1,22 +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.legacy.parser.lang.variables;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public interface Variable<T> {
|
|
||||||
T getValue();
|
|
||||||
|
|
||||||
void setValue(T value);
|
|
||||||
|
|
||||||
Type getType();
|
|
||||||
|
|
||||||
SourcePosition getPosition();
|
|
||||||
}
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BoolAssignmentNode extends VariableAssignmentNode<Boolean> {
|
|
||||||
public BoolAssignmentNode(Expression<Boolean> value, SourcePosition position, int index) {
|
|
||||||
super(value, position, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyBoolean(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
boolean val = value.applyBoolean(implementationArguments, scope);
|
|
||||||
scope.setBool(index, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-31
@@ -1,31 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public class NumAssignmentNode extends VariableAssignmentNode<Number> {
|
|
||||||
public NumAssignmentNode(Expression<Number> value, SourcePosition position, int index) {
|
|
||||||
super(value, position, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return applyDouble(implementationArguments, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
double val = value.applyDouble(implementationArguments, scope);
|
|
||||||
scope.setNum(index, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
public class StrAssignmentNode extends VariableAssignmentNode<String> {
|
|
||||||
public StrAssignmentNode(Expression<String> value, SourcePosition position, int index) {
|
|
||||||
super(value, position, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
String val = value.evaluate(implementationArguments, scope);
|
|
||||||
scope.setStr(index, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +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.legacy.parser.lang.variables.assign;
|
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.lang.Expression;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class VariableAssignmentNode<T> implements Expression<T> {
|
|
||||||
protected final Expression<T> value;
|
|
||||||
protected final int index;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
|
|
||||||
public VariableAssignmentNode(Expression<T> value, SourcePosition position, int index) {
|
|
||||||
this.value = value;
|
|
||||||
this.index = index;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
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 BoolVariableReferenceNode extends VariableReferenceNode<Boolean> {
|
|
||||||
public BoolVariableReferenceNode(SourcePosition position, Type type, int index) {
|
|
||||||
super(position, type, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return scope.getBool(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applyBoolean(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return scope.getBool(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
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 NumVariableReferenceNode extends VariableReferenceNode<Number> {
|
|
||||||
public NumVariableReferenceNode(SourcePosition position, Type type, int index) {
|
|
||||||
super(position, type, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return scope.getNum(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double applyDouble(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return scope.getNum(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-18
@@ -1,18 +0,0 @@
|
|||||||
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<String> {
|
|
||||||
public StrVariableReferenceNode(SourcePosition position, Type type, int index) {
|
|
||||||
super(position, type, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return scope.getStr(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-35
@@ -1,35 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class VariableReferenceNode<T> implements Expression<T> {
|
|
||||||
protected final int index;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
public VariableReferenceNode(SourcePosition position, Type type, int index) {
|
|
||||||
this.position = position;
|
|
||||||
this.type = type;
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-162
@@ -1,162 +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.legacy.script;
|
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
|
||||||
import com.dfsek.terra.api.structure.LootTable;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
import com.dfsek.terra.api.util.Rotation;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3Int;
|
|
||||||
import com.dfsek.terra.api.world.WritableWorld;
|
|
||||||
|
|
||||||
|
|
||||||
public class StructureScript implements Structure, Keyed<StructureScript> {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(StructureScript.class);
|
|
||||||
private final Executable executable;
|
|
||||||
private final RegistryKey id;
|
|
||||||
|
|
||||||
private final String profile;
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
public StructureScript(InputStream source, RegistryKey id, Platform platform, Registry<Structure> structureRegistry,
|
|
||||||
Registry<LootTable> lootRegistry,
|
|
||||||
Registry<FunctionBuilder> functionRegistry) {
|
|
||||||
Lexer lexer;
|
|
||||||
try {
|
|
||||||
lexer = new Lexer(IOUtils.toString(source, Charset.defaultCharset()));
|
|
||||||
} catch(IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
Parser parser = new Parser(lexer);
|
|
||||||
this.id = id;
|
|
||||||
this.profile = "terrascript_direct:" + id;
|
|
||||||
|
|
||||||
ScopeBuilder scope = new ScopeBuilder();
|
|
||||||
|
|
||||||
functionRegistry.forEach((key, function) -> scope.registerFunction(key.getID(), function)); // Register registry functions.
|
|
||||||
|
|
||||||
scope
|
|
||||||
.registerFunction("block", new BlockFunctionBuilder(platform))
|
|
||||||
.registerFunction("debugBlock", new BlockFunctionBuilder(platform))
|
|
||||||
.registerFunction("structure", new StructureFunctionBuilder(structureRegistry, platform))
|
|
||||||
.registerFunction("recursions", new RecursionsFunctionBuilder())
|
|
||||||
.registerFunction("setMark", new SetMarkFunctionBuilder())
|
|
||||||
.registerFunction("getMark", new GetMarkFunctionBuilder())
|
|
||||||
.registerFunction("pull", new PullFunctionBuilder(platform))
|
|
||||||
.registerFunction("loot", new LootFunctionBuilder(platform, lootRegistry, this))
|
|
||||||
.registerFunction("entity", new EntityFunctionBuilder(platform))
|
|
||||||
.registerFunction("getBiome", new BiomeFunctionBuilder(platform))
|
|
||||||
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
|
|
||||||
.registerFunction("state", new StateFunctionBuilder(platform))
|
|
||||||
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
|
|
||||||
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getX(),
|
|
||||||
Type.NUMBER))
|
|
||||||
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getY(),
|
|
||||||
Type.NUMBER))
|
|
||||||
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getOrigin().getZ(),
|
|
||||||
Type.NUMBER))
|
|
||||||
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(),
|
|
||||||
Type.STRING))
|
|
||||||
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(),
|
|
||||||
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(
|
|
||||||
(number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))
|
|
||||||
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue())))
|
|
||||||
.registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue())))
|
|
||||||
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue())))
|
|
||||||
.registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue())))
|
|
||||||
.registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue())))
|
|
||||||
.registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue())))
|
|
||||||
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue())))
|
|
||||||
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue())))
|
|
||||||
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue())))
|
|
||||||
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue())))
|
|
||||||
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue())))
|
|
||||||
.registerFunction("max", new BinaryNumberFunctionBuilder(
|
|
||||||
(number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
|
|
||||||
.registerFunction("min", new BinaryNumberFunctionBuilder(
|
|
||||||
(number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
|
|
||||||
|
|
||||||
executable = parser.parse(scope);
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("try")
|
|
||||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) {
|
|
||||||
platform.getProfiler().push(profile);
|
|
||||||
boolean result = execute(new TerraImplementationArguments(location, rotation, random, world, 0));
|
|
||||||
platform.getProfiler().pop(profile);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation, int recursions) {
|
|
||||||
platform.getProfiler().push(profile);
|
|
||||||
boolean result = execute(new TerraImplementationArguments(location, rotation, random, world, recursions));
|
|
||||||
platform.getProfiler().pop(profile);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean execute(TerraImplementationArguments arguments) {
|
|
||||||
try {
|
|
||||||
return executable.execute(arguments);
|
|
||||||
} catch(RuntimeException e) {
|
|
||||||
LOGGER.error("Failed to generate structure at {}", arguments.getOrigin(), e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RegistryKey getRegistryKey() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-73
@@ -1,73 +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.legacy.script;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
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;
|
|
||||||
import com.dfsek.terra.api.world.WritableWorld;
|
|
||||||
|
|
||||||
|
|
||||||
public class TerraImplementationArguments implements ImplementationArguments {
|
|
||||||
private final Rotation rotation;
|
|
||||||
private final Random random;
|
|
||||||
private final WritableWorld world;
|
|
||||||
private final Map<Vector3, String> marks = new HashMap<>();
|
|
||||||
private final int recursions;
|
|
||||||
private final Vector3Int origin;
|
|
||||||
private boolean waterlog = false;
|
|
||||||
|
|
||||||
public TerraImplementationArguments(Vector3Int origin, Rotation rotation, Random random, WritableWorld world, int recursions) {
|
|
||||||
this.rotation = rotation;
|
|
||||||
this.random = random;
|
|
||||||
this.world = world;
|
|
||||||
this.recursions = recursions;
|
|
||||||
this.origin = origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getRecursions() {
|
|
||||||
return recursions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Random getRandom() {
|
|
||||||
return random;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rotation getRotation() {
|
|
||||||
return rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWaterlog() {
|
|
||||||
return waterlog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWaterlog(boolean waterlog) {
|
|
||||||
this.waterlog = waterlog;
|
|
||||||
}
|
|
||||||
|
|
||||||
public WritableWorld getWorld() {
|
|
||||||
return world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector3Int getOrigin() {
|
|
||||||
return origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMark(Vector3 pos, String mark) {
|
|
||||||
marks.put(pos, mark);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMark(Vector3 pos) {
|
|
||||||
return marks.get(pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-62
@@ -1,62 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
|
||||||
|
|
||||||
private final BiFunction<Number, Number, Number> function;
|
|
||||||
|
|
||||||
public BinaryNumberFunctionBuilder(BiFunction<Number, Number, Number> function) {
|
|
||||||
this.function = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<Number> build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new Function<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return function.apply(((Expression<Number>) argumentList.get(0)).evaluate(implementationArguments, scope),
|
|
||||||
((Expression<Number>) argumentList.get(1)).evaluate(implementationArguments, scope));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0 || position == 1) return Type.NUMBER;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-46
@@ -1,46 +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.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.BiomeFunction;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
import com.dfsek.terra.api.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class BiomeFunctionBuilder implements FunctionBuilder<BiomeFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public BiomeFunctionBuilder(Platform platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public BiomeFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new BiomeFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-60
@@ -1,60 +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.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.api.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class BlockFunctionBuilder implements FunctionBuilder<BlockFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public BlockFunctionBuilder(Platform platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public BlockFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
|
|
||||||
Expression<Boolean> booleanReturnable = new BooleanConstant(true, position);
|
|
||||||
if(argumentList.size() == 5) booleanReturnable = (Expression<Boolean>) argumentList.get(4);
|
|
||||||
if(argumentList.get(3) instanceof StringConstant) {
|
|
||||||
return new BlockFunction.Constant((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (StringConstant) argumentList.get(3),
|
|
||||||
booleanReturnable, platform, position);
|
|
||||||
}
|
|
||||||
return new BlockFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), booleanReturnable,
|
|
||||||
platform, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
case 4 -> Type.BOOLEAN;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-39
@@ -1,39 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public CheckBlockFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new CheckBlockFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +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.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.api.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class EntityFunctionBuilder implements FunctionBuilder<EntityFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public EntityFunctionBuilder(Platform platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public EntityFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new EntityFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), platform, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-43
@@ -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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class GetMarkFunctionBuilder implements FunctionBuilder<GetMarkFunction> {
|
|
||||||
|
|
||||||
public GetMarkFunctionBuilder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public GetMarkFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new GetMarkFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-55
@@ -1,55 +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.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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.registry.Registry;
|
|
||||||
import com.dfsek.terra.api.structure.LootTable;
|
|
||||||
|
|
||||||
|
|
||||||
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
private final Registry<LootTable> registry;
|
|
||||||
private final StructureScript script;
|
|
||||||
|
|
||||||
public LootFunctionBuilder(Platform platform, Registry<LootTable> registry, StructureScript script) {
|
|
||||||
this.platform = platform;
|
|
||||||
this.registry = registry;
|
|
||||||
this.script = script;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public LootFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new LootFunction(registry, (Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), platform, position,
|
|
||||||
script);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +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.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.api.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class PullFunctionBuilder implements FunctionBuilder<PullFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public PullFunctionBuilder(Platform platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public PullFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new PullFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), platform, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public RandomFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new RandomFunction((Expression<Number>) argumentList.get(0), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0) return Type.NUMBER;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-34
@@ -1,34 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class RecursionsFunctionBuilder implements FunctionBuilder<RecursionsFunction> {
|
|
||||||
@Override
|
|
||||||
public RecursionsFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new RecursionsFunction(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +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.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.SetMarkFunction;
|
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.SourcePosition;
|
|
||||||
|
|
||||||
|
|
||||||
public class SetMarkFunctionBuilder implements FunctionBuilder<SetMarkFunction> {
|
|
||||||
|
|
||||||
public SetMarkFunctionBuilder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public SetMarkFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new SetMarkFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-49
@@ -1,49 +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.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.api.Platform;
|
|
||||||
|
|
||||||
|
|
||||||
public class StateFunctionBuilder implements FunctionBuilder<StateFunction> {
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public StateFunctionBuilder(Platform platform) {
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public StateFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
|
|
||||||
return new StateFunction((Expression<Number>) argumentList.get(0), (Expression<Number>) argumentList.get(1),
|
|
||||||
(Expression<Number>) argumentList.get(2), (Expression<String>) argumentList.get(3), position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
case 3 -> Type.STRING;
|
|
||||||
default -> null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-56
@@ -1,56 +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.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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.registry.Registry;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
|
|
||||||
|
|
||||||
public class StructureFunctionBuilder implements FunctionBuilder<StructureFunction> {
|
|
||||||
private final Registry<Structure> registry;
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public StructureFunctionBuilder(Registry<Structure> registry, Platform platform) {
|
|
||||||
this.registry = registry;
|
|
||||||
this.platform = platform;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public StructureFunction build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
if(argumentList.size() < 5) throw new ParseException("Expected rotations", position);
|
|
||||||
|
|
||||||
return new StructureFunction((Expression<Number>) argumentList.remove(0), (Expression<Number>) argumentList.remove(0),
|
|
||||||
(Expression<Number>) argumentList.remove(0), (Expression<String>) argumentList.remove(0),
|
|
||||||
argumentList.stream().map(item -> ((Expression<String>) item)).collect(Collectors.toList()), registry,
|
|
||||||
position, platform);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
return switch(position) {
|
|
||||||
case 0, 1, 2 -> Type.NUMBER;
|
|
||||||
default -> Type.STRING;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-64
@@ -1,64 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
|
||||||
|
|
||||||
private final BiConsumer<Boolean, TerraImplementationArguments> function;
|
|
||||||
|
|
||||||
public UnaryBooleanFunctionBuilder(BiConsumer<Boolean, TerraImplementationArguments> function) {
|
|
||||||
this.function = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<Void> build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new Function<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
function.accept(((Expression<Boolean>) argumentList.get(0)).evaluate(implementationArguments, scope),
|
|
||||||
(TerraImplementationArguments) implementationArguments);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0) return Type.BOOLEAN;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-60
@@ -1,60 +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.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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
|
||||||
|
|
||||||
private final java.util.function.Function<Number, Number> function;
|
|
||||||
|
|
||||||
public UnaryNumberFunctionBuilder(java.util.function.Function<Number, Number> function) {
|
|
||||||
this.function = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<Number> build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new Function<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return function.apply(((Expression<Number>) argumentList.get(0)).evaluate(implementationArguments, scope));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0) return Type.NUMBER;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-61
@@ -1,61 +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.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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
|
||||||
|
|
||||||
private final java.util.function.Consumer<String> function;
|
|
||||||
|
|
||||||
public UnaryStringFunctionBuilder(java.util.function.Consumer<String> function) {
|
|
||||||
this.function = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<Void> build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new Function<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
function.accept(((Expression<String>) argumentList.get(0)).evaluate(implementationArguments, scope));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0) return Type.STRING;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-61
@@ -1,61 +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.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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
|
|
||||||
private final java.util.function.Function<TerraImplementationArguments, T> function;
|
|
||||||
private final Type type;
|
|
||||||
|
|
||||||
public ZeroArgFunctionBuilder(java.util.function.Function<TerraImplementationArguments, T> function, Type type) {
|
|
||||||
this.function = function;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Function<T> build(List<Expression<?>> argumentList, SourcePosition position) {
|
|
||||||
return new Function<>() {
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return function.apply((TerraImplementationArguments) implementationArguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int argNumber() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type getArgument(int position) {
|
|
||||||
if(position == 0) return type;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-66
@@ -1,66 +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.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.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
|
||||||
|
|
||||||
|
|
||||||
public class BiomeFunction implements Function<String> {
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
|
|
||||||
public BiomeFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, SourcePosition position) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
BiomeProvider grid = arguments.getWorld().getBiomeProvider();
|
|
||||||
|
|
||||||
return grid.getBiome(arguments.getOrigin()
|
|
||||||
.toVector3()
|
|
||||||
.mutable()
|
|
||||||
.add(Vector3.of(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope).intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ()))).immutable(), arguments.getWorld().getSeed()).getID();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-107
@@ -1,107 +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.legacy.script.functions;
|
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class BlockFunction implements Function<Void> {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(BlockFunction.class);
|
|
||||||
protected final Expression<Number> x, y, z;
|
|
||||||
protected final Expression<String> blockData;
|
|
||||||
protected final Platform platform;
|
|
||||||
private final Map<String, BlockState> data = new HashMap<>();
|
|
||||||
private final Expression<Boolean> overwrite;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public BlockFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> blockData,
|
|
||||||
Expression<Boolean> overwrite, Platform platform, SourcePosition position) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.blockData = blockData;
|
|
||||||
this.overwrite = overwrite;
|
|
||||||
this.platform = platform;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
BlockState rot = getBlockState(implementationArguments, scope);
|
|
||||||
setBlock(implementationArguments, scope, arguments, rot);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBlock(ImplementationArguments implementationArguments, Scope scope,
|
|
||||||
TerraImplementationArguments arguments, BlockState rot) {
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
try {
|
|
||||||
Vector3.Mutable set = Vector3.of(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin());
|
|
||||||
BlockState current = arguments.getWorld().getBlockState(set);
|
|
||||||
if(overwrite.evaluate(implementationArguments, scope) || current.isAir()) {
|
|
||||||
arguments.getWorld().setBlockState(set, rot);
|
|
||||||
}
|
|
||||||
} catch(RuntimeException e) {
|
|
||||||
logger.error("Failed to place block at location {}", arguments.getOrigin(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) {
|
|
||||||
return data.computeIfAbsent(blockData.evaluate(arguments, scope), platform.getWorldHandle()::createBlockState);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static class Constant extends BlockFunction {
|
|
||||||
private final BlockState state;
|
|
||||||
|
|
||||||
public Constant(Expression<Number> x, Expression<Number> y, Expression<Number> z, StringConstant blockData,
|
|
||||||
Expression<Boolean> overwrite, Platform platform, SourcePosition position) {
|
|
||||||
super(x, y, z, blockData, overwrite, platform, position);
|
|
||||||
this.state = platform.getWorldHandle().createBlockState(blockData.getConstant());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected BlockState getBlockState(ImplementationArguments arguments, Scope scope) {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-66
@@ -1,66 +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.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.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class CheckBlockFunction implements Function<String> {
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public CheckBlockFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, SourcePosition position) {
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
String data = arguments.getWorld()
|
|
||||||
.getBlockState(arguments.getOrigin()
|
|
||||||
.toVector3()
|
|
||||||
.mutable()
|
|
||||||
.add(Vector3.of(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope)
|
|
||||||
.doubleValue(), FastMath.roundToInt(xz.getZ()))))
|
|
||||||
.getAsString();
|
|
||||||
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
|
|
||||||
else return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-72
@@ -1,72 +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.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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.entity.Entity;
|
|
||||||
import com.dfsek.terra.api.entity.EntityType;
|
|
||||||
import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class EntityFunction implements Function<Void> {
|
|
||||||
private final EntityType data;
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Platform platform;
|
|
||||||
|
|
||||||
public EntityFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> data, Platform platform,
|
|
||||||
SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
this.platform = platform;
|
|
||||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
|
|
||||||
|
|
||||||
this.data = platform.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
Entity entity = arguments.getWorld().spawnEntity(Vector3.of(xz.getX(), y.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
xz.getZ())
|
|
||||||
.mutable()
|
|
||||||
.add(arguments.getOrigin())
|
|
||||||
.add(0.5, 0, 0.5)
|
|
||||||
.immutable(), data);
|
|
||||||
platform.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getPack(), entity));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-60
@@ -1,60 +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.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.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class GetMarkFunction implements Function<String> {
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public GetMarkFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
String mark = arguments.getMark(Vector3.of(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(
|
|
||||||
y.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
FastMath.floorToInt(xz.getZ()))
|
|
||||||
.mutable()
|
|
||||||
.add(arguments.getOrigin())
|
|
||||||
.immutable());
|
|
||||||
return mark == null ? "" : mark;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.STRING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-109
@@ -1,109 +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.legacy.script.functions;
|
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
|
||||||
import com.dfsek.terra.api.block.entity.Container;
|
|
||||||
import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent;
|
|
||||||
import com.dfsek.terra.api.registry.Registry;
|
|
||||||
import com.dfsek.terra.api.registry.key.RegistryKey;
|
|
||||||
import com.dfsek.terra.api.structure.LootTable;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class LootFunction implements Function<Void> {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(LootFunction.class);
|
|
||||||
private final Registry<LootTable> registry;
|
|
||||||
private final Expression<String> data;
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Platform platform;
|
|
||||||
private final StructureScript script;
|
|
||||||
|
|
||||||
public LootFunction(Registry<LootTable> registry, Expression<Number> x, Expression<Number> y, Expression<Number> z,
|
|
||||||
Expression<String> data, Platform platform, SourcePosition position, StructureScript script) {
|
|
||||||
this.registry = registry;
|
|
||||||
this.position = position;
|
|
||||||
this.data = data;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.platform = platform;
|
|
||||||
this.script = script;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
String id = data.evaluate(implementationArguments, scope);
|
|
||||||
|
|
||||||
|
|
||||||
registry.get(RegistryKey.parse(id))
|
|
||||||
.ifPresentOrElse(table -> {
|
|
||||||
Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope)
|
|
||||||
.intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
|
||||||
|
|
||||||
try {
|
|
||||||
BlockEntity data = arguments.getWorld().getBlockEntity(apply);
|
|
||||||
if(!(data instanceof Container container)) {
|
|
||||||
LOGGER.error("Failed to place loot at {}; block {} is not a container",
|
|
||||||
apply, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LootPopulateEvent event = new LootPopulateEvent(container, table,
|
|
||||||
arguments.getWorld().getPack(), script);
|
|
||||||
platform.getEventManager().callEvent(event);
|
|
||||||
if(event.isCancelled()) return;
|
|
||||||
|
|
||||||
event.getTable().fillInventory(container.getInventory(),
|
|
||||||
new Random(apply.hashCode()));
|
|
||||||
data.update(false);
|
|
||||||
} catch(Exception e) {
|
|
||||||
LOGGER.error("Could not apply loot at {}", apply, e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() -> LOGGER.error("No such loot table {}", id));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-72
@@ -1,72 +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.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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.block.state.BlockState;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class PullFunction implements Function<Void> {
|
|
||||||
private final BlockState data;
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public PullFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> data, Platform platform,
|
|
||||||
SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
|
|
||||||
|
|
||||||
this.data = platform.getWorldHandle().createBlockState(((ConstantExpression<String>) data).getConstant());
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
Vector3.Mutable mutable = Vector3.of(FastMath.roundToInt(xz.getX()), y.evaluate(implementationArguments, scope).intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin());
|
|
||||||
while(mutable.getY() > arguments.getWorld().getMinHeight()) {
|
|
||||||
if(!arguments.getWorld().getBlockState(mutable).isAir()) {
|
|
||||||
arguments.getWorld().setBlockState(mutable, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mutable.subtract(0, 1, 0);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-44
@@ -1,44 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class RandomFunction implements Function<Integer> {
|
|
||||||
private final Expression<Number> numberReturnable;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public RandomFunction(Expression<Number> numberReturnable, SourcePosition position) {
|
|
||||||
this.numberReturnable = numberReturnable;
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(
|
|
||||||
numberReturnable.evaluate(implementationArguments, scope).intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-39
@@ -1,39 +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.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;
|
|
||||||
|
|
||||||
|
|
||||||
public class RecursionsFunction implements Function<Number> {
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public RecursionsFunction(SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.NUMBER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Number evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
return ((TerraImplementationArguments) implementationArguments).getRecursions();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-63
@@ -1,63 +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.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.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class SetMarkFunction implements Function<Void> {
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Expression<String> mark;
|
|
||||||
|
|
||||||
public SetMarkFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> mark,
|
|
||||||
SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
this.mark = mark;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
arguments.setMark(Vector3.of(FastMath.floorToInt(xz.getX()),
|
|
||||||
FastMath.floorToInt(
|
|
||||||
y.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
FastMath.floorToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(),
|
|
||||||
mark.evaluate(implementationArguments, scope));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-72
@@ -1,72 +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.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.api.block.entity.BlockEntity;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
public class StateFunction implements Function<Void> {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(StateFunction.class);
|
|
||||||
private final Expression<String> data;
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
|
|
||||||
public StateFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> data,
|
|
||||||
SourcePosition position) {
|
|
||||||
this.position = position;
|
|
||||||
this.data = data;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
Vector3 origin = Vector3.of(FastMath.roundToInt(xz.getX()), y.evaluate(implementationArguments, scope).intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
|
|
||||||
try {
|
|
||||||
BlockEntity state = arguments.getWorld().getBlockEntity(origin);
|
|
||||||
state.applyState(data.evaluate(implementationArguments, scope));
|
|
||||||
state.update(false);
|
|
||||||
} catch(Exception e) {
|
|
||||||
LOGGER.warn("Could not apply BlockState at {}", origin, e);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.VOID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-107
@@ -1,107 +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.legacy.script.functions;
|
|
||||||
|
|
||||||
import net.jafama.FastMath;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
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.api.Platform;
|
|
||||||
import com.dfsek.terra.api.registry.Registry;
|
|
||||||
import com.dfsek.terra.api.structure.Structure;
|
|
||||||
import com.dfsek.terra.api.util.Rotation;
|
|
||||||
import com.dfsek.terra.api.util.RotationUtil;
|
|
||||||
import com.dfsek.terra.api.util.vector.Vector2;
|
|
||||||
|
|
||||||
|
|
||||||
public class StructureFunction implements Function<Boolean> {
|
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(StructureFunction.class);
|
|
||||||
private final Registry<Structure> registry;
|
|
||||||
private final Expression<String> id;
|
|
||||||
private final Expression<Number> x, y, z;
|
|
||||||
private final SourcePosition position;
|
|
||||||
private final Platform platform;
|
|
||||||
private final List<Expression<String>> rotations;
|
|
||||||
|
|
||||||
public StructureFunction(Expression<Number> x, Expression<Number> y, Expression<Number> z, Expression<String> id,
|
|
||||||
List<Expression<String>> rotations, Registry<Structure> registry, SourcePosition position, Platform platform) {
|
|
||||||
this.registry = registry;
|
|
||||||
this.id = id;
|
|
||||||
this.position = position;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
this.platform = platform;
|
|
||||||
this.rotations = rotations;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Type returnType() {
|
|
||||||
return Type.BOOLEAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate(ImplementationArguments implementationArguments, Scope scope) {
|
|
||||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
|
||||||
|
|
||||||
if(arguments.getRecursions() > platform.getTerraConfig().getMaxRecursion())
|
|
||||||
throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions());
|
|
||||||
|
|
||||||
Vector2 xz = RotationUtil.rotateVector(Vector2.of(x.evaluate(implementationArguments, scope).doubleValue(),
|
|
||||||
z.evaluate(implementationArguments, scope).doubleValue()),
|
|
||||||
arguments.getRotation());
|
|
||||||
|
|
||||||
|
|
||||||
String app = id.evaluate(implementationArguments, scope);
|
|
||||||
return registry.getByID(app).map(script -> {
|
|
||||||
Rotation rotation1;
|
|
||||||
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).evaluate(implementationArguments, scope);
|
|
||||||
try {
|
|
||||||
rotation1 = Rotation.valueOf(rotString);
|
|
||||||
} catch(IllegalArgumentException e) {
|
|
||||||
LOGGER.warn("Invalid rotation {}", rotString);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(script instanceof StructureScript structureScript) {
|
|
||||||
return structureScript.generate(arguments.getOrigin(),
|
|
||||||
arguments.getWorld()
|
|
||||||
.buffer(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope).intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())),
|
|
||||||
arguments.getRandom(),
|
|
||||||
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
|
|
||||||
}
|
|
||||||
return script.generate(arguments.getOrigin(),
|
|
||||||
arguments.getWorld()
|
|
||||||
.buffer(FastMath.roundToInt(xz.getX()),
|
|
||||||
y.evaluate(implementationArguments, scope).intValue(),
|
|
||||||
FastMath.roundToInt(xz.getZ())),
|
|
||||||
arguments.getRandom(),
|
|
||||||
arguments.getRotation().rotate(rotation1));
|
|
||||||
}).orElseGet(() -> {
|
|
||||||
LOGGER.error("No such structure {}", app);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourcePosition getPosition() {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+4
-9
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
package com.dfsek.terra.addons.terrascript.lexer;
|
package com.dfsek.terra.addons.terrascript.lexer;
|
||||||
|
|
||||||
|
import com.dfsek.terra.addons.terrascript.parser.ParseException;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -17,7 +19,6 @@ import java.util.Set;
|
|||||||
import com.dfsek.terra.addons.terrascript.exception.lexer.EOFException;
|
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.FormatException;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.lexer.TokenizerException;
|
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.Token.TokenType;
|
||||||
|
|
||||||
|
|
||||||
@@ -190,14 +191,8 @@ public class Lexer {
|
|||||||
if(tokenString.equals("false"))
|
if(tokenString.equals("false"))
|
||||||
return new Token(tokenString, TokenType.BOOLEAN, position);
|
return new Token(tokenString, TokenType.BOOLEAN, position);
|
||||||
|
|
||||||
if(tokenString.equals("num"))
|
if(tokenString.equals("var"))
|
||||||
return new Token(tokenString, TokenType.TYPE_NUMBER, position);
|
return new Token(tokenString, TokenType.VARIABLE, position);
|
||||||
if(tokenString.equals("str"))
|
|
||||||
return new Token(tokenString, TokenType.TYPE_STRING, position);
|
|
||||||
if(tokenString.equals("bool"))
|
|
||||||
return new Token(tokenString, TokenType.TYPE_BOOLEAN, position);
|
|
||||||
if(tokenString.equals("void"))
|
|
||||||
return new Token(tokenString, TokenType.TYPE_VOID, position);
|
|
||||||
|
|
||||||
if(tokenString.equals("fun"))
|
if(tokenString.equals("fun"))
|
||||||
return new Token(tokenString, TokenType.FUNCTION, position);
|
return new Token(tokenString, TokenType.FUNCTION, position);
|
||||||
|
|||||||
+2
-14
@@ -159,21 +159,9 @@ public class Token {
|
|||||||
*/
|
*/
|
||||||
BOOLEAN_AND,
|
BOOLEAN_AND,
|
||||||
/**
|
/**
|
||||||
* Numeric variable declaration
|
* Variable declaration
|
||||||
*/
|
*/
|
||||||
TYPE_NUMBER,
|
VARIABLE,
|
||||||
/**
|
|
||||||
* String variable declaration
|
|
||||||
*/
|
|
||||||
TYPE_STRING,
|
|
||||||
/**
|
|
||||||
* Boolean variable declaration
|
|
||||||
*/
|
|
||||||
TYPE_BOOLEAN,
|
|
||||||
/**
|
|
||||||
* Void type declaration
|
|
||||||
*/
|
|
||||||
TYPE_VOID,
|
|
||||||
/**
|
/**
|
||||||
* Function declaration
|
* Function declaration
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
* reference the LICENSE file in this module's root directory.
|
* reference the LICENSE file in this module's root directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.dfsek.terra.addons.terrascript.legacy.parser.exceptions;
|
package com.dfsek.terra.addons.terrascript.parser;
|
||||||
|
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
|
|
||||||
+19
-14
@@ -8,12 +8,11 @@ import java.util.Optional;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.dfsek.terra.addons.terrascript.Type;
|
import com.dfsek.terra.addons.terrascript.Type;
|
||||||
|
import com.dfsek.terra.addons.terrascript.Type.TypeException;
|
||||||
import com.dfsek.terra.addons.terrascript.ast.Expr;
|
import com.dfsek.terra.addons.terrascript.ast.Expr;
|
||||||
import com.dfsek.terra.addons.terrascript.ast.Expr.Variable;
|
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;
|
||||||
import com.dfsek.terra.addons.terrascript.ast.Stmt.Block;
|
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.SourcePosition;
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.Token;
|
import com.dfsek.terra.addons.terrascript.lexer.Token;
|
||||||
import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType;
|
import com.dfsek.terra.addons.terrascript.lexer.Token.TokenType;
|
||||||
@@ -77,7 +76,7 @@ public class Parser {
|
|||||||
return switch(current().type()) {
|
return switch(current().type()) {
|
||||||
case BLOCK_BEGIN -> block();
|
case BLOCK_BEGIN -> block();
|
||||||
case FUNCTION -> functionDeclaration();
|
case FUNCTION -> functionDeclaration();
|
||||||
case TYPE_STRING, TYPE_BOOLEAN, TYPE_NUMBER -> variableDeclaration();
|
case VARIABLE -> variableDeclaration();
|
||||||
case RETURN -> returnStmt();
|
case RETURN -> returnStmt();
|
||||||
case IF_STATEMENT -> ifStmt();
|
case IF_STATEMENT -> ifStmt();
|
||||||
case FOR_LOOP -> forLoop();
|
case FOR_LOOP -> forLoop();
|
||||||
@@ -104,7 +103,7 @@ public class Parser {
|
|||||||
paramToken.position());
|
paramToken.position());
|
||||||
|
|
||||||
consume("Expected type declaration after parameter name. Example: '" + paramId + ": <type>'", TokenType.COLON);
|
consume("Expected type declaration after parameter name. Example: '" + paramId + ": <type>'", TokenType.COLON);
|
||||||
Type paramType = ParserUtil.getVariableReturnType(consumeUnchecked());
|
Type paramType = typeExpr();
|
||||||
|
|
||||||
params.add(Pair.of(paramId, paramType));
|
params.add(Pair.of(paramId, paramType));
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ public class Parser {
|
|||||||
TokenType.CLOSE_PAREN);
|
TokenType.CLOSE_PAREN);
|
||||||
if(current().isType(TokenType.COLON)) {
|
if(current().isType(TokenType.COLON)) {
|
||||||
consumeUnchecked();
|
consumeUnchecked();
|
||||||
funcReturn = ParserUtil.getVariableReturnType(consumeUnchecked());
|
funcReturn = typeExpr();
|
||||||
}
|
}
|
||||||
|
|
||||||
Stmt.Block body = blockOrSingleStatement();
|
Stmt.Block body = blockOrSingleStatement();
|
||||||
@@ -127,22 +126,26 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Stmt.VariableDeclaration variableDeclaration() {
|
private Stmt.VariableDeclaration variableDeclaration() {
|
||||||
Token typeToken = consumeUnchecked();
|
SourcePosition position = consume("Expected 'var' keyword at start of variable declaration", TokenType.VARIABLE).position();
|
||||||
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();
|
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);
|
consume("Expected ':' after variable name", TokenType.COLON);
|
||||||
|
Type type = typeExpr();
|
||||||
|
consume("Expected '=' following variable type declaration", TokenType.ASSIGNMENT);
|
||||||
Expr expr = expression();
|
Expr expr = expression();
|
||||||
consumeStatementEnd("variable declaration");
|
consumeStatementEnd("variable declaration");
|
||||||
|
|
||||||
return new Stmt.VariableDeclaration(type, id, expr, position);
|
return new Stmt.VariableDeclaration(type, id, expr, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Type typeExpr() {
|
||||||
|
Token typeToken = consume("Expected " + TokenType.IDENTIFIER + " specified as variable type", TokenType.IDENTIFIER);
|
||||||
|
try {
|
||||||
|
return Type.fromString(typeToken.lexeme());
|
||||||
|
} catch(TypeException e) {
|
||||||
|
throw new ParseException("Failed to parse type expression", typeToken.position());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Stmt.Return returnStmt() {
|
private Stmt.Return returnStmt() {
|
||||||
SourcePosition position = consume("Expected 'return' keyword, found '" + current().lexeme() + "'", TokenType.RETURN).position();
|
SourcePosition position = consume("Expected 'return' keyword, found '" + current().lexeme() + "'", TokenType.RETURN).position();
|
||||||
Expr value = new Expr.Void(position);
|
Expr value = new Expr.Void(position);
|
||||||
@@ -371,4 +374,6 @@ public class Parser {
|
|||||||
private Expr variable(Token identifier) {
|
private Expr variable(Token identifier) {
|
||||||
return new Expr.Variable(identifier.lexeme(), identifier.position());
|
return new Expr.Variable(identifier.lexeme(), identifier.position());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -25,7 +25,7 @@ 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.VariableDeclaration;
|
||||||
import com.dfsek.terra.addons.terrascript.ast.Stmt.While;
|
import com.dfsek.terra.addons.terrascript.ast.Stmt.While;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException;
|
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException;
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException;
|
import com.dfsek.terra.addons.terrascript.parser.ParseException;
|
||||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -19,7 +19,7 @@ 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;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.IdentifierAlreadyDeclaredException;
|
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.IdentifierAlreadyDeclaredException;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException;
|
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.UndefinedReferenceException;
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException;
|
import com.dfsek.terra.addons.terrascript.parser.ParseException;
|
||||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+23
-23
@@ -21,7 +21,7 @@ import com.dfsek.terra.addons.terrascript.ast.TypedExpr;
|
|||||||
import com.dfsek.terra.addons.terrascript.ast.TypedStmt;
|
import com.dfsek.terra.addons.terrascript.ast.TypedStmt;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidFunctionDeclarationException;
|
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidFunctionDeclarationException;
|
||||||
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidTypeException;
|
import com.dfsek.terra.addons.terrascript.exception.semanticanalysis.InvalidTypeException;
|
||||||
import com.dfsek.terra.addons.terrascript.legacy.parser.exceptions.ParseException;
|
import com.dfsek.terra.addons.terrascript.parser.ParseException;
|
||||||
import com.dfsek.terra.api.util.generic.pair.Pair;
|
import com.dfsek.terra.api.util.generic.pair.Pair;
|
||||||
|
|
||||||
import static com.dfsek.terra.addons.terrascript.util.OrdinalUtil.ordinalOf;
|
import static com.dfsek.terra.addons.terrascript.util.OrdinalUtil.ordinalOf;
|
||||||
@@ -47,31 +47,31 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
|
|
||||||
Type type = switch(expr.operator) {
|
Type type = switch(expr.operator) {
|
||||||
case BOOLEAN_OR, BOOLEAN_AND -> {
|
case BOOLEAN_OR, BOOLEAN_AND -> {
|
||||||
if(leftType != Type.BOOLEAN || rightType != Type.BOOLEAN)
|
if(!leftType.typeOf(Type.BOOLEAN) || !rightType.typeOf(Type.BOOLEAN))
|
||||||
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.NUMBER + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.BOOLEAN + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
||||||
yield Type.BOOLEAN;
|
yield Type.BOOLEAN;
|
||||||
}
|
}
|
||||||
case EQUALS, NOT_EQUALS -> {
|
case EQUALS, NOT_EQUALS -> {
|
||||||
if(leftType != rightType) errorHandler.add(new InvalidTypeException("Both operands of equality operator (==) must be of the same type, found mismatched types '" + leftType + "' and '" + rightType + "'", expr.position));
|
if(!leftType.typeOf(rightType)) errorHandler.add(new InvalidTypeException("Both operands of equality operator (==) must be of the same type, found mismatched types '" + leftType + "' and '" + rightType + "'", expr.position));
|
||||||
yield Type.BOOLEAN;
|
yield Type.BOOLEAN;
|
||||||
}
|
}
|
||||||
case GREATER, GREATER_EQUALS, LESS, LESS_EQUALS -> {
|
case GREATER, GREATER_EQUALS, LESS, LESS_EQUALS -> {
|
||||||
if(leftType != Type.NUMBER || rightType != Type.NUMBER)
|
if(!leftType.typeOf(Type.NUMBER) || !rightType.typeOf(Type.NUMBER))
|
||||||
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.NUMBER + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.NUMBER + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
||||||
yield Type.BOOLEAN;
|
yield Type.BOOLEAN;
|
||||||
}
|
}
|
||||||
case ADD -> {
|
case ADD -> {
|
||||||
if(leftType == Type.NUMBER && rightType == Type.NUMBER) {
|
if(leftType.typeOf(Type.NUMBER) && rightType.typeOf(Type.NUMBER)) {
|
||||||
yield Type.NUMBER;
|
yield Type.NUMBER;
|
||||||
}
|
}
|
||||||
if(leftType == Type.STRING || rightType == Type.STRING) {
|
if(leftType.typeOf(Type.STRING) || rightType.typeOf(Type.STRING)) {
|
||||||
yield Type.STRING;
|
yield Type.STRING;
|
||||||
}
|
}
|
||||||
errorHandler.add(new RuntimeException("Addition operands must be either both numbers, or one of type string"));
|
errorHandler.add(new RuntimeException("Addition operands must be either both of type '" + Type.NUMBER + "', or one of type '" + Type.STRING + "'"));
|
||||||
yield Type.VOID;
|
yield Type.VOID;
|
||||||
}
|
}
|
||||||
case SUBTRACT, MULTIPLY, DIVIDE, MODULO -> {
|
case SUBTRACT, MULTIPLY, DIVIDE, MODULO -> {
|
||||||
if(leftType != Type.NUMBER || rightType != Type.NUMBER)
|
if(!leftType.typeOf(Type.NUMBER) || !rightType.typeOf(Type.NUMBER))
|
||||||
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.NUMBER + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
errorHandler.add(new InvalidTypeException("Both operands of '" + expr.operator + "' operator must be of type '" + Type.NUMBER + "', found types '" + leftType + "' and '" + rightType + "'", expr.position));
|
||||||
yield Type.NUMBER;
|
yield Type.NUMBER;
|
||||||
}
|
}
|
||||||
@@ -94,11 +94,11 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
TypedExpr right = expr.operand.accept(this);
|
TypedExpr right = expr.operand.accept(this);
|
||||||
Type type = switch(expr.operator) {
|
Type type = switch(expr.operator) {
|
||||||
case NOT -> {
|
case NOT -> {
|
||||||
if(right.type != Type.BOOLEAN) throw new RuntimeException();
|
if(!right.type.typeOf(Type.BOOLEAN)) throw new RuntimeException();
|
||||||
yield Type.BOOLEAN;
|
yield Type.BOOLEAN;
|
||||||
}
|
}
|
||||||
case NEGATE -> {
|
case NEGATE -> {
|
||||||
if(right.type != Type.NUMBER) throw new RuntimeException();
|
if(!right.type.typeOf(Type.NUMBER)) throw new RuntimeException();
|
||||||
yield Type.NUMBER;
|
yield Type.NUMBER;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -122,7 +122,7 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
for(int i = 0; i < parameters.size(); i++) {
|
for(int i = 0; i < parameters.size(); i++) {
|
||||||
Type expectedType = parameters.get(i);
|
Type expectedType = parameters.get(i);
|
||||||
Type providedType = arguments.get(i).type;
|
Type providedType = arguments.get(i).type;
|
||||||
if(expectedType != providedType)
|
if(!expectedType.typeOf(providedType))
|
||||||
errorHandler.add(new InvalidTypeException(
|
errorHandler.add(new InvalidTypeException(
|
||||||
ordinalOf(i + 1) + " argument provided for function '" + id + "' expects type " + expectedType + ", found " +
|
ordinalOf(i + 1) + " argument provided for function '" + id + "' expects type " + expectedType + ", found " +
|
||||||
providedType + " instead", expr.position));
|
providedType + " instead", expr.position));
|
||||||
@@ -142,9 +142,9 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
TypedExpr right = expr.rValue.accept(this);
|
TypedExpr right = expr.rValue.accept(this);
|
||||||
Type expected = left.type;
|
Type expected = left.type;
|
||||||
String id = expr.lValue.identifier;
|
String id = expr.lValue.identifier;
|
||||||
if(right.type != expected)
|
if(!right.type.typeOf(expected))
|
||||||
errorHandler.add(new InvalidTypeException(
|
errorHandler.add(new InvalidTypeException(
|
||||||
"Cannot assign variable '" + id + "' to type " + right + ", '" + id + "' is declared with type " + expected,
|
"Cannot assign variable '" + id + "' to value of type " + right.type + ", '" + id + "' is declared with type " + expected,
|
||||||
expr.position));
|
expr.position));
|
||||||
return new TypedExpr.Assignment(left, right, right.type);
|
return new TypedExpr.Assignment(left, right, right.type);
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,7 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
public TypedStmt visitFunctionDeclarationStmt(Stmt.FunctionDeclaration stmt) {
|
public TypedStmt visitFunctionDeclarationStmt(Stmt.FunctionDeclaration stmt) {
|
||||||
TypedStmt.Block body = new TypedStmt.Block(stmt.body.statements.stream().map(s -> s.accept(this)).toList());
|
TypedStmt.Block body = new TypedStmt.Block(stmt.body.statements.stream().map(s -> s.accept(this)).toList());
|
||||||
boolean hasReturn = alwaysReturns(body, stmt);
|
boolean hasReturn = alwaysReturns(body, stmt);
|
||||||
if(stmt.returnType != Type.VOID && !hasReturn) {
|
if(!stmt.returnType.typeOf(Type.VOID) && !hasReturn) {
|
||||||
errorHandler.add(
|
errorHandler.add(
|
||||||
new InvalidFunctionDeclarationException("Function body for '" + stmt.identifier + "' does not contain return statement",
|
new InvalidFunctionDeclarationException("Function body for '" + stmt.identifier + "' does not contain return statement",
|
||||||
stmt.position));
|
stmt.position));
|
||||||
@@ -178,7 +178,7 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
|
|
||||||
private boolean alwaysReturns(TypedStmt stmt, Stmt.FunctionDeclaration function) {
|
private boolean alwaysReturns(TypedStmt stmt, Stmt.FunctionDeclaration function) {
|
||||||
if(stmt instanceof TypedStmt.Return ret) {
|
if(stmt instanceof TypedStmt.Return ret) {
|
||||||
if(ret.value.type != function.returnType)
|
if(!ret.value.type.typeOf(function.returnType))
|
||||||
errorHandler.add(new InvalidTypeException(
|
errorHandler.add(new InvalidTypeException(
|
||||||
"Return statement must match function's return type. Function '" + function.identifier + "' expects " +
|
"Return statement must match function's return type. Function '" + function.identifier + "' expects " +
|
||||||
function.returnType + ", found " + ret.value.type + " instead", function.position));
|
function.returnType + ", found " + ret.value.type + " instead", function.position));
|
||||||
@@ -196,10 +196,10 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
@Override
|
@Override
|
||||||
public TypedStmt visitVariableDeclarationStmt(Stmt.VariableDeclaration stmt) {
|
public TypedStmt visitVariableDeclarationStmt(Stmt.VariableDeclaration stmt) {
|
||||||
TypedExpr value = stmt.value.accept(this);
|
TypedExpr value = stmt.value.accept(this);
|
||||||
if(stmt.type != value.type)
|
if(!stmt.type.typeOf(value.type))
|
||||||
errorHandler.add(new InvalidTypeException(
|
errorHandler.add(new InvalidTypeException(
|
||||||
"Type " + stmt.type + " declared for variable '" + stmt.identifier + "' does not match assigned value type " +
|
"Type of value assigned to variable '" + stmt.identifier + "' does not match variable's declared type. Expected type '" +
|
||||||
value.type, stmt.position));
|
stmt.type + "', found '" + value.type +"' instead", stmt.position));
|
||||||
return new TypedStmt.VariableDeclaration(stmt.type, stmt.identifier, value);
|
return new TypedStmt.VariableDeclaration(stmt.type, stmt.identifier, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,12 +211,12 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
@Override
|
@Override
|
||||||
public TypedStmt visitIfStmt(Stmt.If stmt) {
|
public TypedStmt visitIfStmt(Stmt.If stmt) {
|
||||||
TypedExpr condition = stmt.condition.accept(this);
|
TypedExpr condition = stmt.condition.accept(this);
|
||||||
if(condition.type != Type.BOOLEAN) errorHandler.add(new InvalidTypeException("If statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
if(!condition.type.typeOf(Type.BOOLEAN)) errorHandler.add(new InvalidTypeException("If statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
||||||
|
|
||||||
TypedStmt.Block trueBody = (TypedStmt.Block) stmt.trueBody.accept(this);
|
TypedStmt.Block trueBody = (TypedStmt.Block) stmt.trueBody.accept(this);
|
||||||
List<Pair<TypedExpr, TypedStmt.Block>> elseIfClauses = stmt.elseIfClauses.stream().map(c -> {
|
List<Pair<TypedExpr, TypedStmt.Block>> elseIfClauses = stmt.elseIfClauses.stream().map(c -> {
|
||||||
TypedExpr clauseCondition = c.getLeft().accept(this);
|
TypedExpr clauseCondition = c.getLeft().accept(this);
|
||||||
if (clauseCondition.type != Type.BOOLEAN) errorHandler.add(new InvalidTypeException("Else if clause conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
if (!clauseCondition.type.typeOf(Type.BOOLEAN)) errorHandler.add(new InvalidTypeException("Else if clause conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
||||||
return Pair.of(clauseCondition, (TypedStmt.Block) c.getRight().accept(this));
|
return Pair.of(clauseCondition, (TypedStmt.Block) c.getRight().accept(this));
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
public TypedStmt visitForStmt(Stmt.For stmt) {
|
public TypedStmt visitForStmt(Stmt.For stmt) {
|
||||||
TypedStmt initializer = stmt.initializer.accept(this);
|
TypedStmt initializer = stmt.initializer.accept(this);
|
||||||
TypedExpr condition = stmt.condition.accept(this);
|
TypedExpr condition = stmt.condition.accept(this);
|
||||||
if(condition.type != Type.BOOLEAN) errorHandler.add(new InvalidTypeException("For statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
if(!condition.type.typeOf(Type.BOOLEAN)) errorHandler.add(new InvalidTypeException("For statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
||||||
TypedExpr incrementer = stmt.incrementer.accept(this);
|
TypedExpr incrementer = stmt.incrementer.accept(this);
|
||||||
return new TypedStmt.For(initializer, condition, incrementer, (TypedStmt.Block) stmt.body.accept(this));
|
return new TypedStmt.For(initializer, condition, incrementer, (TypedStmt.Block) stmt.body.accept(this));
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ public class TypeChecker implements Visitor<TypedExpr>, Stmt.Visitor<TypedStmt>
|
|||||||
@Override
|
@Override
|
||||||
public TypedStmt visitWhileStmt(Stmt.While stmt) {
|
public TypedStmt visitWhileStmt(Stmt.While stmt) {
|
||||||
TypedExpr condition = stmt.condition.accept(this);
|
TypedExpr condition = stmt.condition.accept(this);
|
||||||
if(condition.type != Type.BOOLEAN) errorHandler.add(new InvalidTypeException("While statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
if(!condition.type.typeOf(Type.BOOLEAN)) errorHandler.add(new InvalidTypeException("While statement conditional must be of type '" + Type.BOOLEAN + "', found '" + condition.type + "' instead.", stmt.position));
|
||||||
return new TypedStmt.While(condition, (TypedStmt.Block) stmt.body.accept(this));
|
return new TypedStmt.While(condition, (TypedStmt.Block) stmt.body.accept(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ public class CodeGenTest {
|
|||||||
|
|
||||||
if (1 == 1) print("Dis is true");
|
if (1 == 1) print("Dis is true");
|
||||||
|
|
||||||
num a = 1;
|
var a: num = 1;
|
||||||
num b = 2;
|
var b: num = 2;
|
||||||
str e = "test";
|
var e: str = "test";
|
||||||
|
|
||||||
if (a <= b) {
|
if (a <= b) {
|
||||||
print("a is <= b");
|
print("a is <= b");
|
||||||
@@ -48,17 +48,19 @@ public class CodeGenTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun loopTwiceThenBreak() {
|
fun loopTwiceThenBreak() {
|
||||||
num i = 0;
|
var i: num = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (i == 2) break;
|
print("looped");
|
||||||
|
if (i == 1) break;
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print("Should loop twice:");
|
||||||
loopTwiceThenBreak();
|
loopTwiceThenBreak();
|
||||||
|
|
||||||
retNum();
|
retNum();
|
||||||
bool bln = true;
|
var bln: bool = true;
|
||||||
|
|
||||||
print(takesArgs("test", 3, true));
|
print(takesArgs("test", 3, true));
|
||||||
print(retStr());
|
print(retStr());
|
||||||
@@ -84,9 +86,9 @@ public class CodeGenTest {
|
|||||||
fun concatTwo(a: str, b: str): str {
|
fun concatTwo(a: str, b: str): str {
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
str hello = "Hell";
|
var hello: str = "Hell";
|
||||||
hello = concatTwo(hello, "o");
|
hello = concatTwo(hello, "o");
|
||||||
str world = "world!";
|
var world: str = "world!";
|
||||||
return concatThree(hello, " ", world);
|
return concatThree(hello, " ", world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-21
@@ -20,22 +20,22 @@ public class SemanticAnalyzerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testVariableReference() {
|
public void testVariableReference() {
|
||||||
// Use of declared variable
|
// Use of declared variable
|
||||||
testValid("num a = 1; a + a;");
|
testValid("var a: num = 1; a + a;");
|
||||||
|
|
||||||
// Can't use undeclared variable
|
// Can't use undeclared variable
|
||||||
testInvalid("a + a;", UndefinedReferenceException.class);
|
testInvalid("a + a;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Can't reference variable before declaration
|
// Can't reference variable before declaration
|
||||||
testInvalid("a + a; num a = 1;", UndefinedReferenceException.class);
|
testInvalid("a + a; var a: num = 1;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Variable declarations shouldn't be accessible from inner scopes
|
// Variable declarations shouldn't be accessible from inner scopes
|
||||||
testInvalid("{ num a = 1; } a + a;", UndefinedReferenceException.class);
|
testInvalid("{ var a: num = 1; } a + a;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Can access variables declared in outer scope
|
// Can access variables declared in outer scope
|
||||||
testValid("num a = 3; { a + a; }");
|
testValid("var a: num = 3; { a + a; }");
|
||||||
|
|
||||||
// Should not be able to use variables from outer scope if they're declared after scope
|
// Should not be able to use variables from outer scope if they're declared after scope
|
||||||
testInvalid("{ a + a; } num a = 2;", UndefinedReferenceException.class);
|
testInvalid("{ a + a; } var a: num = 2;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Can't use undeclared variable as function argument
|
// Can't use undeclared variable as function argument
|
||||||
testInvalid("fun test(p: str) {} test(a);", UndefinedReferenceException.class);
|
testInvalid("fun test(p: str) {} test(a);", UndefinedReferenceException.class);
|
||||||
@@ -47,34 +47,34 @@ public class SemanticAnalyzerTest {
|
|||||||
testInvalid("a = 1;", UndefinedReferenceException.class);
|
testInvalid("a = 1;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Cannot assign to variable declared after assignment
|
// Cannot assign to variable declared after assignment
|
||||||
testInvalid("a = 2; num a = 1;", UndefinedReferenceException.class);
|
testInvalid("a = 2; var a: num = 1;", UndefinedReferenceException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAssignment() {
|
public void testAssignment() {
|
||||||
// Simple assignment
|
// Simple assignment
|
||||||
testValid("num a = 1; a = 2;");
|
testValid("var a: num = 1; a = 2;");
|
||||||
|
|
||||||
// Can assign variables declared in outer scope
|
// Can assign variables declared in outer scope
|
||||||
testValid("""
|
testValid("""
|
||||||
num a = 1;
|
var a: num = 1;
|
||||||
{ a = 2; }
|
{ a = 2; }
|
||||||
""");
|
""");
|
||||||
|
|
||||||
// Cannot assign variables declared in inner scope
|
// Cannot assign variables declared in inner scope
|
||||||
testInvalid("""
|
testInvalid("""
|
||||||
{ num a = 1; }
|
{ var a: num = 1; }
|
||||||
a = 2;
|
a = 2;
|
||||||
""", UndefinedReferenceException.class);
|
""", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Cannot assign variables declared in outer scope after reference
|
// Cannot assign variables declared in outer scope after reference
|
||||||
testInvalid("""
|
testInvalid("""
|
||||||
{ a = 2; }
|
{ a = 2; }
|
||||||
num a = 1;
|
var a: num = 1;
|
||||||
""", UndefinedReferenceException.class);
|
""", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Cannot assign variable to expression of different type
|
// Cannot assign variable to expression of different type
|
||||||
testInvalid("num a = 1; a = true;", InvalidTypeException.class);
|
testInvalid("var a: num = 1; a = true;", InvalidTypeException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -293,8 +293,8 @@ public class SemanticAnalyzerTest {
|
|||||||
testInvalid("fun test(a: num, b: num) { a + c; }", UndefinedReferenceException.class);
|
testInvalid("fun test(a: num, b: num) { a + c; }", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Function bodies can't use variables from outer scope
|
// Function bodies can't use variables from outer scope
|
||||||
testInvalid("num a = 1; fun doStuff() { a + 2; }", UndefinedReferenceException.class);
|
testInvalid("var a: num = 1; fun doStuff() { a + 2; }", UndefinedReferenceException.class);
|
||||||
testInvalid("fun doStuff() { a + 2; } num a = 1;", UndefinedReferenceException.class);
|
testInvalid("fun doStuff() { a + 2; } var a: num = 1;", UndefinedReferenceException.class);
|
||||||
|
|
||||||
// Type checking parameters
|
// Type checking parameters
|
||||||
testValid("fun takesNum(a: num) {} fun test(numberParam: num) { takesNum(numberParam); }");
|
testValid("fun takesNum(a: num) {} fun test(numberParam: num) { takesNum(numberParam); }");
|
||||||
@@ -304,20 +304,20 @@ public class SemanticAnalyzerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testShadowing() {
|
public void testShadowing() {
|
||||||
// Can't shadow variable in immediate scope
|
// Can't shadow variable in immediate scope
|
||||||
testInvalid("num a = 1; num a = 2;", IdentifierAlreadyDeclaredException.class);
|
testInvalid("var a: num = 1; var a: num = 2;", IdentifierAlreadyDeclaredException.class);
|
||||||
|
|
||||||
// Can shadow variable from outer scope
|
// Can shadow variable from outer scope
|
||||||
testValid("num a = 1; { num a = 2; }");
|
testValid("var a: num = 1; { var a: num = 2; }");
|
||||||
|
|
||||||
// Can declare variable after same identifier is used previously in an inner scope
|
// Can declare variable after same identifier is used previously in an inner scope
|
||||||
testValid("{ num a = 2; } num a = 1;");
|
testValid("{ var a: num = 2; } var a: num = 1;");
|
||||||
|
|
||||||
// Ensure shadowed variable type is used
|
// Ensure shadowed variable type is used
|
||||||
testValid("""
|
testValid("""
|
||||||
fun takesNum(p: num) {}
|
fun takesNum(p: num) {}
|
||||||
bool a = false;
|
var a: bool = false;
|
||||||
{
|
{
|
||||||
num a = 1;
|
var a: num = 1;
|
||||||
takesNum(a);
|
takesNum(a);
|
||||||
}
|
}
|
||||||
""");
|
""");
|
||||||
@@ -325,9 +325,9 @@ public class SemanticAnalyzerTest {
|
|||||||
// Should not be able to use type of shadowed variable in use of shadowing variable
|
// Should not be able to use type of shadowed variable in use of shadowing variable
|
||||||
testInvalid("""
|
testInvalid("""
|
||||||
fun takesNum(p: num) {}
|
fun takesNum(p: num) {}
|
||||||
num a = false;
|
var a: num = false;
|
||||||
{
|
{
|
||||||
bool a = 1;
|
var a: bool = 1;
|
||||||
takesNum(a);
|
takesNum(a);
|
||||||
}
|
}
|
||||||
""", InvalidTypeException.class);
|
""", InvalidTypeException.class);
|
||||||
@@ -350,7 +350,7 @@ public class SemanticAnalyzerTest {
|
|||||||
""", IdentifierAlreadyDeclaredException.class);
|
""", IdentifierAlreadyDeclaredException.class);
|
||||||
|
|
||||||
// Can't use function name that is already declared as a variable
|
// Can't use function name that is already declared as a variable
|
||||||
testInvalid("num id = 1; fun id() {}", IdentifierAlreadyDeclaredException.class);
|
testInvalid("var id: num = 1; fun id() {}", IdentifierAlreadyDeclaredException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Exception> void testInvalid(String invalidSource, Class<T> exceptionType) {
|
private <T extends Exception> void testInvalid(String invalidSource, Class<T> exceptionType) {
|
||||||
|
|||||||
Reference in new issue
Block a user