diff --git a/build.sbt b/build.sbt index c31f0380c..a71ec7792 100644 --- a/build.sbt +++ b/build.sbt @@ -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") @@ -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 } }, diff --git a/parsley-debug/shared/src/main/scala-3/parsley/debuggable.scala b/parsley-debug/shared/src/main/scala-3/parsley/debuggable.scala index 69e863e3c..9c5a1d7c7 100644 --- a/parsley-debug/shared/src/main/scala-3/parsley/debuggable.scala +++ b/parsley-debug/shared/src/main/scala-3/parsley/debuggable.scala @@ -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) => diff --git a/parsley-debug/shared/src/main/scala/parsley/debug/internal/DebugContext.scala b/parsley-debug/shared/src/main/scala/parsley/debug/internal/DebugContext.scala index 163edcf94..be06a2dbb 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debug/internal/DebugContext.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debug/internal/DebugContext.scala @@ -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) diff --git a/parsley-debug/shared/src/main/scala/parsley/debug/internal/DivergenceContext.scala b/parsley-debug/shared/src/main/scala/parsley/debug/internal/DivergenceContext.scala index caf076f8a..4622b4027 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debug/internal/DivergenceContext.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debug/internal/DivergenceContext.scala @@ -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 @@ -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 diff --git a/parsley-debug/shared/src/main/scala/parsley/debug/internal/Renamer.scala b/parsley-debug/shared/src/main/scala/parsley/debug/internal/Renamer.scala index 52ba98b82..5878aafce 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debug/internal/Renamer.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debug/internal/Renamer.scala @@ -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) } diff --git a/parsley-debug/shared/src/main/scala/parsley/debug/util/Collector.scala b/parsley-debug/shared/src/main/scala/parsley/debug/util/Collector.scala index 86b4f0498..8cb62db14 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debug/util/Collector.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debug/util/Collector.scala @@ -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 }) } @@ -98,10 +98,10 @@ 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 @@ -109,9 +109,9 @@ private [parsley] abstract class CollectorImpl { // 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. diff --git a/parsley-debug/shared/src/main/scala/parsley/debug/util/XDummyCollector.scala b/parsley-debug/shared/src/main/scala/parsley/debug/util/XDummyCollector.scala index b044fcc16..a0c293ea9 100644 --- a/parsley-debug/shared/src/main/scala/parsley/debug/util/XDummyCollector.scala +++ b/parsley-debug/shared/src/main/scala/parsley/debug/util/XDummyCollector.scala @@ -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$ diff --git a/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/Named.scala b/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/Named.scala index ded576f2d..60f77684c 100644 --- a/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/Named.scala +++ b/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/Named.scala @@ -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 diff --git a/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/TaggedWith.scala b/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/TaggedWith.scala index 16cdb57ea..e2c6bfa98 100644 --- a/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/TaggedWith.scala +++ b/parsley-debug/shared/src/main/scala/parsley/internal/deepembedding/frontend/debug/TaggedWith.scala @@ -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) } @@ -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 @@ -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 @@ -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]]] } diff --git a/parsley-debug/shared/src/main/scala/parsley/internal/machine/instructions/debug/DebugInstrs.scala b/parsley-debug/shared/src/main/scala/parsley/internal/machine/instructions/debug/DebugInstrs.scala index 7e387babb..6b671c845 100644 --- a/parsley-debug/shared/src/main/scala/parsley/internal/machine/instructions/debug/DebugInstrs.scala +++ b/parsley-debug/shared/src/main/scala/parsley/internal/machine/instructions/debug/DebugInstrs.scala @@ -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. @@ -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