Skip to content

Commit

Permalink
Rename binary operator to post fix operator, add some non-binary oper…
Browse files Browse the repository at this point in the history
…ators

Just standard stuff like duplicate, swap, negate, abs, and subtract/divide/power with reversed operands
  • Loading branch information
KnightMiner committed Jan 10, 2024
1 parent d25fce0 commit d17923f
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 115 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ public void validateFormula() {

/** Deserializes a formula from JSON */
public static PostFixFormula deserialize(JsonObject json, String[] variableNames) {
// TODO: string formulas using Shunting yard algorithm
return new PostFixFormula(JsonHelper.parseList(json, "formula", (element, key) -> {
if (element.isJsonPrimitive()) {
return StackOperation.deserialize(element.getAsJsonPrimitive(), variableNames);
Expand Down Expand Up @@ -126,37 +127,72 @@ public T variable(int index) {

/** Pushes an add operation into the builder */
public T add() {
return operation(BinaryOperator.ADD);
return operation(PostFixOperator.ADD);
}

/** Pushes a subtract operation into the builder */
public T subtract() {
return operation(BinaryOperator.SUBTRACT);
return operation(PostFixOperator.SUBTRACT);
}

/** Pushes a subtract flipped operation into the builder */
public T subtractFlipped() {
return operation(PostFixOperator.SUBTRACT_FLIPPED);
}

/** Pushes a multiply operation into the builder */
public T multiply() {
return operation(BinaryOperator.MULTIPLY);
return operation(PostFixOperator.MULTIPLY);
}

/** Pushes a negate operation into the builder */
public T negate() {
return operation(PostFixOperator.NEGATE);
}

/** Pushes a divide operation into the builder */
public T divide() {
return operation(BinaryOperator.DIVIDE);
return operation(PostFixOperator.DIVIDE);
}

/** Pushes a divide flipped operation into the builder */
public T divideFlipped() {
return operation(PostFixOperator.DIVIDE_FLIPPED);
}

/** Pushes a power operation into the builder */
public T power() {
return operation(BinaryOperator.POWER);
return operation(PostFixOperator.POWER);
}

/** Pushes a power flipped operation into the builder */
public T powerFlipped() {
return operation(PostFixOperator.POWER_FLIPPED);
}

/** Pushes a min operation into the builder */
public T min() {
return operation(BinaryOperator.MIN);
return operation(PostFixOperator.MIN);
}

/** Pushes a max operation into the builder */
public T max() {
return operation(BinaryOperator.MAX);
return operation(PostFixOperator.MAX);
}

/** Pushes a abs operation into the builder */
public T abs() {
return operation(PostFixOperator.ABS);
}

/** Pushes a swap operation into the builder */
public T swap() {
return operation(PostFixOperator.SWAP);
}

/** Pushes a duplicate operation into the builder */
public T duplicate() {
return operation(PostFixOperator.DUPLICATE);
}

/** Validates and builds the formula */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package slimeknights.tconstruct.library.json.math;

import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import it.unimi.dsi.fastutil.floats.FloatStack;
import lombok.RequiredArgsConstructor;
import net.minecraft.network.FriendlyByteBuf;

/** Represents 2 argument stack operations */
@RequiredArgsConstructor
public enum PostFixOperator implements StackOperation {
ADD("+", Float::sum),
SUBTRACT("-", (left, right) -> left - right),
SUBTRACT_FLIPPED("--", (left, right) -> right - left),
MULTIPLY("*", (left, right) -> left * right),
NEGATE("negate") {
@Override
public void perform(FloatStack stack, float[] variables) {
stack.push(-stack.popFloat());
}
},
DIVIDE("/", (left, right) -> {
if (left == 0) {
return 0;
}
return right / left;
}),
DIVIDE_FLIPPED("//", (left, right) -> {
if (right == 0) {
return 0;
}
return left / right;
}),
POWER("^", (left, right) -> (float)Math.pow(left, right)),
POWER_FLIPPED("^^", (left, right) -> (float)Math.pow(right, left)),
MIN("min", Math::min),
MAX("max", Math::max),
ABS("abs") {
@Override
public void perform(FloatStack stack, float[] variables) {
stack.push(Math.abs(stack.popFloat()));
}
},
/** Swaps the top two elements */
SWAP("swap") {
@Override
public void perform(FloatStack stack, float[] variables) {
float first = stack.popFloat();
float second = stack.popFloat();
stack.push(first);
stack.push(second);
}
},
/** Copies the top element on the stack */
DUPLICATE("duplicate") {
@Override
public void perform(FloatStack stack, float[] variables) {
float value = stack.popFloat();
stack.push(value);
stack.push(value);
}
};

/** Index used for serializing value to the network */
public static final int VALUE_INDEX = values().length;
/** Index used for serializing a variable to the network */
public static final int VARIABLE_INDEX = VALUE_INDEX + 1;

/** Name of this operator when serialized into JSON */
private final String serialized;
/** Binary function to run, used for most operators */
private final BinaryOperator binary;

PostFixOperator(String serialized) {
this(serialized, BinaryOperator.ZERO);
}

@Override
public void perform(FloatStack stack, float[] variables) {
// this may throw, but that is okay as we will run this formula during parsing to make sure its valid
// the way formulas are setup, if it does not throw during parsing, it cannot throw ever
float right = stack.popFloat();
float left = stack.popFloat();
stack.push(binary.apply(left, right));
}


/* JSON and network */

/** Deserializes the operator from a character */
public static PostFixOperator deserialize(String name) {
for (PostFixOperator operator : PostFixOperator.values()) {
if (operator.serialized.equals(name)) {
return operator;
}
}
throw new JsonSyntaxException("Unknown post fix operator '" + name + "'");
}

@Override
public JsonPrimitive serialize(String[] variableNames) {
return new JsonPrimitive(serialized);
}

@Override
public void toNetwork(FriendlyByteBuf buffer) {
// comment on buffer internals: the indices of this enum and StackNetworkType match up until divide,
// so writing our ordinal allows us to read an ordinal for the other enum
buffer.writeEnum(this);
}

/** Interface for common operators */
private interface BinaryOperator {
BinaryOperator ZERO = (left, right) -> 0;

/** Applies this operator to the given values */
float apply(float left, float right);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public JsonPrimitive serialize(String[] variableNames) {

@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeVarInt(BinaryOperator.VALUE_INDEX);
buffer.writeVarInt(PostFixOperator.VALUE_INDEX);
buffer.writeFloat(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public JsonPrimitive serialize(String[] variableNames) {

@Override
public void toNetwork(FriendlyByteBuf buffer) {
buffer.writeVarInt(BinaryOperator.VARIABLE_INDEX);
buffer.writeVarInt(PostFixOperator.VARIABLE_INDEX);
buffer.writeVarInt(index);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static StackOperation deserialize(JsonPrimitive element, String[] variableNames)
}
throw new JsonSyntaxException("Unknown variable '" + str + "'");
}
return BinaryOperator.deserialize(str);
return PostFixOperator.deserialize(str);
}
// numbers are constants
if (element.isNumber()) {
Expand All @@ -46,12 +46,12 @@ static StackOperation deserialize(JsonPrimitive element, String[] variableNames)
/** Reads an operation from the network */
static StackOperation fromNetwork(FriendlyByteBuf buffer) {
int type = buffer.readVarInt();
if (type == BinaryOperator.VALUE_INDEX) {
if (type == PostFixOperator.VALUE_INDEX) {
return new PushConstantOperation(buffer.readFloat());
}
if (type == BinaryOperator.VARIABLE_INDEX) {
if (type == PostFixOperator.VARIABLE_INDEX) {
return new PushVariableOperation(buffer.readVarInt());
}
return BinaryOperator.values()[type];
return PostFixOperator.values()[type];
}
}

0 comments on commit d17923f

Please sign in to comment.