@@ -13,6 +13,7 @@ import at.petrak.hexcasting.api.casting.mishaps.Mishap
1313import at.petrak.hexcasting.api.casting.mishaps.MishapInternalException
1414import at.petrak.hexcasting.common.casting.PatternRegistryManifest
1515import at.petrak.hexcasting.common.casting.actions.eval.OpEval
16+ import at.petrak.hexcasting.common.lib.hex.HexEvalSounds
1617import gay.`object`.hexdebug.adapter.LaunchArgs
1718import gay.`object`.hexdebug.casting.eval.FrameBreakpoint
1819import gay.`object`.hexdebug.casting.eval.IDebugCastEnv
@@ -67,7 +68,9 @@ class HexDebugger(
6768
6869 val evaluatorUIPatterns = mutableListOf<ResolvedPattern >()
6970
70- private var evaluatorResetData: Pair <SpellContinuation , CastingImage >? = null
71+ private var evaluatorResetData: EvaluatorResetData ? = null
72+
73+ private var isAtCaughtMishap = false
7174
7275 private var lastResolutionType = ResolvedPatternType .UNRESOLVED
7376
@@ -379,29 +382,43 @@ class HexDebugger(
379382 * Use [DebugAdapter.evaluate][gay.object.hexdebug.adapter.DebugAdapter.evaluate] instead.
380383 */
381384 internal fun evaluate (env : CastingEnvironment , list : SpellList ): DebugStepResult {
385+ val vm = getVM(env)
386+
387+ if (isAtCaughtMishap) {
388+ // manually trigger the mishap sound
389+ // TODO: this feels scuffed.
390+ env.postExecution(
391+ CastResult (NullIota (), nextContinuation, null , listOf (), lastResolutionType, HexEvalSounds .MISHAP )
392+ )
393+ return DebugStepResult (StopReason .EXCEPTION , clientInfo = getClientView(vm))
394+ }
395+
382396 val startedEvaluating = evaluatorResetData == null
383397 if (startedEvaluating) {
384- evaluatorResetData = Pair (nextContinuation, image)
398+ evaluatorResetData = EvaluatorResetData (nextContinuation, image, lastResolutionType, isAtCaughtMishap )
385399 }
400+
386401 nextContinuation = nextContinuation.pushFrame(FrameEvaluate (list, false ))
387- return executeNextDebugStep(getVM(env) ).copy(startedEvaluating = startedEvaluating)
402+ return executeNextDebugStep(vm, doStaffMishaps = true ).copy(startedEvaluating = startedEvaluating)
388403 }
389404
390405 /* *
391406 * Use [DebugAdapter.resetEvaluator][gay.object.hexdebug.adapter.DebugAdapter.resetEvaluator] instead.
392407 */
393- internal fun resetEvaluator () {
394- evaluatorResetData?.also { (continuation, image) ->
395- nextContinuation = continuation
396- this .image = image
397- evaluatorResetData = null
408+ internal fun resetEvaluator () = (evaluatorResetData != null ).also { _ ->
409+ evaluatorResetData?.also {
410+ nextContinuation = it.continuation
411+ image = it.image
412+ lastResolutionType = it.lastResolutionType
413+ isAtCaughtMishap = it.isAtCaughtMishap
398414 }
415+ evaluatorResetData = null
399416 evaluatorUIPatterns.clear()
400417 }
401418
402419 fun start (): DebugStepResult {
403420 return if (launchArgs.stopOnEntry) {
404- DebugStepResult (StopReason .ENTRY )
421+ DebugStepResult (StopReason .STARTED )
405422 } else if (isAtBreakpoint()) {
406423 DebugStepResult (StopReason .BREAKPOINT )
407424 } else {
@@ -418,12 +435,11 @@ class HexDebugger(
418435 var hitBreakpoint = false
419436
420437 while (true ) {
421- val result = executeNextDebugStep(vm, exactlyOnce = true ).let {
422- if (it.isDone) return it
423- lastResult?.plus(it) ? : it
424- }
438+ val result = executeNextDebugStep(vm, exactlyOnce = true ).let { lastResult?.plus(it) ? : it }
425439 lastResult = result
426440
441+ if (result.reason.stopImmediately) return result
442+
427443 if (isAtBreakpoint()) {
428444 hitBreakpoint = true
429445 }
@@ -466,7 +482,11 @@ class HexDebugger(
466482 fun executeOnce () = executeNextDebugStep(getVM())
467483
468484 // Copy of CastingVM.queueExecuteAndWrapIotas to allow stepping by one pattern at a time.
469- private fun executeNextDebugStep (vm : CastingVM , exactlyOnce : Boolean = false): DebugStepResult {
485+ private fun executeNextDebugStep (
486+ vm : CastingVM ,
487+ exactlyOnce : Boolean = false,
488+ doStaffMishaps : Boolean = false,
489+ ): DebugStepResult {
470490 var stepResult = DebugStepResult (StopReason .STEP )
471491
472492 var continuation = nextContinuation // bind locally so we can do smart casting
@@ -496,13 +516,14 @@ class HexDebugger(
496516 // if something went wrong, push a breakpoint or stop immediately
497517 // and save the old image so we can see the stack BEFORE the mishap instead of after
498518 // TODO: maybe implement a way to see the stack at each call frame instead?
499- val (newContinuation, preMishapImage) = if (castResult.resolutionType.success) {
519+ val (newContinuation, preMishapImage) = if (castResult.resolutionType.success || doStaffMishaps ) {
500520 Pair (castResult.continuation, null )
501521 } else if (ExceptionBreakpointType .UNCAUGHT_MISHAPS in exceptionBreakpoints) {
522+ isAtCaughtMishap = true
502523 stepResult = stepResult.copy(reason = StopReason .EXCEPTION )
503524 Pair (castResult.continuation.pushFrame(FrameBreakpoint .fatal()), vm.image)
504525 } else {
505- Pair (Done , vm.image )
526+ Pair (Done , null )
506527 }
507528
508529 // we use this when printing to the console, so this should happen BEFORE vm.env.postExecution (ie. for mishaps)
@@ -560,6 +581,7 @@ class HexDebugger(
560581 info.earlyExit = info.earlyExit || ! castResult.resolutionType.success
561582
562583 // this needs to be after performSideEffects, since that's where mishaps mess with the stack
584+ // note: preMishapImage is only non-null if we actually encountered a mishap
563585 if (preMishapImage != null ) vm.image = preMishapImage
564586
565587 if (exactlyOnce || shouldStopAtFrame(continuation)) {
@@ -738,6 +760,13 @@ class HexDebugger(
738760 }
739761 }
740762 }
763+
764+ data class EvaluatorResetData (
765+ val continuation : SpellContinuation ,
766+ val image : CastingImage ,
767+ val lastResolutionType : ResolvedPatternType ,
768+ val isAtCaughtMishap : Boolean ,
769+ )
741770}
742771
743772val SpellContinuation .frame get() = (this as ? NotDone )?.frame
0 commit comments