From 0fef1619d232631568c49808560681367d117dd9 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sat, 2 Jan 2021 01:08:45 -0700 Subject: [PATCH] implement ModuloOperation --- .../terra/api/structures/parser/Parser.java | 3 +++ .../api/structures/parser/ParserUtil.java | 2 +- .../lang/operations/ModuloOperation.java | 20 +++++++++++++++++++ .../script/builders/BlockFunctionBuilder.java | 10 ++++++++-- .../script/functions/BlockFunction.java | 6 ++++-- .../structure/buffer/items/BufferedBlock.java | 8 ++++++-- .../terra/api/structures/tokenizer/Token.java | 10 ++++++++-- .../api/structures/tokenizer/Tokenizer.java | 2 ++ 8 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java index 56b66eeb7..f88a02703 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/Parser.java @@ -24,6 +24,7 @@ import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation import com.dfsek.terra.api.structures.parser.lang.operations.BooleanOrOperation; import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperation; import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation; +import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation; import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation; import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation; import com.dfsek.terra.api.structures.parser.lang.operations.SubtractionOperation; @@ -321,6 +322,8 @@ public class Parser { return new BooleanAndOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); case BOOLEAN_OR: return new BooleanOrOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); + case MODULO_OPERATOR: + return new ModuloOperation((Returnable) left, (Returnable) right, binaryOperator.getPosition()); default: throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType()); } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java index 0462d630c..212d99d70 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/ParserUtil.java @@ -12,7 +12,7 @@ import java.util.Map; public class ParserUtil { private static final Map> PRECEDENCE = new HashMap<>(); - private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR); + private static final List ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR); private static final List COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR); static { // Setup precedence diff --git a/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java new file mode 100644 index 000000000..44ef9a7d1 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/structures/parser/lang/operations/ModuloOperation.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.structures.parser.lang.operations; + +import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.tokenizer.Position; + +public class ModuloOperation extends BinaryOperation { + public ModuloOperation(Returnable left, Returnable right, Position start) { + super(left, right, start); + } + + @Override + public Number apply(Number left, Number right) { + return left.doubleValue() % right.doubleValue(); + } + + @Override + public ReturnType returnType() { + return ReturnType.NUMBER; + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java index 8997bd937..116681866 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/BlockFunctionBuilder.java @@ -3,6 +3,7 @@ package com.dfsek.terra.api.structures.script.builders; import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.api.structures.parser.exceptions.ParseException; import com.dfsek.terra.api.structures.parser.lang.Returnable; +import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.functions.BlockFunction; import com.dfsek.terra.api.structures.tokenizer.Position; @@ -19,12 +20,15 @@ public class BlockFunctionBuilder implements FunctionBuilder { @SuppressWarnings("unchecked") @Override public BlockFunction build(List> argumentList, Position position) throws ParseException { - return new BlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), main, position); + if(argumentList.size() < 4) throw new ParseException("Expected data", position); + Returnable booleanReturnable = new BooleanConstant(true, position); + if(argumentList.size() == 5) booleanReturnable = (Returnable) argumentList.get(4); + return new BlockFunction((Returnable) argumentList.get(0), (Returnable) argumentList.get(1), (Returnable) argumentList.get(2), (Returnable) argumentList.get(3), booleanReturnable, main, position); } @Override public int argNumber() { - return 4; + return -1; } @Override @@ -36,6 +40,8 @@ public class BlockFunctionBuilder implements FunctionBuilder { return Returnable.ReturnType.NUMBER; case 3: return Returnable.ReturnType.STRING; + case 4: + return Returnable.ReturnType.BOOLEAN; default: return null; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java index 953d3505a..215c37d0f 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/BlockFunction.java @@ -19,8 +19,9 @@ public class BlockFunction implements Function { private final BlockData data; private final Returnable x, y, z; private final Position position; + private final Returnable overwrite; - public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, TerraPlugin main, Position position) throws ParseException { + public BlockFunction(Returnable x, Returnable y, Returnable z, Returnable data, Returnable overwrite, TerraPlugin main, Position position) throws ParseException { this.position = position; if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition()); @@ -28,6 +29,7 @@ public class BlockFunction implements Function { this.x = x; this.y = y; this.z = z; + this.overwrite = overwrite; } @Override @@ -38,7 +40,7 @@ public class BlockFunction implements Function { RotationUtil.rotateVector(xz, arguments.getRotation()); BlockData rot = data.clone(); RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse()); - arguments.getBuffer().addItem(new BufferedBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ()))); + arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ()))); return null; } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java index 1ed1b414d..932efbd15 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/structure/buffer/items/BufferedBlock.java @@ -1,17 +1,21 @@ package com.dfsek.terra.api.structures.structure.buffer.items; import com.dfsek.terra.api.math.vector.Location; +import com.dfsek.terra.api.platform.block.Block; import com.dfsek.terra.api.platform.block.BlockData; public class BufferedBlock implements BufferedItem { private final BlockData data; + private final boolean overwrite; - public BufferedBlock(BlockData data) { + public BufferedBlock(BlockData data, boolean overwrite) { this.data = data; + this.overwrite = overwrite; } @Override public void paste(Location origin) { - origin.getBlock().setBlockData(data, false); + Block block = origin.getBlock(); + if(overwrite || block.isEmpty()) block.setBlockData(data, false); } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java index 31af0c837..b74a206f7 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Token.java @@ -44,7 +44,8 @@ public class Token { || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) || type.equals(Type.BOOLEAN_OR) - || type.equals(Type.BOOLEAN_AND); + || type.equals(Type.BOOLEAN_AND) + || type.equals(Type.MODULO_OPERATOR); } public boolean isStrictNumericOperator() { @@ -54,7 +55,8 @@ public class Token { || type.equals(Type.GREATER_THAN_OPERATOR) || type.equals(Type.LESS_THAN_OPERATOR) || type.equals(Type.LESS_THAN_OR_EQUALS_OPERATOR) - || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR); + || type.equals(Type.GREATER_THAN_OR_EQUALS_OPERATOR) + || type.equals(Type.MODULO_OPERATOR); } public boolean isStrictBooleanOperator() { @@ -164,6 +166,10 @@ public class Token { * Division operator */ DIVISION_OPERATOR, + /** + * Modulo operator. + */ + MODULO_OPERATOR, /** * Boolean not operator */ diff --git a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java index cd25b52f4..857bcf157 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/tokenizer/Tokenizer.java @@ -96,6 +96,8 @@ public class Tokenizer { return new Token(reader.consume().toString(), Token.Type.MULTIPLICATION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('/')) return new Token(reader.consume().toString(), Token.Type.DIVISION_OPERATOR, new Position(reader.getLine(), reader.getIndex())); + if(reader.current().is('%')) + return new Token(reader.consume().toString(), Token.Type.MODULO_OPERATOR, new Position(reader.getLine(), reader.getIndex())); if(reader.current().is('!')) return new Token(reader.consume().toString(), Token.Type.BOOLEAN_NOT, new Position(reader.getLine(), reader.getIndex()));