Make continuations immutable and functional
This commit is contained in:
parent
cf89dfe38b
commit
cd5657d7b8
18 changed files with 127 additions and 90 deletions
|
@ -1,7 +1,7 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
|
||||
|
@ -15,7 +15,7 @@ interface ConstManaOperator : Operator {
|
|||
|
||||
fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>>
|
||||
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw MishapNotEnoughArgs(this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
|
@ -25,6 +25,6 @@ interface ConstManaOperator : Operator {
|
|||
|
||||
val sideEffects = mutableListOf<OperatorSideEffect>(OperatorSideEffect.ConsumeMana(this.manaCost))
|
||||
|
||||
return OperationResult(stack, local, sideEffects)
|
||||
return OperationResult(continuation, stack, local, sideEffects)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
/**
|
||||
* What happens when an operator is through?
|
||||
*/
|
||||
data class OperationResult(val newStack: List<SpellDatum<*>>, val newLocalIota: SpellDatum<*>, val sideEffects: List<OperatorSideEffect>)
|
||||
data class OperationResult(val newContinuation: SpellContinuation, val newStack: List<SpellDatum<*>>, val newLocalIota: SpellDatum<*>, val sideEffects: List<OperatorSideEffect>)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ interface Operator {
|
|||
*
|
||||
* A particle effect at the cast site and various messages and advancements are done automagically.
|
||||
*/
|
||||
fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
|
||||
fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
|
||||
|
||||
/**
|
||||
* Do you need to be enlightened to use this operator?
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package at.petrak.hexcasting.api.spell
|
||||
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
|
||||
|
@ -17,12 +17,12 @@ interface SpellOperator : Operator {
|
|||
ctx: CastingContext
|
||||
): Triple<RenderedSpell, Int, List<ParticleSpray>>?
|
||||
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (this.argc > stack.size)
|
||||
throw MishapNotEnoughArgs(this.argc, stack.size)
|
||||
val args = stack.takeLast(this.argc)
|
||||
for (_i in 0 until this.argc) stack.removeLast()
|
||||
val executeResult = this.execute(args, ctx) ?: return OperationResult(stack, local, listOf())
|
||||
val executeResult = this.execute(args, ctx) ?: return OperationResult(continuation, stack, local, listOf())
|
||||
val (spell, mana, particles) = executeResult
|
||||
|
||||
val sideEffects = mutableListOf(
|
||||
|
@ -33,7 +33,7 @@ interface SpellOperator : Operator {
|
|||
sideEffects.add(OperatorSideEffect.Particles(spray))
|
||||
}
|
||||
|
||||
return OperationResult(stack, local, sideEffects)
|
||||
return OperationResult(continuation, stack, local, sideEffects)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -63,19 +63,20 @@ class CastingHarness private constructor(
|
|||
*/
|
||||
fun executeIotas(iotas: List<SpellDatum<*>>, world: ServerLevel): ControllerInfo {
|
||||
// Initialize the continuation stack to a single top-level eval for all iotas.
|
||||
val continuation: MutableList<ContinuationFrame> = mutableListOf(ContinuationFrame.Evaluate(SpellList.LList(0, iotas)))
|
||||
var continuation = SpellContinuation.Done.pushFrame(ContinuationFrame.Evaluate(SpellList.LList(0, iotas)))
|
||||
// Begin aggregating info
|
||||
val info = TempControllerInfo(false, false)
|
||||
var lastResolutionType = ResolvedPatternType.UNKNOWN
|
||||
while (continuation.isNotEmpty() && !info.earlyExit) {
|
||||
while (continuation is SpellContinuation.NotDone && !info.earlyExit) {
|
||||
// Take the top of the continuation stack...
|
||||
val next = continuation.removeLast()
|
||||
val next = continuation.frame
|
||||
// ...and execute it.
|
||||
val result = next.evaluate(continuation, world, this)
|
||||
val result = next.evaluate(continuation.next, world, this)
|
||||
// Then write all pertinent data back to the harness for the next iteration.
|
||||
if (result.newData != null) {
|
||||
this.applyFunctionalData(result.newData)
|
||||
}
|
||||
continuation = result.continuation
|
||||
lastResolutionType = result.resolutionType
|
||||
performSideEffects(info, result.sideEffects)
|
||||
info.earlyExit = info.earlyExit || !lastResolutionType.success
|
||||
|
@ -89,16 +90,17 @@ class CastingHarness private constructor(
|
|||
)
|
||||
}
|
||||
|
||||
fun getUpdate(iota: SpellDatum<*>, world: ServerLevel, continuation: MutableList<ContinuationFrame>): CastResult {
|
||||
fun getUpdate(iota: SpellDatum<*>, world: ServerLevel, continuation: SpellContinuation): CastResult {
|
||||
try {
|
||||
this.handleParentheses(iota)?.let { (data, resolutionType) ->
|
||||
return@getUpdate CastResult(data, resolutionType, listOf())
|
||||
return@getUpdate CastResult(continuation, data, resolutionType, listOf())
|
||||
}
|
||||
|
||||
return if (iota.getType() == DatumType.PATTERN) {
|
||||
updateWithPattern(iota.payload as HexPattern, world, continuation)
|
||||
} else {
|
||||
CastResult(
|
||||
continuation,
|
||||
null,
|
||||
ResolvedPatternType.INVALID, // Should never matter
|
||||
listOf(
|
||||
|
@ -111,6 +113,7 @@ class CastingHarness private constructor(
|
|||
}
|
||||
} catch (mishap: Mishap) {
|
||||
return CastResult(
|
||||
continuation,
|
||||
null,
|
||||
mishap.resolutionType(ctx),
|
||||
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), null))),
|
||||
|
@ -118,6 +121,7 @@ class CastingHarness private constructor(
|
|||
} catch (exception: Exception) {
|
||||
exception.printStackTrace()
|
||||
return CastResult(
|
||||
continuation,
|
||||
null,
|
||||
ResolvedPatternType.ERROR,
|
||||
listOf(OperatorSideEffect.DoMishap(MishapError(exception), Mishap.Context(iota.payload as? HexPattern ?: HexPattern(HexDir.WEST), null)))
|
||||
|
@ -129,7 +133,7 @@ class CastingHarness private constructor(
|
|||
* When the server gets a packet from the client with a new pattern,
|
||||
* handle it functionally.
|
||||
*/
|
||||
fun updateWithPattern(newPat: HexPattern, world: ServerLevel, continuation: MutableList<ContinuationFrame>): CastResult {
|
||||
fun updateWithPattern(newPat: HexPattern, world: ServerLevel, continuation: SpellContinuation): CastResult {
|
||||
if (this.ctx.spellCircle == null)
|
||||
this.ctx.caster.awardStat(HexStatistics.PATTERNS_DRAWN)
|
||||
|
||||
|
@ -141,7 +145,7 @@ class CastingHarness private constructor(
|
|||
if (!HexConfig.server().isActionAllowed(operatorIdPair.second)) {
|
||||
throw MishapDisallowedSpell()
|
||||
}
|
||||
val (stack2, local2, sideEffectsUnmut) = operatorIdPair.first.operate(continuation, this.stack.toMutableList(), this.localIota, this.ctx)
|
||||
val (cont2, stack2, local2, sideEffectsUnmut) = operatorIdPair.first.operate(continuation, this.stack.toMutableList(), this.localIota, this.ctx)
|
||||
this.localIota = local2
|
||||
// Stick a poofy particle effect at the caster position
|
||||
val sideEffects = sideEffectsUnmut.toMutableList()
|
||||
|
@ -161,12 +165,14 @@ class CastingHarness private constructor(
|
|||
)
|
||||
|
||||
return CastResult(
|
||||
cont2,
|
||||
fd,
|
||||
ResolvedPatternType.OK,
|
||||
sideEffects,
|
||||
)
|
||||
} catch (mishap: Mishap) {
|
||||
return CastResult(
|
||||
continuation,
|
||||
null,
|
||||
mishap.resolutionType(ctx),
|
||||
listOf(OperatorSideEffect.DoMishap(mishap, Mishap.Context(newPat, operatorIdPair?.second))),
|
||||
|
@ -174,6 +180,7 @@ class CastingHarness private constructor(
|
|||
} catch (exception: Exception) {
|
||||
exception.printStackTrace()
|
||||
return CastResult(
|
||||
continuation,
|
||||
null,
|
||||
ResolvedPatternType.ERROR,
|
||||
listOf(OperatorSideEffect.DoMishap(MishapError(exception), Mishap.Context(newPat, operatorIdPair?.second)))
|
||||
|
@ -469,6 +476,7 @@ class CastingHarness private constructor(
|
|||
)
|
||||
|
||||
data class CastResult(
|
||||
val continuation: SpellContinuation,
|
||||
val newData: FunctionalData?,
|
||||
val resolutionType: ResolvedPatternType,
|
||||
val sideEffects: List<OperatorSideEffect>,
|
||||
|
|
|
@ -23,7 +23,7 @@ sealed interface ContinuationFrame {
|
|||
* For Evaluate, this consumes one pattern; for ForEach this queues the next iteration of the outer loop.
|
||||
* @return the result of this pattern step
|
||||
*/
|
||||
fun evaluate(continuation: MutableList<ContinuationFrame>, level: ServerLevel, harness: CastingHarness): CastResult
|
||||
fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult
|
||||
/**
|
||||
* The OpHalt instruction wants us to "jump to" the END of the nearest meta-eval.
|
||||
* In other words, we should consume Evaluate frames until we hit a FinishEval or Thoth frame.
|
||||
|
@ -35,25 +35,23 @@ sealed interface ContinuationFrame {
|
|||
* A list of patterns to be evaluated in sequence.
|
||||
* @property list the *remaining* list of patterns to be evaluated
|
||||
*/
|
||||
data class Evaluate(var list: SpellList): ContinuationFrame {
|
||||
data class Evaluate(val list: SpellList): ContinuationFrame {
|
||||
// Discard this frame and keep discarding frames.
|
||||
override fun breakDownwards(stack: List<SpellDatum<*>>) = Pair(false, stack)
|
||||
|
||||
// Step the list of patterns, evaluating a single one.
|
||||
override fun evaluate(continuation: MutableList<ContinuationFrame>, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
override fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
// If there are patterns left...
|
||||
if (list.nonEmpty) {
|
||||
val toEval = list.car
|
||||
list = list.cdr
|
||||
if (list.nonEmpty) { // yay TCO
|
||||
val newCont = if (list.cdr.nonEmpty) { // yay TCO
|
||||
// ...enqueue the evaluation of the rest of the patterns...
|
||||
continuation.add(this)
|
||||
}
|
||||
continuation.pushFrame(Evaluate(list.cdr))
|
||||
} else continuation
|
||||
// ...before evaluating the first one in the list.
|
||||
return harness.getUpdate(toEval, level, continuation)
|
||||
return harness.getUpdate(list.car, level, newCont)
|
||||
} else {
|
||||
// If there are no patterns (e.g. empty Hermes), just return OK.
|
||||
return CastResult(null, ResolvedPatternType.OK, listOf())
|
||||
return CastResult(continuation, null, ResolvedPatternType.OK, listOf())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,8 +66,8 @@ sealed interface ContinuationFrame {
|
|||
override fun breakDownwards(stack: List<SpellDatum<*>>) = Pair(true, stack)
|
||||
|
||||
// Evaluating it does nothing; it's only a boundary condition.
|
||||
override fun evaluate(continuation: MutableList<ContinuationFrame>, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
return CastResult(FunctionalData(harness.stack.toList(), 0, listOf(), false), ResolvedPatternType.OK, listOf())
|
||||
override fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
return CastResult(continuation, FunctionalData(harness.stack.toList(), 0, listOf(), false), ResolvedPatternType.OK, listOf())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,44 +80,45 @@ sealed interface ContinuationFrame {
|
|||
* @property baseStack the stack state at Thoth entry
|
||||
* @property acc concatenated list of final stack states after Thoth exit
|
||||
*/
|
||||
data class ForEach(var first: Boolean, var data: SpellList, val code: SpellList, val baseStack: List<SpellDatum<*>>, var acc: MutableList<SpellDatum<*>>): ContinuationFrame {
|
||||
/** Helper to append something to the original stack. */
|
||||
fun appendBase(iota: SpellDatum<*>): List<SpellDatum<*>> {
|
||||
val mutStack = baseStack.toMutableList()
|
||||
mutStack.add(iota)
|
||||
return mutStack
|
||||
}
|
||||
data class ForEach(val data: SpellList, val code: SpellList, val baseStack: List<SpellDatum<*>>?, val acc: MutableList<SpellDatum<*>>): ContinuationFrame {
|
||||
|
||||
/** When halting, we add the stack state at halt to the stack accumulator, then return the original pre-Thoth stack, plus the accumulator. */
|
||||
override fun breakDownwards(stack: List<SpellDatum<*>>): Pair<Boolean, List<SpellDatum<*>>> {
|
||||
val newStack = baseStack!!.toMutableList()
|
||||
acc.addAll(stack)
|
||||
return Pair(true, appendBase(SpellDatum.make(acc)))
|
||||
newStack.add(SpellDatum.make(acc))
|
||||
return Pair(true, newStack)
|
||||
}
|
||||
|
||||
/** Step the Thoth computation, enqueueing one code evaluation. */
|
||||
override fun evaluate(continuation: MutableList<ContinuationFrame>, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
override fun evaluate(continuation: SpellContinuation, level: ServerLevel, harness: CastingHarness): CastResult {
|
||||
// If this isn't the very first Thoth step (i.e. no Thoth computations run yet)...
|
||||
if (!first) {
|
||||
// add everything we've added
|
||||
val stack = if (baseStack == null) {
|
||||
// init stack to the harness stack...
|
||||
harness.stack.toList()
|
||||
} else {
|
||||
// else save the stack to the accumulator and reuse the saved base stack.
|
||||
acc.addAll(harness.stack)
|
||||
baseStack
|
||||
}
|
||||
first = false
|
||||
|
||||
// If we still have data to process...
|
||||
val stackTop = if (data.nonEmpty) {
|
||||
// queue next datum for Thoth eval.
|
||||
val toEval = data.car
|
||||
data = data.cdr
|
||||
// Put this Thoth object: back on the stack for the next Thoth cycle,
|
||||
continuation.add(this)
|
||||
// and prep the Thoth'd code block for evaluation.
|
||||
continuation.add(Evaluate(code))
|
||||
// Push the next datum to the top of the stack.
|
||||
toEval
|
||||
val (stackTop, newCont) = if (data.nonEmpty) {
|
||||
Pair(
|
||||
data.car, // Push the next datum to the top of the stack,
|
||||
continuation
|
||||
// put the next Thoth object back on the stack for the next Thoth cycle,
|
||||
.pushFrame(ForEach(data.cdr, code, stack, acc))
|
||||
// and prep the Thoth'd code block for evaluation.
|
||||
.pushFrame(Evaluate(code))
|
||||
)
|
||||
} else {
|
||||
// Else, dump our final list onto the stack.
|
||||
SpellDatum.make(acc)
|
||||
Pair(SpellDatum.make(acc), continuation)
|
||||
}
|
||||
return CastResult(FunctionalData(appendBase(stackTop), 0, listOf(), false), ResolvedPatternType.OK, listOf())
|
||||
val tStack = stack.toMutableList()
|
||||
tStack.add(stackTop)
|
||||
return CastResult(newCont, FunctionalData(tStack, 0, listOf(), false), ResolvedPatternType.OK, listOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package at.petrak.hexcasting.api.spell.casting
|
||||
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingHarness.CastResult
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
|
||||
/**
|
||||
* A continuation during the execution of a spell.
|
||||
*/
|
||||
sealed interface SpellContinuation {
|
||||
object Done: SpellContinuation {}
|
||||
|
||||
data class NotDone(val frame: ContinuationFrame, val next: SpellContinuation): SpellContinuation {}
|
||||
|
||||
fun pushFrame(frame: ContinuationFrame): SpellContinuation = NotDone(frame, this)
|
||||
}
|
|
@ -9,20 +9,23 @@ import at.petrak.hexcasting.api.spell.casting.CastingContext
|
|||
import at.petrak.hexcasting.api.spell.casting.CastingHarness
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpEval : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
val instrs: SpellList = stack.getChecked(stack.lastIndex)
|
||||
stack.removeLastOrNull()
|
||||
|
||||
ctx.incDepth()
|
||||
|
||||
// if not installed already...
|
||||
if (!(continuation.isNotEmpty() && continuation.last() is ContinuationFrame.FinishEval)) {
|
||||
continuation.add(ContinuationFrame.FinishEval()) // install a break-boundary after eval
|
||||
val newCont = if (continuation is SpellContinuation.NotDone && continuation.frame is ContinuationFrame.FinishEval) {
|
||||
continuation
|
||||
} else {
|
||||
continuation.pushFrame(ContinuationFrame.FinishEval()) // install a break-boundary after eval
|
||||
}
|
||||
continuation.add(ContinuationFrame.Evaluate(instrs))
|
||||
|
||||
return OperationResult(stack, local, listOf())
|
||||
val frame = ContinuationFrame.Evaluate(instrs)
|
||||
return OperationResult(newCont.pushFrame(frame), stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import at.petrak.hexcasting.api.spell.OperationResult
|
|||
import at.petrak.hexcasting.api.spell.Operator
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpEvalDelay : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
return OperationResult(stack, local, listOf())
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
return OperationResult(continuation, stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@ import at.petrak.hexcasting.api.spell.casting.CastingHarness
|
|||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpForEach : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (stack.size < 2)
|
||||
throw MishapNotEnoughArgs(2, stack.size)
|
||||
|
||||
|
@ -21,8 +22,13 @@ object OpForEach : Operator {
|
|||
stack.removeLastOrNull()
|
||||
stack.removeLastOrNull()
|
||||
|
||||
continuation.add(ContinuationFrame.ForEach(true, datums, instrs, stack, mutableListOf()))
|
||||
val frame = ContinuationFrame.ForEach(datums, instrs, null, mutableListOf())
|
||||
|
||||
return OperationResult(stack, local, listOf())
|
||||
return OperationResult(
|
||||
continuation.pushFrame(frame),
|
||||
stack,
|
||||
local,
|
||||
listOf()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,20 @@ import at.petrak.hexcasting.api.spell.SpellDatum
|
|||
import at.petrak.hexcasting.api.spell.SpellList
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingHarness
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
|
||||
object OpHalt : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
var newStack = stack.toList()
|
||||
var done = false
|
||||
while (!done && continuation.isNotEmpty()) {
|
||||
var newCont = continuation
|
||||
while (!done && newCont is SpellContinuation.NotDone) {
|
||||
// Kotlin Y U NO destructuring assignment
|
||||
val newInfo = continuation.removeLast().breakDownwards(newStack)
|
||||
val newInfo = newCont.frame.breakDownwards(newStack)
|
||||
done = newInfo.first
|
||||
newStack = newInfo.second
|
||||
newCont = newCont.next
|
||||
}
|
||||
// if we hit no continuation boundaries (i.e. thoth/hermes exits), we've TOTALLY cleared the itinerary...
|
||||
if (!done) {
|
||||
|
@ -26,6 +28,6 @@ object OpHalt : Operator {
|
|||
newStack = listOf()
|
||||
}
|
||||
|
||||
return OperationResult(newStack, local, listOf())
|
||||
return OperationResult(newCont, newStack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package at.petrak.hexcasting.common.casting.operators.lists
|
|||
|
||||
import at.petrak.hexcasting.api.spell.*
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
|
@ -10,7 +10,7 @@ import kotlin.math.abs
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
object OpLastNToList : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (stack.isEmpty())
|
||||
throw MishapNotEnoughArgs(1, 0)
|
||||
val arg = stack.takeLast(1).getChecked<Double>(0)
|
||||
|
@ -31,6 +31,6 @@ object OpLastNToList : Operator {
|
|||
}
|
||||
stack.addAll(output.asSpellResult)
|
||||
|
||||
return OperationResult(stack, local, listOf())
|
||||
return OperationResult(continuation, stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@ import at.petrak.hexcasting.api.spell.OperationResult
|
|||
import at.petrak.hexcasting.api.spell.Operator
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpPeekLocal : Operator {
|
||||
override fun operate(
|
||||
continuation: MutableList<ContinuationFrame>,
|
||||
continuation: SpellContinuation,
|
||||
stack: MutableList<SpellDatum<*>>,
|
||||
local: SpellDatum<*>,
|
||||
ctx: CastingContext
|
||||
): OperationResult {
|
||||
stack.add(local)
|
||||
return OperationResult(stack, local, listOf())
|
||||
return OperationResult(continuation, stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import at.petrak.hexcasting.api.spell.Operator
|
|||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpPushLocal : Operator {
|
||||
override fun operate(
|
||||
continuation: MutableList<ContinuationFrame>,
|
||||
continuation: SpellContinuation,
|
||||
stack: MutableList<SpellDatum<*>>,
|
||||
local: SpellDatum<*>,
|
||||
ctx: CastingContext
|
||||
|
@ -17,6 +17,6 @@ object OpPushLocal : Operator {
|
|||
if (stack.isEmpty())
|
||||
throw MishapNotEnoughArgs(1, 0)
|
||||
val newLocal = stack.removeLast()
|
||||
return OperationResult(stack, newLocal, listOf())
|
||||
return OperationResult(continuation, stack, newLocal, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,19 @@ import at.petrak.hexcasting.api.spell.Operator
|
|||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import net.minecraft.Util
|
||||
|
||||
object OpPrint : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (stack.isEmpty()) {
|
||||
throw MishapNotEnoughArgs(1, 0)
|
||||
}
|
||||
val datum = stack[stack.lastIndex]
|
||||
return OperationResult(
|
||||
stack, local, listOf(
|
||||
continuation, stack, local, listOf(
|
||||
OperatorSideEffect.AttemptSpell(Spell(datum), false)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -6,10 +6,10 @@ import at.petrak.hexcasting.api.spell.Operator
|
|||
import at.petrak.hexcasting.api.spell.getChecked
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
import kotlin.math.abs
|
||||
|
@ -18,7 +18,7 @@ import kotlin.math.roundToInt
|
|||
|
||||
// "lehmer code"
|
||||
object OpAlwinfyHasAscendedToABeingOfPureMath : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (stack.isEmpty())
|
||||
throw MishapNotEnoughArgs(1, 0) // todo: better message?
|
||||
|
||||
|
@ -56,6 +56,7 @@ object OpAlwinfyHasAscendedToABeingOfPureMath : Operator {
|
|||
val cost = (ln((strides.lastOrNull() ?: 0).toFloat()) * ManaConstants.DUST_UNIT).toInt()
|
||||
|
||||
return OperationResult(
|
||||
continuation,
|
||||
stack,
|
||||
local,
|
||||
listOf(OperatorSideEffect.ConsumeMana(cost))
|
||||
|
|
|
@ -5,7 +5,7 @@ import at.petrak.hexcasting.api.spell.Operator
|
|||
import at.petrak.hexcasting.api.spell.getChecked
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
|
||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||
import net.minecraft.network.chat.TranslatableComponent
|
||||
|
@ -13,7 +13,7 @@ import kotlin.math.abs
|
|||
import kotlin.math.roundToInt
|
||||
|
||||
object OpFisherman : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
if (stack.isEmpty())
|
||||
throw MishapNotEnoughArgs(1, 0)
|
||||
val arg = stack.getChecked<Double>(stack.lastIndex)
|
||||
|
@ -32,6 +32,6 @@ object OpFisherman : Operator {
|
|||
)
|
||||
}
|
||||
|
||||
return OperationResult(stack, local, listOf())
|
||||
return OperationResult(continuation, stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ import at.petrak.hexcasting.api.spell.OperationResult
|
|||
import at.petrak.hexcasting.api.spell.Operator
|
||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||
import at.petrak.hexcasting.api.spell.casting.ContinuationFrame
|
||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||
|
||||
object OpStackSize : Operator {
|
||||
override fun operate(continuation: MutableList<ContinuationFrame>, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
override fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult {
|
||||
stack.add(SpellDatum.make(stack.size.toDouble()))
|
||||
return OperationResult(stack, local, listOf())
|
||||
return OperationResult(continuation, stack, local, listOf())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue