Skip to content

Commit

Permalink
chore: put parsley-debug on 3.5
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mie6 committed Jan 12, 2025
1 parent cca7b43 commit 8f51551
Show file tree
Hide file tree
Showing 10 changed files with 32 additions and 30 deletions.
4 changes: 3 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ val projectName = "parsley"
val Scala213 = "2.13.14"
val Scala212 = "2.12.18"
val Scala3 = "3.3.3"
val Scala35 = "3.5.2"
val Java11 = JavaSpec.temurin("11")
val Java17 = JavaSpec.temurin("17")
val Java21 = JavaSpec.temurin("21")
Expand Down Expand Up @@ -84,11 +85,12 @@ lazy val parsleyDebug = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.dependsOn(parsley % "compile->compile;test->test") // Forwards the test classes to this project. Needed for ParsleyTest.
.settings(
name := "parsley-debug",
crossScalaVersions := Seq(Scala213, Scala212, Scala35),
commonSettings,
scalacOptions ++= {
scalaVersion.value match {
case Scala213 => Seq("-Ymacro-annotations")
case Scala3 => Seq.empty
case Scala35 => Seq.empty
case Scala212 => Seq.empty
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import scala.quoted.*
* @since 5.0.0
*/
@experimental class debuggable extends MacroAnnotation {
def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = {
override def transform(using Quotes)(tree: quotes.reflect.Definition, companion: Option[quotes.reflect.Definition]): List[quotes.reflect.Definition] = {
import quotes.reflect.*
tree match {
case cls@ClassDef(clsName, constr, parents, selfOpt, body) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private [parsley] class DebugContext(private val toStringRules: PartialFunction[
}*/

// Push a new parser onto the parser callstack.
def push(fullInput: String, parser: LazyParsley[_], userAssignedName: Option[String]): Unit = {
def push(fullInput: String, parser: LazyParsley[?], userAssignedName: Option[String]): Unit = {
val newTree = new TransientDebugTree(fullInput = fullInput)
newTree.name = Renamer.nameOf(userAssignedName, parser)
newTree.internal = Renamer.internalName(parser)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import parsley.internal.deepembedding.frontend.LazyParsley
// FIXME: in future, this should use better tuned exception names

private [parsley] final class DivergenceContext {
case class CtxSnap(pc: Int, instrs: Array[_], off: Int, regs: List[AnyRef])
case class HandlerSnap(pc: Int, instrs: Array[_])
case class CtxSnap(pc: Int, instrs: Array[?], off: Int, regs: List[AnyRef])
case class HandlerSnap(pc: Int, instrs: Array[?])
private case class Snapshot(name: String, internalName: String, ctxSnap: CtxSnap, handlerSnap: Option[HandlerSnap], children: mutable.ListBuffer[Snapshot]) {
// this is true when the ctxSnaps match
def matchesParent(that: Snapshot): Boolean = this.ctxSnap == that.ctxSnap
Expand All @@ -32,7 +32,7 @@ private [parsley] final class DivergenceContext {
// For a recursive structure, I think the pruning actually would work, and can be done
private val snaps = mutable.Stack.empty[Snapshot]

def takeSnapshot(parser: LazyParsley[_], userAssignedName: Option[String], ctxSnap: CtxSnap, handlerSnap: Option[HandlerSnap]): Unit = {
def takeSnapshot(parser: LazyParsley[?], userAssignedName: Option[String], ctxSnap: CtxSnap, handlerSnap: Option[HandlerSnap]): Unit = {
val name = Renamer.nameOf(userAssignedName, parser)
val internalName = Renamer.internalName(parser)
// at this point we may have some old snapshots on the stack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ private [parsley] object Renamer {
// to their parsers, or directly invoke Collector.assignName to strongly assign names to parsers.
// Just like parser reference collection for the debugger, we need a weak map so ephemeral renamed
// parsers don't leak memory.
lazy private val collected = new XWeakMap[LazyParsley[_], String]
lazy private val collected = new XWeakMap[LazyParsley[?], String]

private def underlying(p: LazyParsley[_]): LazyParsley[_] = p match {
case dbg: TaggedWith[_] => dbg.origin // this should never be the case?
private def underlying(p: LazyParsley[?]): LazyParsley[?] = p match {
case dbg: TaggedWith[?] => dbg.origin // this should never be the case?
case _ => p
}

// This method attempts the renaming of a parser, even if at least partially.
// This renames the parser if it is present, otherwise gives the default name found earlier.
def nameOf(userAssignedName: Option[String], p: LazyParsley[_]): String = userAssignedName.getOrElse {
def nameOf(userAssignedName: Option[String], p: LazyParsley[?]): String = userAssignedName.getOrElse {
val extracted = underlying(p)
collected.getOrElse(extracted, extracted.debugName)
}

// Perform the first step of renaming, a partial rename where only the type name is exposed.
@inline def internalName(p: LazyParsley[_]): String = underlying(p).debugName
@inline def internalName(p: LazyParsley[?]): String = underlying(p).debugName

private [parsley] def addNames(names: Map[LazyParsley[_], String]): Unit = collected ++= names
private [parsley] def addName(par: LazyParsley[_], name: String): Unit = collected.update(par, name)
private [parsley] def addNames(names: Map[LazyParsley[?], String]): Unit = collected ++= names
private [parsley] def addName(par: LazyParsley[?], name: String): Unit = collected.update(par, name)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object Collector {
}*/

/** This is an internal method used by the `parsley.debuggable` annotation */
def registerNames(names: Map[Parsley[_], String]): Unit = {
def registerNames(names: Map[Parsley[?], String]): Unit = {
Renamer.addNames(names.map { case (k, v) => k.internal -> v })
}

Expand Down Expand Up @@ -98,20 +98,20 @@ object Collector {
// $COVERAGE-OFF$
private [parsley] abstract class CollectorImpl {
/** Collect names of parsers from an object. */
def collectNames(obj: Any): Map[LazyParsley[_], String]
def collectNames(obj: Any): Map[LazyParsley[?], String]

/** Collect names of parsers from a [[parsley.token.Lexer]]. */
def collectLexer(lexer: Lexer): Map[LazyParsley[_], String]
def collectLexer(lexer: Lexer): Map[LazyParsley[?], String]

/** Does the current platform's [[CollectorImpl]] actually get parsers from objects? */
val supported: Boolean

// Try grabbing a parser from a LazyParsley or Parsley instance.
// XXX: Doing a direct type test with match will cause Parsley objects to be instantiated.
// XXX: Using a match-case expression without @unchecked causes an error in CI as these matches are not exhaustive.
protected def tryExtract(par: Any): LazyParsley[_] = (par: @unchecked) match {
case l: LazyParsley[_] => l
case p: Parsley[_] => p.internal
protected def tryExtract(par: Any): LazyParsley[?] = (par: @unchecked) match {
case l: LazyParsley[?] => l
case p: Parsley[?] => p.internal
}

// All of these objects inside a lexer are exposed, so are easy to collect parser names from.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import parsley.internal.deepembedding.frontend.LazyParsley
// Empty collector for platforms that don't support reflection.
// $COVERAGE-OFF$
private [util] class XDummyCollector extends CollectorImpl {
override def collectNames(obj: Any): Map[LazyParsley[_], String] = Map.empty
override def collectLexer(lexer: Lexer): Map[LazyParsley[_], String] = Map.empty
override def collectNames(obj: Any): Map[LazyParsley[?], String] = Map.empty
override def collectLexer(lexer: Lexer): Map[LazyParsley[?], String] = Map.empty
override val supported: Boolean = false
}
// $COVERAGE-ON$
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import parsley.internal.deepembedding.frontend.{LazyParsley, LazyParsleyIVisitor
// $COVERAGE-OFF$
// Wrapper parser class indicating explicitly named parsers.
private [parsley] final class Named[A](_p: LazyParsley[A], val name: String) extends Unary[A, A](_p) {
XAssert.assert(!p.isInstanceOf[Named[_]], "Named parsers should not be nested within each other directly.")
XAssert.assert(!p.isInstanceOf[Named[?]], "Named parsers should not be nested within each other directly.")
def make(p: StrictParsley[A]): StrictParsley[A] = p
override def visit[T, U[+_]](visitor: LazyParsleyIVisitor[T, U], context: T): U[A] = visitor.visitUnknown(this, context)
private [parsley] var debugName = name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import parsley.internal.deepembedding.frontend._ // scalastyle:ignore underscore
// FIXME: this clobbers the register allocator, apparently?
private [parsley] final class TaggedWith[A](factory: TagFactory)(val origin: LazyParsley[A], val subParser: LazyParsley[A], userAssignedName: Option[String])
extends LazyParsley[A] {
XAssert.assert(!origin.isInstanceOf[TaggedWith[_]], "Tagged parsers should not be nested within each other directly.")
XAssert.assert(!origin.isInstanceOf[TaggedWith[?]], "Tagged parsers should not be nested within each other directly.")

def make(p: StrictParsley[A]): StrictParsley[A] = factory.create(origin, p, userAssignedName)

override def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[_]])(implicit state: LetFinderState): M[R, Unit] = suspend(subParser.findLets(seen))
override def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[?]])(implicit state: LetFinderState): M[R, Unit] = suspend(subParser.findLets(seen))
override def preprocess[M[_, +_] : ContOps, R, A_ >: A](implicit lets: LetMap): M[R, StrictParsley[A_]] = {
for (p <- suspend[M, R, StrictParsley[A]](subParser.optimised[M, R, A])) yield make(p)
}
Expand Down Expand Up @@ -61,14 +61,14 @@ private [parsley] object TaggedWith {
// This map tracks seen parsers to prevent infinitely recursive parsers from overflowing the stack (and ties
// the knot for these recursive parsers).
// Use maps with weak keys or don't pass this into a >>= parser.
private final class ParserTracker(val map: mutable.Map[LazyParsley[_], ParsleyPromise[_]]) {
private final class ParserTracker(val map: mutable.Map[LazyParsley[?], ParsleyPromise[?]]) {
def put[A](par: LazyParsley[A]): ParsleyPromise[A] = {
val prom = new ParsleyPromise[A]
map(par) = prom
prom
}
def get[A](par: LazyParsley[A]): Deferred[LazyParsley[A]] = map(par).get.asInstanceOf[Deferred[LazyParsley[A]]]
def hasSeen(par: LazyParsley[_]): Boolean = map.contains(par)
def hasSeen(par: LazyParsley[?]): Boolean = map.contains(par)
}

// these two classes are used to allow for parsers to be added into the ParserTracker map without
Expand All @@ -78,7 +78,7 @@ private [parsley] object TaggedWith {
// instead, the lazy box is opened in the by-name parameters of constructed nodes, which ensures
// that the traversal completes before the promise is checked.
private final class ParsleyPromise[A] {
private var value: Deferred[LazyParsley[A]] = _
private var value: Deferred[LazyParsley[A]] = null
def get: Deferred[LazyParsley[A]] = Deferred {
if (value == null) throw new NoSuchElementException("fetched empty promise value")
value.get
Expand All @@ -93,7 +93,7 @@ private [parsley] object TaggedWith {
}

// Keeping this around for easy access to LPM.
@unused private [this] final class ContWrap[M[_, +_], R] {
@unused private final class ContWrap[M[_, +_], R] {
type LPM[+A] = M[R, LazyParsley[A]]
type DLPM[+A] = M[R, Deferred[LazyParsley[A]]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import parsley.internal.machine.XAssert._
import parsley.internal.machine.stacks.Stack.StackExt

// Enter into the scope of a parser in the current context.
private [internal] class EnterParser(var label: Int, origin: LazyParsley[_], userAssignedName: Option[String])(dbgCtx: DebugContext) extends InstrWithLabel {
private [internal] class EnterParser(var label: Int, origin: LazyParsley[?], userAssignedName: Option[String])(dbgCtx: DebugContext) extends InstrWithLabel {
override def apply(ctx: Context): Unit = {
ensureRegularInstruction(ctx)
// Uncomment to debug entries and exits.
Expand Down Expand Up @@ -76,7 +76,7 @@ private [internal] class AddAttemptAndLeave(dbgCtx: DebugContext) extends Instr
// $COVERAGE-ON$
}

private [internal] class TakeSnapshot(var label: Int, origin: LazyParsley[_], userAssignedName: Option[String])(dtx: DivergenceContext) extends InstrWithLabel {
private [internal] class TakeSnapshot(var label: Int, origin: LazyParsley[?], userAssignedName: Option[String])(dtx: DivergenceContext) extends InstrWithLabel {
override def apply(ctx: Context): Unit = {
ensureRegularInstruction(ctx)
val handler = ctx.handlers
Expand Down

0 comments on commit 8f51551

Please sign in to comment.