diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/AlternativeEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/AlternativeEmbedding.scala index 63e4ed2d7..7d9c7b27c 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/AlternativeEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/AlternativeEmbedding.scala @@ -105,7 +105,8 @@ private [backend] object Choice { (implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = { val handler = state.freshLabel() val skip = state.freshLabel() - instrs += new instructions.PushHandlerAndState(handler, saveHints = true, hideHints = false) + // FIXME: check this, this is the only one that uses this instruction, and I think it was a mistake + instrs += new instructions.PushHandlerAndStateAndClearHints(handler) suspend(p.codeGen[M, R]) >> { instrs += new instructions.JumpAndPopState(skip) instrs += new instructions.Label(handler) @@ -119,7 +120,7 @@ private [backend] object Choice { (implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = { val handler = state.freshLabel() val skip = state.freshLabel() - instrs += new instructions.PushHandlerAndCheck(handler, saveHints = true) + instrs += new instructions.PushHandlerAndClearHints(handler) suspend(p.codeGen[M, R]) >> { instrs += new instructions.JumpAndPopCheck(skip) instrs += new instructions.Label(handler) diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/ErrorEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/ErrorEmbedding.scala index 8d3062344..18d3d38aa 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/ErrorEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/ErrorEmbedding.scala @@ -11,18 +11,17 @@ import parsley.internal.deepembedding.singletons._ import parsley.internal.machine.instructions private [deepembedding] final class ErrorLabel[A](val p: StrictParsley[A], private val labels: scala.Seq[String]) extends ScopedUnary[A, A] { - // This needs to save the hints because label should relabel only the hints generated _within_ its context, then merge with the originals after - override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndCheck(label, saveHints = true) + override def setup(label: Int): instructions.Instr = new instructions.PushHandler(label) // was AndClearHints override def instr: instructions.Instr = new instructions.RelabelHints(labels) override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabelForRelabelError(labels) // don't need to be limited to not hidden when the thing can never internally generate hints final override def optimise: StrictParsley[A] = p match { - case CharTok(c) /*if ct.expected ne Hidden */ => new CharTok(c, Label(labels: _*)).asInstanceOf[StrictParsley[A]] - case SupplementaryCharTok(c) /*if ct.expected ne Hidden */ => new SupplementaryCharTok(c, Label(labels: _*)).asInstanceOf[StrictParsley[A]] - case StringTok(s) /*if st.expected ne Hidden */ => new StringTok(s, Label(labels: _*)).asInstanceOf[StrictParsley[A]] - case Satisfy(f) /*if sat.expected ne Hidden */ => new Satisfy(f, Label(labels: _*)).asInstanceOf[StrictParsley[A]] - case UniSatisfy(f) /*if sat.expected ne Hidden */ => new UniSatisfy(f, Label(labels: _*)).asInstanceOf[StrictParsley[A]] + case CharTok(c) => new CharTok(c, Label(labels: _*)).asInstanceOf[StrictParsley[A]] + case SupplementaryCharTok(c) => new SupplementaryCharTok(c, Label(labels: _*)).asInstanceOf[StrictParsley[A]] + case StringTok(s) => new StringTok(s, Label(labels: _*)).asInstanceOf[StrictParsley[A]] + case Satisfy(f) => new Satisfy(f, Label(labels: _*)).asInstanceOf[StrictParsley[A]] + case UniSatisfy(f) => new UniSatisfy(f, Label(labels: _*)).asInstanceOf[StrictParsley[A]] case ErrorLabel(p, label2) if label2.nonEmpty => ErrorLabel(p, labels) case _ => this } @@ -32,8 +31,7 @@ private [deepembedding] final class ErrorLabel[A](val p: StrictParsley[A], priva // $COVERAGE-ON$ } private [deepembedding] final class ErrorHide[A](val p: StrictParsley[A]) extends ScopedUnary[A, A] { - // This needs to save the hints because label should hints only the hints generated _within_ its context, then merge with the originals after - override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndCheck(label, saveHints = true) + override def setup(label: Int): instructions.Instr = new instructions.PushHandler(label) override def instr: instructions.Instr = instructions.HideHints override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.HideErrorAndFail) @@ -43,8 +41,8 @@ private [deepembedding] final class ErrorHide[A](val p: StrictParsley[A]) extend // $COVERAGE-ON$ } private [deepembedding] final class ErrorExplain[A](val p: StrictParsley[A], reason: String) extends ScopedUnary[A, A] { - override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndCheck(label, saveHints = false) - override def instr: instructions.Instr = instructions.PopHandlerAndCheck + override def setup(label: Int): instructions.Instr = new instructions.PushHandler(label) + override def instr: instructions.Instr = instructions.PopHandler override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabelForApplyReason(reason) // $COVERAGE-OFF$ @@ -52,7 +50,7 @@ private [deepembedding] final class ErrorExplain[A](val p: StrictParsley[A], rea // $COVERAGE-ON$ } -private [deepembedding] final class ErrorAmend[A](val p: StrictParsley[A], partial: Boolean) extends ScopedUnaryWithState[A, A](false) { +private [deepembedding] final class ErrorAmend[A](val p: StrictParsley[A], partial: Boolean) extends ScopedUnaryWithState[A, A] { override val instr: instructions.Instr = instructions.PopHandlerAndState override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.AmendAndFail(partial)) @@ -82,8 +80,8 @@ private [deepembedding] final class ErrorDislodge[A](n: Int, val p: StrictParsle private [deepembedding] final class ErrorLexical[A](val p: StrictParsley[A]) extends ScopedUnary[A, A] { // This needs to save the hints because error label will relabel the first hint, which because the list is ordered would be the hints that came _before_ // entering labels context. Instead label should relabel the first hint generated _within_ its context, then merge with the originals after - override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndCheck(label, saveHints = false) - override def instr: instructions.Instr = instructions.PopHandlerAndCheck + override def setup(label: Int): instructions.Instr = new instructions.PushHandler(label) + override def instr: instructions.Instr = instructions.PopHandler override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.SetLexicalAndFail) diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/GeneralisedEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/GeneralisedEmbedding.scala index 3e2c02dcd..1cea419b5 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/GeneralisedEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/GeneralisedEmbedding.scala @@ -35,6 +35,6 @@ private [backend] abstract class ScopedUnary[A, B] extends Unary[A, B] { } } -private [backend] abstract class ScopedUnaryWithState[A, B](doesNotProduceHints: Boolean) extends ScopedUnary[A, B] { - override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndState(label, doesNotProduceHints, doesNotProduceHints) +private [backend] abstract class ScopedUnaryWithState[A, B] extends ScopedUnary[A, B] { + override def setup(label: Int): instructions.Instr = new instructions.PushHandlerAndState(label) } diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/IterativeEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/IterativeEmbedding.scala index 6fa716b28..0a605febb 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/IterativeEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/IterativeEmbedding.scala @@ -27,7 +27,7 @@ private [backend] sealed abstract class ManyLike[A, B](name: String, unit: B) ex val body = state.freshLabel() val handler = state.freshLabel() preamble(instrs) - instrs += new instructions.PushHandlerIterative(handler) + instrs += new instructions.PushHandler(handler) instrs += new instructions.Label(body) suspend(p.codeGen[M, R]) |> { instrs += new instructions.Label(handler) @@ -66,7 +66,7 @@ private [deepembedding] final class ChainPost[A](p: StrictParsley[A], op: Strict val body = state.freshLabel() val handler = state.freshLabel() suspend(p.codeGen[M, R]) >> { - instrs += new instructions.PushHandlerIterative(handler) + instrs += new instructions.PushHandler(handler) instrs += new instructions.Label(body) suspend(op.codeGen[M, R]) |> { instrs += new instructions.Label(handler) @@ -83,7 +83,7 @@ private [deepembedding] final class ChainPre[A](p: StrictParsley[A], op: StrictP val body = state.freshLabel() val handler = state.freshLabel() instrs += new instructions.Push(identity[Any] _) - instrs += new instructions.PushHandlerIterative(handler) + instrs += new instructions.PushHandler(handler) instrs += new instructions.Label(body) suspend(op.codeGen[M, R]) >> { instrs += new instructions.Label(handler) @@ -102,7 +102,7 @@ private [deepembedding] final class Chainl[A, B](init: StrictParsley[B], p: Stri val body = state.freshLabel() val handler = state.freshLabel() suspend(init.codeGen[M, R]) >> { - instrs += new instructions.PushHandlerIterative(handler) + instrs += new instructions.PushHandler(handler) instrs += new instructions.Label(body) op.codeGen[M, R] >> suspend(p.codeGen[M, R]) |> { @@ -120,13 +120,14 @@ private [deepembedding] final class Chainr[A, B](p: StrictParsley[A], op: Strict def inlinable: Boolean = false override def codeGen[M[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit]= { val body = state.freshLabel() - val handler1 = state.getLabel(instructions.ChainrWholeHandler) + // handler1 is where the check offset is kept + val handler1 = state.getLabel(instructions.Refail) val handler2 = state.freshLabel() instrs += new instructions.Push(identity[Any] _) - instrs += new instructions.PushHandlerIterative(handler1) + instrs += new instructions.PushHandler(handler1) instrs += new instructions.Label(body) suspend(p.codeGen[M, R]) >> { - instrs += new instructions.PushHandlerIterative(handler2) + instrs += new instructions.PushHandler(handler2) suspend(op.codeGen[M, R]) |> { instrs += new instructions.ChainrJump(body) instrs += new instructions.Label(handler2) @@ -145,10 +146,10 @@ private [deepembedding] final class SepEndBy1[A, B](p: StrictParsley[A], sep: St val handler1 = state.freshLabel() val handler2 = state.freshLabel() instrs += new instructions.Fresh(mutable.ListBuffer.empty[Any]) - instrs += new instructions.PushHandlerIterative(handler1) + instrs += new instructions.PushHandler(handler1) instrs += new instructions.Label(body) suspend(p.codeGen[M, R]) >> { - instrs += new instructions.PushHandlerIterative(handler2) + instrs += new instructions.PushHandler(handler2) suspend(sep.codeGen[M, R]) |> { instrs += new instructions.SepEndBy1Jump(body) instrs += new instructions.Label(handler2) diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/PrimitiveEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/PrimitiveEmbedding.scala index 78db7bd22..16d15d5c1 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/PrimitiveEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/PrimitiveEmbedding.scala @@ -14,7 +14,7 @@ import parsley.internal.deepembedding.singletons._ import parsley.internal.machine.instructions import StrictParsley.InstrBuffer -private [deepembedding] final class Attempt[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A](false) { +private [deepembedding] final class Attempt[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A] { override val instr: instructions.Instr = instructions.PopHandlerAndState override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.RestoreAndFail) @@ -28,7 +28,7 @@ private [deepembedding] final class Attempt[A](val p: StrictParsley[A]) extends final override def pretty(p: String): String = s"attempt($p)" // $COVERAGE-ON$ } -private [deepembedding] final class Look[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A](true) { +private [deepembedding] final class Look[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A] { override val instr: instructions.Instr = instructions.RestoreHintsAndState override def instrNeedsLabel: Boolean = false override def handlerLabel(state: CodeGenState): Int = state.getLabel(instructions.PopStateRestoreHintsAndFail) @@ -43,7 +43,7 @@ private [deepembedding] final class NotFollowedBy[A](val p: StrictParsley[A]) ex }*/ final override def codeGen[M[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = { val handler = state.freshLabel() - instrs += new instructions.PushHandlerAndState(handler, saveHints = true, hideHints = true) + instrs += new instructions.PushHandlerAndState(handler) suspend[M, R, Unit](p.codeGen) |> { instrs += instructions.NegLookFail instrs += new instructions.Label(handler) diff --git a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/SelectiveEmbedding.scala b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/SelectiveEmbedding.scala index 095028aaf..3fe7e0b21 100644 --- a/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/SelectiveEmbedding.scala +++ b/parsley/shared/src/main/scala/parsley/internal/deepembedding/backend/SelectiveEmbedding.scala @@ -77,7 +77,7 @@ private [backend] sealed abstract class FilterLike[A, B] extends StrictParsley[B val handler1 = state.getLabel(instructions.PopStateAndFail) val handler2 = state.getLabel(instructions.AmendAndFail(false)) val jumpLabel = state.freshLabel() - instrs += new instructions.PushHandlerAndState(handler1, saveHints = false, hideHints = false) + instrs += new instructions.PushHandlerAndState(handler1) suspend(p.codeGen[M, R]) >> { instrs += instr(handler2, jumpLabel) suspend(err.codeGen[M, R]) |> { diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala b/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala index 8b2fa885d..ba11fc84b 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/Context.scala @@ -18,7 +18,7 @@ import parsley.internal.errors.{CaretWidth, ExpectItem, LineBuilder, UnexpectDes import parsley.internal.machine.errors.{ClassicFancyError, DefuncError, DefuncHints, EmptyHints, ErrorItemBuilder, ExpectedError, UnexpectedError} import instructions.Instr -import stacks.{ArrayStack, CallStack, CheckStack, ErrorStack, HandlerStack, HintStack, Stack, StateStack}, Stack.StackExt +import stacks.{ArrayStack, CallStack, ErrorStack, HandlerStack, Stack, StateStack}, Stack.StackExt private [parsley] final class Context(private [machine] var instrs: Array[Instr], private [machine] val input: String, @@ -35,7 +35,6 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] /** State stack consisting of offsets and positions that can be rolled back */ private [machine] var states: StateStack = Stack.empty /** Stack consisting of offsets at previous checkpoints, which may query to test for consumed input */ - private [machine] var checkStack: CheckStack = Stack.empty /** Current operational status of the machine */ private [machine] var good: Boolean = true private [machine] var running: Boolean = true @@ -53,23 +52,14 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] private [machine] var debuglvl: Int = 0 // NEW ERROR MECHANISMS - private var hints: DefuncHints = EmptyHints + private [machine] var hints: DefuncHints = EmptyHints private var hintsValidOffset = 0 - private var hintStack = Stack.empty[HintStack] private [machine] var errs: ErrorStack = Stack.empty - private [machine] def saveHints(shadow: Boolean): Unit = { - hintStack = new HintStack(hints, hintsValidOffset, hintStack) - if (!shadow) hints = EmptyHints - } private [machine] def restoreHints(): Unit = { - val hintFrame = this.hintStack - this.hintsValidOffset = hintFrame.validOffset + val hintFrame = this.handlers + this.hintsValidOffset = hintFrame.hintOffset this.hints = hintFrame.hints - this.commitHints() - } - private [machine] def commitHints(): Unit = { - this.hintStack = this.hintStack.tail } /* Error Debugging Info */ @@ -79,9 +69,8 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] /* ERROR RELABELLING BEGIN */ private [machine] def mergeHints(): Unit = { - val hintFrame = this.hintStack - if (hintFrame.validOffset == offset) this.hints = hintFrame.hints.merge(this.hints) - commitHints() + val hintFrame = this.handlers + if (hintFrame.hintOffset == offset) this.hints = hintFrame.hints.merge(this.hints) } private [machine] def replaceHint(labels: Iterable[String]): Unit = hints = hints.rename(labels) private [machine] def popHints(): Unit = hints = hints.pop @@ -114,7 +103,7 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] } private [machine] def updateCheckOffset() = { - this.checkStack.offset = this.offset + this.handlers.check = this.offset } // $COVERAGE-OFF$ @@ -129,10 +118,8 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] | rets = ${calls.mkString(", ")} | handlers = ${handlers.mkString(", ")} | recstates = ${states.mkString(", ")} - | checks = ${checkStack.mkString(", ")} | registers = ${regs.zipWithIndex.map{case (r, i) => s"r$i = $r"}.toList.mkString("\n ")} | errors = ${errs.mkString(", ")} - | hints = ($hintsValidOffset, ${hints.toSet}):${hintStack.mkString(", ")} |]""".stripMargin } // $COVERAGE-ON$ @@ -147,18 +134,14 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] assert(stack.size == 1, s"stack must end a parse with exactly one item, it has ${stack.size}") assert(calls.isEmpty, "there must be no more calls to unwind on end of parser") assert(handlers.isEmpty, "there must be no more handlers on end of parse") - assert(checkStack.isEmpty, "there must be no residual check remaining on end of parse") assert(states.isEmpty, "there must be no residual states left at end of parse") assert(errs.isEmpty, "there should be no parse errors remaining at end of parse") - assert(hintStack.isEmpty, "there should be no hints remaining at end of parse") Success(stack.peek[A]) } else { assert(!errs.isEmpty && errs.tail.isEmpty, "there should be exactly 1 parse error remaining at end of parse") assert(handlers.isEmpty, "there must be no more handlers on end of parse") - assert(checkStack.isEmpty, "there must be no residual check remaining on end of parse") assert(states.isEmpty, "there must be no residual states left at end of parse") - assert(hintStack.isEmpty, "there should be no hints remaining at end of parse") Failure(errs.error.asParseError.format(sourceFile)) } } @@ -180,14 +163,16 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] calls = calls.tail } - private [machine] def catchNoConsumed(handler: =>Unit): Unit = { + private [machine] def catchNoConsumed(check: Int)(handler: =>Unit): Unit = { assert(!good, "catching can only be performed in a handler") - if (offset != checkStack.offset) fail() + if (offset != check) { + handlers = handlers.tail + fail() + } else { good = true handler } - checkStack = checkStack.tail } private [machine] def pushError(err: DefuncError): Unit = this.errs = new ErrorStack(this.useHints(err), this.errs) @@ -220,7 +205,6 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] if (handlers.isEmpty) running = false else { val handler = handlers - handlers = handlers.tail instrs = handler.instrs calls = handler.calls pc = handler.pc @@ -267,8 +251,7 @@ private [parsley] final class Context(private [machine] var instrs: Array[Instr] offset += n col += n } - private [machine] def pushHandler(label: Int): Unit = handlers = new HandlerStack(calls, instrs, label, stack.usize, handlers) - private [machine] def pushCheck(): Unit = checkStack = new CheckStack(offset, checkStack) + private [machine] def pushHandler(label: Int): Unit = handlers = new HandlerStack(calls, instrs, label, stack.usize, offset, hints, hintsValidOffset, handlers) private [machine] def saveState(): Unit = states = new StateStack(offset, line, col, states) private [machine] def restoreState(): Unit = { val state = states diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/CoreInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/CoreInstrs.scala index da176aaf2..c95f1feaa 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/CoreInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/CoreInstrs.scala @@ -5,9 +5,11 @@ */ package parsley.internal.machine.instructions +import parsley.XAssert._ + import parsley.internal.machine.Context import parsley.internal.machine.XAssert._ -import parsley.internal.machine.errors.EmptyError +import parsley.internal.machine.errors.{EmptyError, EmptyHints} // Stack Manipulators private [internal] final class Push[A](x: A) extends Instr { @@ -155,54 +157,52 @@ private [internal] object PopHandler extends Instr { // $COVERAGE-ON$ } -private [internal] final class PushHandlerAndState(var label: Int, saveHints: Boolean, hideHints: Boolean) extends InstrWithLabel { +private [internal] final class PushHandlerAndClearHints(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) ctx.pushHandler(label) - ctx.saveState() - // FIXME: shadow = !hide so why is it like this? - if (saveHints) ctx.saveHints(shadow = hideHints) + ctx.hints = EmptyHints ctx.inc() } // $COVERAGE-OFF$ - override def toString: String = s"PushHandlerAndState($label)" + override def toString: String = s"PushHandlerAndClearHints($label)" // $COVERAGE-ON$ } -private [internal] object PopHandlerAndState extends Instr { +private [internal] final class PushHandlerAndStateAndClearHints(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) - ctx.states = ctx.states.tail - ctx.handlers = ctx.handlers.tail + ctx.pushHandler(label) + ctx.saveState() + ctx.hints = EmptyHints ctx.inc() } // $COVERAGE-OFF$ - override def toString: String = "PopHandlerAndState" + override def toString: String = s"PushHandlerAndStateAmdClearHints($label)" // $COVERAGE-ON$ } -private [internal] final class PushHandlerAndCheck(var label: Int, saveHints: Boolean) extends InstrWithLabel { +private [internal] final class PushHandlerAndState(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) - ctx.pushCheck() ctx.pushHandler(label) - if (saveHints) ctx.saveHints(false) + ctx.saveState() ctx.inc() } // $COVERAGE-OFF$ - override def toString: String = s"PushHandlerAndCheck($label)" + override def toString: String = s"PushHandlerAndState($label)" // $COVERAGE-ON$ } -private [internal] object PopHandlerAndCheck extends Instr { +private [internal] object PopHandlerAndState extends Instr { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) - ctx.checkStack = ctx.checkStack.tail + ctx.states = ctx.states.tail ctx.handlers = ctx.handlers.tail ctx.inc() } // $COVERAGE-OFF$ - override def toString: String = "PopHandlerAndCheck" + override def toString: String = "PopHandlerAndState" // $COVERAGE-ON$ } @@ -219,9 +219,8 @@ private [internal] final class Jump(var label: Int) extends InstrWithLabel { private [internal] final class JumpAndPopCheck(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) + // TODO: should this be mergeHints? ctx.handlers = ctx.handlers.tail - ctx.checkStack = ctx.checkStack.tail - ctx.commitHints() // TODO: should this be mergeHints? ctx.pc = label } // $COVERAGE-OFF$ @@ -234,7 +233,6 @@ private [internal] final class JumpAndPopState(var label: Int) extends InstrWith ensureRegularInstruction(ctx) ctx.handlers = ctx.handlers.tail ctx.states = ctx.states.tail - ctx.commitHints() ctx.pc = label } // $COVERAGE-OFF$ @@ -246,8 +244,12 @@ private [internal] final class Catch(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) ctx.restoreHints() - ctx.catchNoConsumed { - ctx.pushHandler(label) + val handler = ctx.handlers + ctx.catchNoConsumed(handler.check) { + assume(handler.stacksz == ctx.stack.usize && handler.check == ctx.offset + && handler.hints == ctx.hints && handler.hintOffset == ctx.currentHintsValidOffset, + "the handler can be re-used") + handler.pc = label ctx.inc() } } @@ -262,10 +264,26 @@ private [internal] final class RestoreAndPushHandler(var label: Int) extends Ins ctx.restoreState() ctx.restoreHints() ctx.good = true - ctx.pushHandler(label) + val handler = ctx.handlers + assume(handler.stacksz == ctx.stack.usize && handler.check == ctx.offset + && handler.hints == ctx.hints && handler.hintOffset == ctx.currentHintsValidOffset, + "the handler can be re-used") + handler.pc = label ctx.inc() } // $COVERAGE-OFF$ override def toString: String = s"RestoreAndPushHandler($label)" // $COVERAGE-ON$ } + +private [internal] object Refail extends Instr { + override def apply(ctx: Context): Unit = { + ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail + ctx.fail() + } + + // $COVERAGE-OFF$ + override def toString: String = "Refail" + // $COVERAGE-ON$ +} diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/DebugInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/DebugInstrs.scala index ffb92b2de..a9aa44ce1 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/DebugInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/DebugInstrs.scala @@ -111,9 +111,9 @@ private [internal] final class LogEnd(val name: String, override val ascii: Bool override def apply(ctx: Context): Unit = { assert(ctx.running, "cannot wrap a Halt with a debug") ctx.debuglvl -= 1 + ctx.handlers = ctx.handlers.tail val end = " " + { if (ctx.good) { - ctx.handlers = ctx.handlers.tail ctx.inc() green("Good") } @@ -173,6 +173,7 @@ private [internal] final class LogErrEnd(override val name: String, override val override def apply(ctx: Context): Unit = { assert(ctx.running, "cannot wrap a Halt with a debug") ctx.debuglvl -= 1 + ctx.handlers = ctx.handlers.tail @unused val currentHintsValidOffset = ctx.currentHintsValidOffset if (ctx.good) { // In this case, the currently in-flight hints should be reported @@ -180,7 +181,6 @@ private [internal] final class LogErrEnd(override val name: String, override val val inFlightHints = ctx.inFlightHints.toSet val formattedInFlight = inFlightHints.map(_.formatExpect) val msgInit = s": ${green("Good")}, current hints are $formattedInFlight with" - ctx.handlers = ctx.handlers.tail if (!oldData.stillValid(ctx.currentHintsValidOffset)) { println(preludeString(Exit, ctx, s"$msgInit old hints discarded (valid at offset ${ctx.currentHintsValidOffset})")) } diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/ErrorInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/ErrorInstrs.scala index bb8de2d84..2b5cfae82 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/ErrorInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/ErrorInstrs.scala @@ -22,12 +22,11 @@ private [internal] final class RelabelHints(labels: Iterable[String]) extends In if (isHide) ctx.popHints() // EOK // replace the head of the hints with the singleton for our label - else if (ctx.offset == ctx.checkStack.offset) ctx.replaceHint(labels) + else if (ctx.offset == ctx.handlers.check) ctx.replaceHint(labels) // COK // do nothing ctx.mergeHints() ctx.handlers = ctx.handlers.tail - ctx.checkStack = ctx.checkStack.tail ctx.inc() } // $COVERAGE-OFF$ @@ -42,9 +41,9 @@ private [internal] final class RelabelErrorAndFail(labels: Iterable[String]) ext ctx.errs.error = ctx.useHints { // only use the label if the error message is generated at the same offset // as the check stack saved for the start of the `label` combinator. - ctx.errs.error.label(labels, ctx.checkStack.offset) + ctx.errs.error.label(labels, ctx.handlers.check) } - ctx.checkStack = ctx.checkStack.tail + ctx.handlers = ctx.handlers.tail ctx.fail() } // $COVERAGE-OFF$ @@ -58,7 +57,6 @@ private [internal] object HideHints extends Instr { ctx.popHints() ctx.mergeHints() ctx.handlers = ctx.handlers.tail - ctx.checkStack = ctx.checkStack.tail ctx.inc() } // $COVERAGE-OFF$ @@ -71,7 +69,7 @@ private [internal] object HideErrorAndFail extends Instr { ensureHandlerInstruction(ctx) ctx.restoreHints() ctx.errs.error = new EmptyError(ctx.offset, ctx.line, ctx.col, unexpectedWidth = 0) - ctx.checkStack = ctx.checkStack.tail + ctx.handlers = ctx.handlers.tail ctx.fail() } // $COVERAGE-OFF$ @@ -95,6 +93,7 @@ private [internal] object ErrorToHints extends Instr { private [internal] object MergeErrorsAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail val err2 = ctx.errs.error ctx.errs = ctx.errs.tail ctx.errs.error = ctx.errs.error.merge(err2) @@ -109,8 +108,8 @@ private [internal] object MergeErrorsAndFail extends Instr { private [internal] class ApplyReasonAndFail(reason: String) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) - ctx.errs.error = ctx.errs.error.withReason(reason, ctx.checkStack.offset) - ctx.checkStack = ctx.checkStack.tail + ctx.errs.error = ctx.errs.error.withReason(reason, ctx.handlers.check) + ctx.handlers = ctx.handlers.tail ctx.fail() } @@ -122,6 +121,7 @@ private [internal] class ApplyReasonAndFail(reason: String) extends Instr { private [internal] class AmendAndFail private (partial: Boolean) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail ctx.errs.error = ctx.errs.error.amend(partial, ctx.states.offset, ctx.states.line, ctx.states.col) ctx.states = ctx.states.tail ctx.fail() @@ -140,6 +140,7 @@ private [internal] object AmendAndFail { private [internal] object EntrenchAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail ctx.errs.error = ctx.errs.error.entrench ctx.fail() } @@ -152,6 +153,7 @@ private [internal] object EntrenchAndFail extends Instr { private [internal] class DislodgeAndFail(n: Int) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail ctx.errs.error = ctx.errs.error.dislodge(n) ctx.fail() } @@ -164,8 +166,8 @@ private [internal] class DislodgeAndFail(n: Int) extends Instr { private [internal] object SetLexicalAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) - ctx.errs.error = ctx.errs.error.markAsLexical(ctx.checkStack.offset) - ctx.checkStack = ctx.checkStack.tail + ctx.errs.error = ctx.errs.error.markAsLexical(ctx.handlers.check) + ctx.handlers = ctx.handlers.tail ctx.fail() } diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IntrinsicInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IntrinsicInstrs.scala index 5c9a07542..f4ad5c844 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IntrinsicInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IntrinsicInstrs.scala @@ -210,6 +210,7 @@ private [internal] object NegLookGood extends Instr { // Recover the previous state; notFollowedBy NEVER consumes input ctx.restoreState() ctx.restoreHints() + ctx.handlers = ctx.handlers.tail // A failure is what we wanted ctx.good = true ctx.errs = ctx.errs.tail diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala index 59c2ed820..53134691d 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/IterativeInstrs.scala @@ -12,21 +12,6 @@ import parsley.XAssert._ import parsley.internal.machine.Context import parsley.internal.machine.XAssert._ -// TODO: Now PushHandlerAndCheck(label, false), so could be removed again! -private [internal] final class PushHandlerIterative(var label: Int) extends InstrWithLabel { - override def apply(ctx: Context): Unit = { - ensureRegularInstruction(ctx) - // This is used for iterative parsers, which must ensure that invalidated hints are invalided _now_ - //ctx.invalidateHints() // FIXME: This has been removed because hint setting in updateCheckOffsetAndHints has been disabled, pending deep thought - ctx.pushCheck() - ctx.pushHandler(label) - ctx.inc() - } - // $COVERAGE-OFF$ - override def toString: String = s"PushHandlerIterative($label)" - // $COVERAGE-ON$ -} - private [internal] final class Many(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { if (ctx.good) { @@ -36,7 +21,8 @@ private [internal] final class Many(var label: Int) extends InstrWithLabel { ctx.pc = label } // If the head of input stack is not the same size as the head of check stack, we fail to next handler - else ctx.catchNoConsumed { + else ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.exchangeAndContinue(ctx.stack.peek[mutable.ListBuffer[Any]].toList) } @@ -54,7 +40,8 @@ private [internal] final class SkipMany(var label: Int) extends InstrWithLabel { ctx.pc = label } // If the head of input stack is not the same size as the head of check stack, we fail to next handler - else ctx.catchNoConsumed { + else ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.pushAndContinue(()) } @@ -73,7 +60,8 @@ private [internal] final class ChainPost(var label: Int) extends InstrWithLabel ctx.pc = label } // If the head of input stack is not the same size as the head of check stack, we fail to next handler - else ctx.catchNoConsumed { + else ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.inc() } @@ -92,7 +80,8 @@ private [internal] final class ChainPre(var label: Int) extends InstrWithLabel { ctx.pc = label } // If the head of input stack is not the same size as the head of check stack, we fail to next handler - else ctx.catchNoConsumed { + else ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.inc() } @@ -111,7 +100,8 @@ private [internal] final class Chainl(var label: Int) extends InstrWithLabel { ctx.pc = label } // If the head of input stack is not the same size as the head of check stack, we fail to next handler - else ctx.catchNoConsumed { + else ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.inc() } @@ -124,7 +114,6 @@ private [internal] final class Chainl(var label: Int) extends InstrWithLabel { private [instructions] object DualHandler { def popSecondHandlerAndJump(ctx: Context, label: Int): Unit = { ctx.handlers = ctx.handlers.tail - ctx.checkStack = ctx.checkStack.tail ctx.updateCheckOffset() ctx.pc = label } @@ -149,13 +138,14 @@ private [internal] final class ChainrJump(var label: Int) extends InstrWithLabel private [internal] final class ChainrOpHandler(wrap: Any => Any) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + val check = ctx.handlers.check ctx.handlers = ctx.handlers.tail - ctx.catchNoConsumed { + ctx.catchNoConsumed(check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() val y = ctx.stack.upop() ctx.exchangeAndContinue(ctx.stack.peek[Any => Any](wrap(y))) } - ctx.checkStack = ctx.checkStack.tail } // $COVERAGE-OFF$ @@ -166,18 +156,6 @@ private [internal] object ChainrOpHandler { def apply[A, B](wrap: A => B): ChainrOpHandler = new ChainrOpHandler(wrap.asInstanceOf[Any => Any]) } -private [internal] object ChainrWholeHandler extends Instr { - override def apply(ctx: Context): Unit = { - ensureHandlerInstruction(ctx) - ctx.checkStack = ctx.checkStack.tail - ctx.fail() - } - - // $COVERAGE-OFF$ - override def toString: String = "ChainrWholeHandler" - // $COVERAGE-ON$ -} - private [internal] final class SepEndBy1Jump(var label: Int) extends InstrWithLabel { override def apply(ctx: Context): Unit = { ensureRegularInstruction(ctx) @@ -193,8 +171,8 @@ private [internal] final class SepEndBy1Jump(var label: Int) extends InstrWithLa } private [instructions] object SepEndBy1Handlers { - def pushAccWhenCheckValidAndContinue(ctx: Context, acc: mutable.ListBuffer[Any]): Unit = { - if (ctx.offset != ctx.checkStack.offset || acc.isEmpty) ctx.fail() + def pushAccWhenCheckValidAndContinue(ctx: Context, check: Int, acc: mutable.ListBuffer[Any]): Unit = { + if (ctx.offset != check || acc.isEmpty) ctx.fail() else { ctx.addErrorToHintsAndPop() ctx.good = true @@ -206,6 +184,8 @@ private [instructions] object SepEndBy1Handlers { private [internal] object SepEndBy1SepHandler extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + val check = ctx.handlers.check + ctx.handlers = ctx.handlers.tail // p succeeded and sep didn't, so push p and fall-through to the whole handler val x = ctx.stack.upop() val acc = ctx.stack.peek[mutable.ListBuffer[Any]] @@ -215,8 +195,7 @@ private [internal] object SepEndBy1SepHandler extends Instr { assert(ctx.handlers.pc == ctx.pc + 1, "the top-most handler must be the whole handler in the sep handler") ctx.handlers = ctx.handlers.tail ctx.inc() - SepEndBy1Handlers.pushAccWhenCheckValidAndContinue(ctx, acc) - ctx.checkStack = ctx.checkStack.tail.tail + SepEndBy1Handlers.pushAccWhenCheckValidAndContinue(ctx, check, acc) } // $COVERAGE-OFF$ @@ -227,8 +206,9 @@ private [internal] object SepEndBy1SepHandler extends Instr { private [internal] object SepEndBy1WholeHandler extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) - SepEndBy1Handlers.pushAccWhenCheckValidAndContinue(ctx, ctx.stack.peek[mutable.ListBuffer[Any]]) - ctx.checkStack = ctx.checkStack.tail + val check = ctx.handlers.check + ctx.handlers = ctx.handlers.tail + SepEndBy1Handlers.pushAccWhenCheckValidAndContinue(ctx, check, ctx.stack.peek[mutable.ListBuffer[Any]]) } // $COVERAGE-OFF$ @@ -249,7 +229,10 @@ private [internal] final class ManyUntil(var label: Int) extends InstrWithLabel } } // ManyUntil is a fallthrough handler, it must be visited during failure, but does nothing to the external state - else ctx.fail() + else { + ctx.handlers = ctx.handlers.tail + ctx.fail() + } } // $COVERAGE-OFF$ override def toString: String = s"ManyUntil($label)" @@ -269,7 +252,10 @@ private [internal] final class SkipManyUntil(var label: Int) extends InstrWithLa } } // ManyUntil is a fallthrough handler, it must be visited during failure, but does nothing to the external state - else ctx.fail() + else { + ctx.handlers = ctx.handlers.tail + ctx.fail() + } } // $COVERAGE-OFF$ override def toString: String = s"ManyUntil($label)" diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/OptInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/OptInstrs.scala index 79c29ae6e..c2774ef64 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/OptInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/OptInstrs.scala @@ -13,7 +13,7 @@ import parsley.token.errors.LabelConfig import parsley.internal.errors.ExpectItem import parsley.internal.machine.Context import parsley.internal.machine.XAssert._ -import parsley.internal.machine.errors.ExpectedError +import parsley.internal.machine.errors.{EmptyHints, ExpectedError} import parsley.internal.machine.stacks.ErrorStack private [internal] final class Lift1(f: Any => Any) extends Instr { @@ -58,7 +58,8 @@ private [internal] final class RecoverWith[A](x: A) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) ctx.restoreHints() // This must be before adding the error to hints - ctx.catchNoConsumed { + ctx.catchNoConsumed(ctx.handlers.check) { + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.pushAndContinue(x) } @@ -73,6 +74,7 @@ private [internal] final class AlwaysRecoverWith[A](x: A) extends Instr { ensureHandlerInstruction(ctx) ctx.restoreState() ctx.restoreHints() // This must be before adding the error to hints + ctx.handlers = ctx.handlers.tail ctx.addErrorToHintsAndPop() ctx.good = true ctx.pushAndContinue(x) @@ -99,9 +101,8 @@ private [internal] final class JumpTable(jumpTable: mutable.LongMap[(Int, Iterab val (dest, errorItems) = jumpTable.getOrElse(ctx.peekChar.toLong, (default, allErrorItems)) ctx.pc = dest if (dest != default) { - ctx.pushCheck() ctx.pushHandler(defaultPreamble) - ctx.saveHints(shadow = false) + ctx.hints = EmptyHints } addErrors(ctx, errorItems) // adds a handler } diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/PrimitiveInstrs.scala b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/PrimitiveInstrs.scala index 4028d7a38..1b6daf0ff 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/instructions/PrimitiveInstrs.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/instructions/PrimitiveInstrs.scala @@ -27,6 +27,7 @@ private [internal] final class Satisfies(f: Char => Boolean, expected: Iterable[ private [internal] object RestoreAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail // Pop input off head then fail to next handler ctx.restoreState() ctx.fail() @@ -52,6 +53,7 @@ private [internal] object RestoreHintsAndState extends Instr { private [internal] object PopStateAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail ctx.states = ctx.states.tail ctx.fail() } @@ -64,6 +66,7 @@ private [internal] object PopStateRestoreHintsAndFail extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) ctx.restoreHints() + ctx.handlers = ctx.handlers.tail ctx.states = ctx.states.tail ctx.fail() } @@ -128,6 +131,7 @@ private [internal] final class Put(reg: Int) extends Instr { private [internal] final class PutAndFail(reg: Int) extends Instr { override def apply(ctx: Context): Unit = { ensureHandlerInstruction(ctx) + ctx.handlers = ctx.handlers.tail ctx.writeReg(reg, ctx.stack.upeek) ctx.fail() } @@ -174,10 +178,8 @@ private [parsley] final class CalleeSave(var label: Int, localRegs: Set[Reg[_]], } private def continue(ctx: Context): Unit = { - if (ctx.good) { - ctx.handlers = ctx.handlers.tail - ctx.pc = label - } + ctx.handlers = ctx.handlers.tail + if (ctx.good) ctx.pc = label else ctx.fail() } diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/CheckStack.scala b/parsley/shared/src/main/scala/parsley/internal/machine/stacks/CheckStack.scala deleted file mode 100644 index 80de35d83..000000000 --- a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/CheckStack.scala +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 Parsley Contributors - * - * SPDX-License-Identifier: BSD-3-Clause - */ -package parsley.internal.machine.stacks - -private [machine] final class CheckStack(var offset: Int, val tail: CheckStack) -private [machine] object CheckStack extends Stack[CheckStack] { - implicit val inst: Stack[CheckStack] = this - type ElemTy = Int - // $COVERAGE-OFF$ - override protected def show(x: ElemTy): String = x.toString - override protected def head(xs: CheckStack): ElemTy = xs.offset - override protected def tail(xs: CheckStack): CheckStack = xs.tail - // $COVERAGE-ON$ -} diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HandlerStack.scala b/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HandlerStack.scala index ffb7a099f..8165a053b 100644 --- a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HandlerStack.scala +++ b/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HandlerStack.scala @@ -6,17 +6,22 @@ package parsley.internal.machine.stacks import parsley.internal.machine.instructions.Instr +import parsley.internal.machine.errors.DefuncHints private [machine] final class HandlerStack( val calls: CallStack, val instrs: Array[Instr], var pc: Int, val stacksz: Int, + var check: Int, + val hints: DefuncHints, + val hintOffset: Int, val tail: HandlerStack) private [machine] object HandlerStack extends Stack[HandlerStack] { implicit val inst: Stack[HandlerStack] = this type ElemTy = (Int, Int) // $COVERAGE-OFF$ + // TODO: needs to change override protected def show(x: ElemTy): String = { val (pc, stacksz) = x s"Handler:$pc(-${stacksz + 1})" diff --git a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HintStack.scala b/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HintStack.scala deleted file mode 100644 index e6e012e8c..000000000 --- a/parsley/shared/src/main/scala/parsley/internal/machine/stacks/HintStack.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020 Parsley Contributors - * - * SPDX-License-Identifier: BSD-3-Clause - */ -package parsley.internal.machine.stacks - -import parsley.internal.machine.errors.DefuncHints - -private [machine] final class HintStack(val hints: DefuncHints, val validOffset: Int, val tail: HintStack) -private [machine] object HintStack extends Stack[HintStack] { - implicit val inst: Stack[HintStack] = this - type ElemTy = (DefuncHints, Int) - // $COVERAGE-OFF$ - override protected def show(x: ElemTy): String = { - val (hints, validOffset) = x - s"($validOffset, $hints)" - } - override protected def head(xs: HintStack): ElemTy = (xs.hints, xs.validOffset) - override protected def tail(xs: HintStack): HintStack = xs.tail - // $COVERAGE-ON$ -}