@@ -16,6 +16,7 @@ import at.petrak.hexcasting.common.casting.actions.eval.OpEval
1616import gay.`object`.hexdebug.adapter.LaunchArgs
1717import gay.`object`.hexdebug.casting.eval.FrameBreakpoint
1818import gay.`object`.hexdebug.casting.eval.IDebugCastEnv
19+ import gay.`object`.hexdebug.casting.eval.debugCastEnv
1920import gay.`object`.hexdebug.debugger.allocators.SourceAllocator
2021import gay.`object`.hexdebug.debugger.allocators.VariablesAllocator
2122import gay.`object`.hexdebug.utils.ceilToPow
@@ -29,21 +30,26 @@ import org.eclipse.lsp4j.debug.LoadedSourceEventArgumentsReason as LoadedSourceR
2930class HexDebugger (
3031 private val initArgs : InitializeRequestArguments ,
3132 private val launchArgs : LaunchArgs ,
32- val vm : CastingVM ,
33+ private val defaultEnv : CastingEnvironment ,
3334 private val world : ServerLevel ,
3435 private val onExecute : ((Iota ) -> Unit )? = null ,
3536 iotas : List <Iota >,
37+ private var image : CastingImage = CastingImage (),
3638) {
3739 constructor (
3840 initArgs: InitializeRequestArguments ,
3941 launchArgs: LaunchArgs ,
4042 castArgs: CastArgs ,
41- ) : this (initArgs, launchArgs, CastingVM .empty(castArgs.env), castArgs.world, castArgs.onExecute, castArgs.iotas)
43+ image: CastingImage = CastingImage (),
44+ ) : this (initArgs, launchArgs, castArgs.env, castArgs.world, castArgs.onExecute, castArgs.iotas, image)
4245
4346 var lastEvaluatedMetadata: IotaMetadata ? = null
4447 private set
4548
46- private val debugCastEnv = vm.env as IDebugCastEnv
49+ // ensure we passed a debug cast env to help catch errors early
50+ init {
51+ defaultEnv as IDebugCastEnv
52+ }
4753
4854 private val variablesAllocator = VariablesAllocator ()
4955 private val sourceAllocator = SourceAllocator (iotas.hashCode())
@@ -94,6 +100,8 @@ class HexDebugger(
94100
95101 private val nextFrame get() = (nextContinuation as ? NotDone )?.frame
96102
103+ private fun getVM (env : CastingEnvironment ? = null) = CastingVM (image, env ? : defaultEnv)
104+
97105 private fun registerNewSource (frame : ContinuationFrame ): Source ? = getIotas(frame)?.let (::registerNewSource)
98106
99107 private fun registerNewSource (iotas : Iterable <Iota >): Source ? {
@@ -154,7 +162,7 @@ class HexDebugger(
154162 val scopes = mutableListOf (
155163 Scope ().apply {
156164 name = " Data"
157- variablesReference = vm. image.run {
165+ variablesReference = image.run {
158166 variablesAllocator.add(
159167 toVariable(" Stack" , stack.asReversed()),
160168 toVariable(" Ravenmind" , getRavenmind()),
@@ -163,7 +171,7 @@ class HexDebugger(
163171 },
164172 Scope ().apply {
165173 name = " State"
166- variablesReference = vm. image.run {
174+ variablesReference = image.run {
167175 val variables = mutableListOf (
168176 toVariable(" OpsConsumed" , opsConsumed.toString()),
169177 toVariable(" EscapeNext" , escapeNext.toString()),
@@ -241,9 +249,9 @@ class HexDebugger(
241249 }
242250 }
243251
244- private fun getRavenmind () = vm. image.userData.let {
252+ private fun getRavenmind () = image.userData.let {
245253 if (it.contains(HexAPI .RAVENMIND_USERDATA )) {
246- IotaType .deserialize(it.getCompound(HexAPI .RAVENMIND_USERDATA ), vm.env .world)
254+ IotaType .deserialize(it.getCompound(HexAPI .RAVENMIND_USERDATA ), defaultEnv .world)
247255 } else {
248256 NullIota ()
249257 }
@@ -350,7 +358,7 @@ class HexDebugger(
350358 ?.let { breakpoints[it.source.sourceReference]?.get(it.line) }
351359 ? : return false
352360
353- val escapeNext = vm. image.escapeNext || vm. image.parenCount > 0
361+ val escapeNext = image.escapeNext || image.parenCount > 0
354362
355363 return when (breakpointMode) {
356364 SourceBreakpointMode .EVALUATED -> ! escapeNext
@@ -359,6 +367,8 @@ class HexDebugger(
359367 }
360368 }
361369
370+ fun generateDescs () = getVM().generateDescs()
371+
362372 private fun getClientView (vm : CastingVM ): ExecutionClientView {
363373 val (stackDescs, ravenmind) = vm.generateDescs()
364374 val isStackClear = nextContinuation is Done // only close the window if we're done evaluating
@@ -368,13 +378,13 @@ class HexDebugger(
368378 /* *
369379 * Use [DebugAdapter.evaluate][gay.object.hexdebug.adapter.DebugAdapter.evaluate] instead.
370380 */
371- internal fun evaluate (list : SpellList ): DebugStepResult {
381+ internal fun evaluate (env : CastingEnvironment , list : SpellList ): DebugStepResult {
372382 val startedEvaluating = evaluatorResetData == null
373383 if (startedEvaluating) {
374- evaluatorResetData = Pair (nextContinuation, vm. image)
384+ evaluatorResetData = Pair (nextContinuation, image)
375385 }
376386 nextContinuation = nextContinuation.pushFrame(FrameEvaluate (list, false ))
377- return executeOnce( ).copy(startedEvaluating = startedEvaluating)
387+ return executeNextDebugStep(getVM(env) ).copy(startedEvaluating = startedEvaluating)
378388 }
379389
380390 /* *
@@ -383,7 +393,7 @@ class HexDebugger(
383393 internal fun resetEvaluator () {
384394 evaluatorResetData?.also { (continuation, image) ->
385395 nextContinuation = continuation
386- vm .image = image
396+ this .image = image
387397 evaluatorResetData = null
388398 }
389399 evaluatorUIPatterns.clear()
@@ -400,14 +410,15 @@ class HexDebugger(
400410 }
401411
402412 fun executeUntilStopped (stepType : RequestStepType ? = null): DebugStepResult {
413+ val vm = getVM()
403414 var lastResult: DebugStepResult ? = null
404415 var isEscaping: Boolean? = null
405416 var stepDepth = 0
406417 var shouldStop = false
407418 var hitBreakpoint = false
408419
409420 while (true ) {
410- val result = executeOnce( exactlyOnce = true ).let {
421+ val result = executeNextDebugStep(vm, exactlyOnce = true ).let {
411422 if (it.isDone) return it
412423 lastResult?.plus(it) ? : it
413424 }
@@ -452,8 +463,10 @@ class HexDebugger(
452463 }
453464 }
454465
466+ fun executeOnce () = executeNextDebugStep(getVM())
467+
455468 // Copy of CastingVM.queueExecuteAndWrapIotas to allow stepping by one pattern at a time.
456- fun executeOnce ( exactlyOnce : Boolean = false): DebugStepResult {
469+ private fun executeNextDebugStep ( vm : CastingVM , exactlyOnce : Boolean = false): DebugStepResult {
457470 var stepResult = DebugStepResult (StopReason .STEP )
458471
459472 var continuation = nextContinuation // bind locally so we can do smart casting
@@ -464,7 +477,7 @@ class HexDebugger(
464477 // Begin aggregating info
465478 val info = CastingVM .TempControllerInfo (earlyExit = false )
466479 while (continuation is NotDone && ! info.earlyExit) {
467- debugCastEnv.reset()
480+ vm. debugCastEnv.reset()
468481
469482 // Take the top of the continuation stack...
470483 val frame = continuation.frame
@@ -506,7 +519,7 @@ class HexDebugger(
506519 onExecute?.invoke(castResult.cast)
507520 }
508521
509- val stepType = getStepType(castResult, continuation, newContinuation)
522+ val stepType = getStepType(vm, castResult, continuation, newContinuation)
510523 if (newContinuation is NotDone ) {
511524 setIotaOverrides(castResult, continuation, newContinuation, stepType)
512525
@@ -516,7 +529,7 @@ class HexDebugger(
516529 }
517530
518531 // insert a virtual FrameFinishEval if OpEval didn't (ie. if we did a TCO)
519- if (launchArgs.showTailCallFrames && debugCastEnv.lastEvaluatedAction is OpEval ) {
532+ if (launchArgs.showTailCallFrames && vm. debugCastEnv.lastEvaluatedAction is OpEval ) {
520533 val invokeMeta = iotaMetadata[castResult.cast]
521534 val nextInvokeMeta = frameInvocationMetadata[newContinuation.next]?.invoke()
522535 if (invokeMeta != null && invokeMeta != nextInvokeMeta) {
@@ -558,11 +571,12 @@ class HexDebugger(
558571 virtualFrames[continuation]?.clear()
559572
560573 nextContinuation = continuation
574+ image = vm.image
561575
562- if (continuation is Done ) {
563- stepResult = stepResult.done()
564- }
565- return stepResult .copy(clientInfo = getClientView(vm))
576+ return when (continuation) {
577+ is Done -> stepResult.done()
578+ is NotDone -> stepResult
579+ } .copy(clientInfo = getClientView(vm))
566580 }
567581
568582 private fun shouldStopAtFrame (continuation : SpellContinuation ) =
@@ -608,6 +622,7 @@ class HexDebugger(
608622 }
609623
610624 private fun getStepType (
625+ vm : CastingVM ,
611626 castResult : CastResult ,
612627 continuation : NotDone ,
613628 newContinuation : SpellContinuation ,
@@ -645,7 +660,7 @@ class HexDebugger(
645660 return DebugStepType .IN
646661 }
647662
648- return debugCastEnv.lastDebugStepType
663+ return vm. debugCastEnv.lastDebugStepType
649664 }
650665
651666 private fun setIotaOverrides (
@@ -686,7 +701,7 @@ class HexDebugger(
686701 private fun iotaToString (iota : Iota , isSource : Boolean = false): String = when (iota) {
687702 // i feel like hex should have a thing for this...
688703 is PatternIota -> HexAPI .instance().run {
689- when (val lookup = PatternRegistryManifest .matchPattern(iota.pattern, vm.env , false )) {
704+ when (val lookup = PatternRegistryManifest .matchPattern(iota.pattern, defaultEnv , false )) {
690705 is PatternShapeMatch .Normal -> getActionI18n(lookup.key, false )
691706 is PatternShapeMatch .PerWorld -> getActionI18n(lookup.key, true )
692707 is PatternShapeMatch .Special -> lookup.handler.name
0 commit comments