Skip to content

Commit

Permalink
documentation, deprecation, and dumb scala compiler bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mie6 committed Apr 23, 2024
1 parent 8103478 commit 90e250b
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 59 deletions.
32 changes: 16 additions & 16 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,6 @@ lazy val parsley = crossProject(JSPlatform, JVMPlatform, NativePlatform)
Compile / doc / scalacOptions ++= Seq("-doc-root-content", s"${baseDirectory.value.getPath}/rootdoc.md"),
)

lazy val docs = project
.in(file("site"))
.dependsOn(parsley.jvm)
.enablePlugins(ParsleySitePlugin)
.settings(
tlSiteApiModule := Some((parsley.jvm / projectID).value),
libraryDependencySchemes ++= Seq(
// this helps us when parsley-cats is trailing behind us
"com.github.j-mie6" %% "parsley" % VersionScheme.Always,
),
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % "2.10.0",
"com.github.j-mie6" %% "parsley-cats" % "1.3.0"
),
)

lazy val parsleyDebug = crossProject(JSPlatform, JVMPlatform, NativePlatform)
.withoutSuffixFor(JVMPlatform)
.crossType(CrossType.Full)
Expand Down Expand Up @@ -128,6 +112,22 @@ lazy val parsleyDebug = crossProject(JSPlatform, JVMPlatform, NativePlatform)
),
)

lazy val docs = project
.in(file("site"))
.dependsOn(parsley.jvm)
.enablePlugins(ParsleySitePlugin)
.settings(
tlSiteApiModule := Some((parsley.jvm / projectID).value),
libraryDependencySchemes ++= Seq(
// this helps us when parsley-cats is trailing behind us
"com.github.j-mie6" %% "parsley" % VersionScheme.Always,
),
libraryDependencies ++= Seq(
"org.typelevel" %% "cats-core" % "2.10.0",
"com.github.j-mie6" %% "parsley-cats" % "1.3.0"
),
)

