Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic;
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator;
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment;
import at.petrak.hexcasting.api.casting.eval.OperationResult;
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage;
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation;
import at.petrak.hexcasting.api.casting.iota.Iota;
import at.petrak.hexcasting.api.casting.math.HexPattern;
import at.petrak.hexcasting.api.casting.mishaps.Mishap;
Expand Down Expand Up @@ -64,29 +67,34 @@ public Iterable<HexPattern> operatorSyms() {
/**
* Runs one of the contained Operators assigned to the given pattern, modifying the passed stack of iotas.
* @param pattern The pattern that was drawn, used to determine which operators are candidates.
* @param iotas The current stack.
* @param startingLength The length of the stack before the operator executes (used for errors).
* @param env The casting environment.
* @param image The casting image.
* @param continuation The current continuation.
* @return The iotas to be added to the stack.
* @throws Mishap mishaps if invalid input to the operators is given by the caster.
*/
public Iterable<Iota> run(HexPattern pattern, Stack<Iota> iotas, int startingLength, CastingEnvironment env) throws Mishap {
public OperationResult run(HexPattern pattern, CastingEnvironment env, CastingImage image, SpellContinuation continuation) throws Mishap {
var stackList = image.getStack();
var stack = new Stack<Iota>();
stack.addAll(stackList);
var startingLength = stackList.size();

var candidates = operators.get(pattern);
if (candidates == null)
throw new InvalidOperatorException("the pattern " + pattern + " is not an operator."); //
HashCons hash = new HashCons.Pattern(pattern);
var args = new ArrayList<Iota>(candidates.arity());
for (var i = 0; i < candidates.arity(); i++) {
if (iotas.isEmpty()) {
if (stack.isEmpty()) {
throw new MishapNotEnoughArgs(candidates.arity, startingLength);
}
var iota = iotas.pop();
var iota = stack.pop();
hash = new HashCons.Pair(iota.getType(), hash);
args.add(iota);
}
Collections.reverse(args);
var op = resolveCandidates(args, hash, candidates);
return op.apply(args, env);
return op.operate(env, image, continuation);
}

private Operator resolveCandidates(List<Iota> args, HashCons hash, OpCandidates candidates) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package at.petrak.hexcasting.api.casting.arithmetic.operator

import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.IotaType
import at.petrak.hexcasting.api.casting.mishaps.Mishap
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import java.util.function.Consumer

abstract class Operator
/**
* @param arity The number of arguments from the stack that this Operator requires; all Operators with the same pattern must have arity.
* @param accepts A function that should return true if the passed list of Iotas satisfies this Operator's type constraints, and false otherwise.
*/
(
@JvmField
val arity: Int,
@JvmField
val accepts: IotaMultiPredicate
) {

/**
* Functionally update the image. Return the image and any side effects.
*/
@Throws(Mishap::class)
abstract fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult


companion object {
/**
* A helper method to take an iota that you know is of iotaType and returning it as an iota of that type.
*/
@JvmStatic
fun <T : Iota?> downcast(iota: Iota, iotaType: IotaType<T>): T {
check(iota.type === iotaType) { "Attempting to downcast $iota to type: $iotaType" }
return iota as T
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package at.petrak.hexcasting.api.casting.arithmetic.operator

import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.mishaps.Mishap
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import java.util.function.Consumer

abstract class OperatorBasic(arity: Int, accepts: IotaMultiPredicate) : Operator(arity, accepts) {

@Throws(Mishap::class)
override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult {
val stack = image.stack.toMutableList()
val args = stack.takeLast(arity)
repeat(arity) { stack.removeLast() }

val ret = apply(args, env)
ret.forEach(Consumer { e: Iota -> stack.add(e) })

val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + 1)
return OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE)
}

/**
* / **
* The method called when this Operator is actually acting on the stack, for real.
* @param iotas An iterable of iotas with [Operator.arity] elements that satisfied [Operator.accepts].
* @param env The casting environment, to make use of if this operator needs it.
* @return the iotas that this operator will return to the stack (with the first element of the returned iterable being placed deepest into the stack, and the last element on top of the stack).
* @throws Mishap if the Operator mishaps for any reason it will be passed up the chain.
*/
@Throws(Mishap::class)
abstract fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota>

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/**
* A helper class for defining {@link Operator}s of two iotas.
*/
public class OperatorBinary extends Operator {
public class OperatorBinary extends OperatorBasic {
public BinaryOperator<Iota> inner;

public OperatorBinary(IotaMultiPredicate accepts, BinaryOperator<Iota> inner) {
Expand All @@ -21,7 +21,7 @@ public OperatorBinary(IotaMultiPredicate accepts, BinaryOperator<Iota> inner) {
}

@Override
public @NotNull Iterable<Iota> apply(@NotNull Iterable<Iota> iotas, @NotNull CastingEnvironment env) {
public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) {
var it = iotas.iterator();
return List.of(inner.apply(it.next(), it.next()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/**
* A helper class for defining {@link Operator}s of one iota.
*/
public class OperatorUnary extends Operator {
public class OperatorUnary extends OperatorBasic {
public UnaryOperator<Iota> inner;

public OperatorUnary(IotaMultiPredicate accepts, UnaryOperator<Iota> inner) {
Expand All @@ -21,7 +21,7 @@ public OperatorUnary(IotaMultiPredicate accepts, UnaryOperator<Iota> inner) {
}

@Override
public @NotNull Iterable<Iota> apply(@NotNull Iterable<Iota> iotas, @NotNull CastingEnvironment env) {
public @NotNull Iterable<Iota> apply(Iterable<? extends Iota> iotas, @NotNull CastingEnvironment env) {
return List.of(inner.apply(iotas.iterator().next()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,18 @@ import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.eval.OperationResult
import at.petrak.hexcasting.api.casting.eval.vm.CastingImage
import at.petrak.hexcasting.api.casting.eval.vm.SpellContinuation
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.math.HexPattern
import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidOperatorArgs
import at.petrak.hexcasting.common.lib.hex.HexArithmetics
import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
import java.util.*
import java.util.function.Consumer

/**
* Represents an Operator with the give pattern as its identifier, a special type of Action that calls a different function depending on the type of its arguments.
* This exists so that addons can easily define their own overloads to patterns like addition, subtraction, etc.
*/
data class OperationAction(val pattern: HexPattern) : Action {
override fun operate(env: CastingEnvironment, image: CastingImage, continuation: SpellContinuation): OperationResult {
val stackList = image.stack
val stack = Stack<Iota>()
stack.addAll(stackList)
val startingLength = stackList.size
return try {
val ret: Iterable<Iota> = HexArithmetics.getEngine().run(pattern, stack, startingLength, env)
ret.forEach(Consumer { e: Iota -> stack.add(e) })
val image2 = image.copy(stack = stack, opsConsumed = image.opsConsumed + 1) // TODO: maybe let operators figure out how many ops to consume?
OperationResult(image2, listOf(), continuation, HexEvalSounds.NORMAL_EXECUTE)
HexArithmetics.getEngine().run(pattern, env, image, continuation)
} catch (e: NoOperatorCandidatesException) {
throw MishapInvalidOperatorArgs(e.args, e.pattern)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic.*
import at.petrak.hexcasting.api.casting.arithmetic.engine.InvalidOperatorException
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.Companion.downcast
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorUnary
import at.petrak.hexcasting.api.casting.iota.DoubleIota
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic.*
import at.petrak.hexcasting.api.casting.arithmetic.engine.InvalidOperatorException
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.downcast
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.Companion.downcast
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorUnary
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate.all
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic
import at.petrak.hexcasting.api.casting.arithmetic.Arithmetic.*
import at.petrak.hexcasting.api.casting.arithmetic.engine.InvalidOperatorException
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.*
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator.Companion.downcast
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBinary
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate.*
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.petrak.hexcasting.common.casting.arithmetic.operator

import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.asActionResult
Expand All @@ -10,7 +11,7 @@ import at.petrak.hexcasting.api.casting.mishaps.MishapDivideByZero
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.DOUBLE
import kotlin.math.log

object OperatorLog : Operator(2, IotaMultiPredicate.all(IotaPredicate.ofType(DOUBLE))) {
object OperatorLog : OperatorBasic(2, IotaMultiPredicate.all(IotaPredicate.ofType(DOUBLE))) {
override fun apply(iotas: Iterable<Iota>, env : CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator().withIndex()
val value = it.nextDouble(arity)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.petrak.hexcasting.common.casting.arithmetic.operator.list

import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.asActionResult
Expand All @@ -9,7 +10,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*

object OperatorAppend : Operator(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) {
object OperatorAppend : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) {
override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator().withIndex()
val list = it.nextList(arity).toMutableList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package at.petrak.hexcasting.common.casting.arithmetic.operator.list
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.eval.CastingEnvironment
import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.api.casting.iota.NullIota
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*
import kotlin.math.roundToInt

object OperatorIndex : Operator(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) {
object OperatorIndex : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) {
override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator()
val list = downcast(it.next(), LIST).list.toMutableList()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.petrak.hexcasting.common.casting.arithmetic.operator.list

import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.asActionResult
Expand All @@ -9,7 +10,7 @@ import at.petrak.hexcasting.api.casting.iota.Iota
import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*

object OperatorIndexOf : Operator(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) {
object OperatorIndexOf : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.TRUE)) {
override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator().withIndex()
val list = it.nextList(arity).toList()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package at.petrak.hexcasting.common.casting.arithmetic.operator.list

import at.petrak.hexcasting.api.casting.arithmetic.operator.Operator
import at.petrak.hexcasting.api.casting.arithmetic.operator.OperatorBasic
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaMultiPredicate
import at.petrak.hexcasting.api.casting.arithmetic.predicates.IotaPredicate
import at.petrak.hexcasting.api.casting.asActionResult
Expand All @@ -10,7 +11,7 @@ import at.petrak.hexcasting.common.casting.arithmetic.operator.nextInt
import at.petrak.hexcasting.common.casting.arithmetic.operator.nextList
import at.petrak.hexcasting.common.lib.hex.HexIotaTypes.*

object OperatorRemove : Operator(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) {
object OperatorRemove : OperatorBasic(2, IotaMultiPredicate.pair(IotaPredicate.ofType(LIST), IotaPredicate.ofType(DOUBLE))) {
override fun apply(iotas: Iterable<Iota>, env: CastingEnvironment): Iterable<Iota> {
val it = iotas.iterator().withIndex()
val list = it.nextList(arity).toMutableList()
Expand Down
Loading