Skip to content

Commit

Permalink
Removed unsafe() method, added Opaque combinator, does the same job…
Browse files Browse the repository at this point in the history
… but way better
  • Loading branch information
j-mie6 committed Aug 14, 2023
1 parent 8df33c8 commit 43d6a39
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 16 deletions.
5 changes: 1 addition & 4 deletions parsley/shared/src/main/scala/parsley/Parsley.scala
Original file line number Diff line number Diff line change
Expand Up @@ -921,10 +921,7 @@ final class Parsley[+A] private [parsley] (private [parsley] val internal: front
*
* @group special
*/
def unsafe(): Parsley[A] = {
internal.unsafe()
this
}
def unsafe(): Parsley[A] = new Parsley(new frontend.Opaque(this.internal))
// $COVERAGE-ON$

// $COVERAGE-OFF$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ private [deepembedding] final class Let[A](val p: StrictParsley[A]) extends Stri
def pretty: String = this.toString
// $COVERAGE-ON$
}
private [deepembedding] final class Opaque[A](p: StrictParsley[A]) extends StrictParsley[A] {
def inlinable = p.inlinable
override def codeGen[M[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): M[R,Unit] = p.codeGen
// $COVERAGE-OFF$
def pretty: String = p.pretty
// $COVERAGE-ON$
}

private [deepembedding] final class Put[S](reg: Reg[S], val p: StrictParsley[S]) extends Unary[S, Unit] {
override def codeGen[M[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
suspend(p.codeGen[M, R]) |>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ import StrictParsley.InstrBuffer
private [deepembedding] final class <*>[A, B](var left: StrictParsley[A => B], var right: StrictParsley[A]) extends StrictParsley[B] {
def inlinable: Boolean = false
// TODO: Refactor
// FIXME: Needs more interation with .safe
override def optimise: StrictParsley[B] = (left, right) match {
// Fusion laws
case (uf, ux@Pure(x)) if (uf.isInstanceOf[Pure[_]] || uf.isInstanceOf[_ <*> _]) && uf.safe && ux.safe => uf match {
case (uf, Pure(x)) if (uf.isInstanceOf[Pure[_]] || uf.isInstanceOf[_ <*> _]) => uf match {
// first position fusion
case Pure(f) => new Pure(f(x))
// second position fusion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,6 @@ private [deepembedding] trait StrictParsley[+A] {
*/
private [deepembedding] def inlinable: Boolean

/** Is this combinator known to be pure? */
final private [deepembedding] var safe = true

// $COVERAGE-OFF$
/** Pretty-prints a combinator tree, for internal debugging purposes only. */
private [deepembedding] def pretty: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ import parsley.internal.machine.instructions, instructions.Instr
private [parsley] abstract class LazyParsley[+A] private [deepembedding] {
// Public API
// $COVERAGE-OFF$
// TODO: remove in 5.0
/** Denotes this parser is unsafe, which will disable certain law-based optimisations that assume purity. */
private [parsley] final def unsafe(): Unit = sSafe = false
private [parsley] final def unsafe(): Unit = ()
/** Force the parser, which eagerly computes its instructions immediately */
private [parsley] final def force(): Unit = instrs: @nowarn
/** Denote that this parser is large enough that it might stack-overflow during
Expand Down Expand Up @@ -82,8 +83,6 @@ private [parsley] abstract class LazyParsley[+A] private [deepembedding] {
*/
protected def preprocess[M[_, +_]: ContOps, R, A_ >: A](implicit lets: LetMap, recs: RecMap): M[R, StrictParsley[A_]]

/** should the underlying strict tree be considered safe? */
final private var sSafe = true
/** should the `Id` instance be skipped? */
final private var cps = false
/** how many registers are used by the ''parent'' of this combinator (this combinator is part of a `flatMap` when this is not -1) */
Expand Down Expand Up @@ -181,10 +180,7 @@ private [parsley] abstract class LazyParsley[+A] private [deepembedding] {
}
/** Similar to `optimised` but does not check for inclusion in the `lets` or `recs` sets. */
private def unsafeOptimised[M[_, +_]: ContOps, R, A_ >: A](implicit lets: LetMap, recs: RecMap): M[R, StrictParsley[A_]] = {
for {p <- this.preprocess} yield {
p.safe = this.sSafe
p.optimise
}
for { p <- this.preprocess } yield p.optimise
}

// Processing with visitors.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,10 @@ private [parsley] final class DebugError[A](p: LazyParsley[A], name: String, asc

override def visit[T, U[+_]](visitor: LazyParsleyIVisitor[T, U], context: T): U[A] = visitor.visit(this, context)(p, name, ascii, errBuilder)
}

private [parsley] final class Opaque[A](p: LazyParsley[A]) extends Unary[A, A](p) {
override def make(p: StrictParsley[A]): StrictParsley[A] = new backend.Opaque(p)

override def visit[T, U[+_]](visitor: LazyParsleyIVisitor[T, U], context: T): U[A] = p.visit(visitor, context)
}
// $COVERAGE-ON$

0 comments on commit 43d6a39

Please sign in to comment.