def testCoverageJob(cacheSteps: List[WorkflowStep]) = WorkflowJob(
id = "coverage",
name = "Run Test Coverage and Upload",
Expand Down
12 changes: 12 additions & 0 deletions parsley-debug/shared/src/main/scala-2/parsley/debuggable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ package parsley
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.reflect.macros.blackbox

/** This annotation can be applied to an object or class to record their
* names for the debugging/diagnostic combinators.
*
* @note BE WARNED: this annotation crashes the compiler for objects/classes nested within another type -- this is ok for Scala 3
* @note It requires that the
* object/class is type-checkable, which due to Scala 2 macro limitations
* involes stripping away the enclosing type itself. This might lead to
* weird edge-cases: if parsley reports that type-checking failed, you
* should report this to the maintainers.
*
* @since 5.0.0
*/
@compileTimeOnly("macros need to be enabled to use this functionality: -Ymacro-annotations in 2.13, or use \"Macro Paradise\" for 2.12")
class debuggable extends StaticAnnotation {
def macroTransform(annottees: Any*): Any = macro debuggable.impl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ package parsley
import scala.annotation.{experimental, MacroAnnotation}
import scala.quoted.*

/** This annotation can be applied to an object or class to record their
* names for the debugging/diagnostic combinators.
*
* @note Currently, macro-annotations in Scala 3 are experimental, which
* means the @experimental annotation will need to be used (or the global
* -experimental flag on 3.4+) to use this functionality.
*
* @since 5.0.0
*/
@experimental class debuggable extends MacroAnnotation {
def transform(using Quotes)(tree: quotes.reflect.Definition): List[quotes.reflect.Definition] = {
import quotes.reflect.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*/
package parsley.debugger.util

import scala.annotation.nowarn

import parsley.Parsley
import parsley.debugger.internal.Renamer
import parsley.token.Lexer
Expand All @@ -30,6 +32,7 @@ object Collector {
* be advised to manually name one's parsers (to be debugged) using [[assignName]] or
* [[parsley.debugger.combinator.named]] if that warning is not desirable.
*/
@deprecated("The functionality of this class has been subsumed by the `parsley.debuggable` annotation", "5.0.0-M7")
def names(obj: Any): Unit = {
collectDefault() // Runs only once, ever, for a program execution.
Renamer.addNames(XCollector.collectNames(obj))
Expand All @@ -47,6 +50,7 @@ object Collector {
* being deprecated.
* @see [[names]] for more information regarding the warning.
*/
//@deprecated("This functionality has been absorbed into parsley itself", "5.0.0-M7")
def lexer(lexer: Lexer): Unit = {
collectDefault()
Renamer.addNames(XCollector.collectLexer(lexer))
Expand Down Expand Up @@ -79,10 +83,10 @@ object Collector {
if (!defaultCollected) {
defaultCollected = true

names(parsley.character)
names(parsley.combinator)
names(parsley.Parsley)
names(parsley.position)
names(parsley.character): @nowarn
names(parsley.combinator): @nowarn
names(parsley.Parsley): @nowarn
names(parsley.position): @nowarn
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object otherParsers {

@experimental @parsley.debuggable
class parsers(val x: Int) {
val p = char('a')
val p = satisfy(_.isDigit)
val q = p ~> p
lazy val r: Parsley[Char] = ~r ~> q
def s = otherParsers.a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
*/
package parsley.debugger

import scala.annotation.experimental

// scalastyle:off underscore.import
import DebuggerUsageSpec.Arithmetic
//import DebuggerUsageSpec.Arithmetic
import org.typelevel.scalaccompat.annotation.unused
import parsley.Parsley, Parsley._
import parsley.ParsleyTest
Expand All @@ -18,6 +20,7 @@ import parsley.internal.deepembedding.frontend.debugger.TaggedWith
import parsley.internal.deepembedding.backend.debugger.Debugging
// scalastyle:on underscore.import

@experimental
class DebuggerUsageSpec extends ParsleyTest {
"the Debugged internal frontend class" should "not allow nesting of Debugged nodes" in {
val factory = new Debugging(new DebugContext())
Expand All @@ -37,14 +40,14 @@ class DebuggerUsageSpec extends ParsleyTest {
}

"the debugger runtime" should "preserve the result of parsers" in {
val debugMath = attachDebugger(Arithmetic.prog)
val (_, debugMath) = attachDebugger(Arithmetic.prog)

debugMath._2.parse("1+1").get.head shouldBe 2
debugMath._2.parse("2*3").get.head shouldBe 6
debugMath._2.parse("9-4").get.head shouldBe 5
debugMath._2.parse("6/2").get.head shouldBe 3
debugMath.parse("1+1").get.head shouldBe 2
debugMath.parse("2*3").get.head shouldBe 6
debugMath.parse("9-4").get.head shouldBe 5
debugMath.parse("6/2").get.head shouldBe 3

debugMath._2.parse("1+2+3+4+5\n2*3*4").get shouldBe List(15, 24) // scalastyle:ignore magic.number
debugMath.parse("1+2+3+4+5\n2*3*4").get shouldBe List(15, 24) // scalastyle:ignore magic.number
}

it should "not cause references to be unallocated" in {
Expand Down Expand Up @@ -87,28 +90,16 @@ class DebuggerUsageSpec extends ParsleyTest {
}
}

object DebuggerUsageSpec {
// Look, for some reason the annotation dies if it's nested, I don't know why, it's impossible to diagnose
//object DebuggerUsageSpec {
@experimental @parsley.debuggable
private [parsley] object Arithmetic {
val int: Parsley[BigInt] =
satisfy(_.isDigit)
.foldLeft1(BigInt(0))((acc, c) => acc * 10 + c.asDigit)

val int: Parsley[BigInt] = satisfy(_.isDigit).foldLeft1(BigInt(0))((acc, c) => acc * 10 + c.asDigit)
lazy val expr: Parsley[BigInt] =
precedence[BigInt](
int,
char('(') ~> expr <~ char(')')
)(
Ops(InfixL)(
char('*') #> (_ * _),
char('/') #> (_ / _)
),
Ops(InfixL)(
char('+') #> (_ + _),
char('-') #> (_ - _)
)
precedence[BigInt](int, char('(') ~> expr <~ char(')'))(
Ops(InfixL)(char('*') #> (_ * _), char('/') #> (_ / _)),
Ops(InfixL)(char('+') #> (_ + _), char('-') #> (_ - _))
)

lazy val prog: Parsley[List[BigInt]] =
many(many(satisfy("\r\n".contains(_))) ~> expr)
lazy val prog: Parsley[List[BigInt]] = many(many(satisfy("\r\n".contains(_))) ~> expr)
}
}
//}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*/
package parsley.internal.deepembedding

import scala.annotation.experimental

import org.scalatest.Assertions.fail
import parsley.ParsleyTest
import parsley.debugger.DebuggerUsageSpec
import parsley.debugger.Arithmetic
import parsley.debugger.internal.{DebugContext, Renamer}
import parsley.debugger.util.Collector
import parsley.internal.deepembedding.backend.StrictParsley
Expand All @@ -17,6 +19,7 @@ import parsley.token.Lexer
import parsley.token.descriptions.LexicalDesc
import parsley.internal.deepembedding.backend.debugger.Debugging

@experimental
class RenameSpec extends ParsleyTest {
"the Renamer object" should "not rename a parser it does not know of" in {
val exampleParser = new DummyParser
Expand Down Expand Up @@ -51,12 +54,12 @@ class RenameSpec extends ParsleyTest {

"the Collector implementations" should "collect names of parsers from objects (on supported platforms)" in {
if (Collector.isSupported) {
Collector.names(DebuggerUsageSpec.Arithmetic)
Renamer.nameOf(None, DebuggerUsageSpec.Arithmetic.prog.internal) shouldBe "prog"
//Collector.names(Arithmetic)
Renamer.nameOf(None, Arithmetic.prog.internal) shouldBe "prog"

info("it should also allow overriding the name")
Collector.assignName(DebuggerUsageSpec.Arithmetic.prog, "foo")
Renamer.nameOf(None, DebuggerUsageSpec.Arithmetic.prog.internal) shouldBe "foo"
Collector.assignName(Arithmetic.prog, "foo")
Renamer.nameOf(None, Arithmetic.prog.internal) shouldBe "foo"
} else alert("the current platform does not support Collector")
}

Expand All @@ -70,22 +73,22 @@ class RenameSpec extends ParsleyTest {
}
}

object RenameSpec {
object Utils {
def crash(): Nothing = fail("Should not have been run.")
}

// These are dummy parsers used for the above tests.
// We don't actually care that they don't implement anything.
private class DummyParser extends LazyParsley[Any] {
override protected def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[_]])(implicit state: LetFinderState): M[R, Unit] = RenameSpec.crash()
override protected def preprocess[M[_, +_] : ContOps, R, A_ >: Any](implicit lets: LetMap): M[R, StrictParsley[A_]] = RenameSpec.crash()
override protected def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[_]])(implicit state: LetFinderState): M[R, Unit] = Utils.crash()
override protected def preprocess[M[_, +_] : ContOps, R, A_ >: Any](implicit lets: LetMap): M[R, StrictParsley[A_]] = Utils.crash()
override def visit[T, U[+_]](visitor: LazyParsleyIVisitor[T, U], context: T): U[Any] = visitor.visitUnknown(this, context)
override private [parsley] def prettyName = "dummyParser"
}

private class <**> extends LazyParsley[Any] {
override protected def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[_]])(implicit state: LetFinderState): M[R, Unit] = RenameSpec.crash()
override protected def preprocess[M[_, +_] : ContOps, R, A_ >: Any](implicit lets: LetMap): M[R, StrictParsley[A_]] = RenameSpec.crash()
override protected def findLetsAux[M[_, +_] : ContOps, R](seen: Set[LazyParsley[_]])(implicit state: LetFinderState): M[R, Unit] = Utils.crash()
override protected def preprocess[M[_, +_] : ContOps, R, A_ >: Any](implicit lets: LetMap): M[R, StrictParsley[A_]] = Utils.crash()
override def visit[T, U[+_]](visitor: LazyParsleyIVisitor[T, U], context: T): U[Any] = visitor.visitUnknown(this, context)
override private [parsley] def prettyName = "<**>"
}

0 comments on commit 90e250b

Please sign in to comment.