All Downloads are FREE. Search and download functionalities are using the official Maven repository.

parsley.internal.deepembedding.backend.IterativeEmbedding.scala Maven / Gradle / Ivy

There is a newer version: 5.0.0-M6
Show newest version
/* SPDX-FileCopyrightText: © 2022 Parsley Contributors 
 * SPDX-License-Identifier: BSD-3-Clause
 */
package parsley.internal.deepembedding.backend

import scala.collection.mutable

import parsley.exceptions.NonProductiveIterationException

import parsley.internal.deepembedding.ContOps, ContOps.{ContAdapter, suspend}
import parsley.internal.deepembedding.singletons._
import parsley.internal.machine.instructions

import StrictParsley.InstrBuffer

private [backend] sealed abstract class ManyLike[A, B](name: String, unit: B) extends Unary[A, B] {
    def instr(label: Int): instructions.Instr
    def preamble(instrs: InstrBuffer): Unit
    final override def optimise: StrictParsley[B] = p match {
        case _: Pure[_] => throw new NonProductiveIterationException(name) // scalastyle:ignore throw
        case _: MZero   => new Pure(unit)
        case _          => this
    }
    final override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val body = state.freshLabel()
        val handler = state.freshLabel()
        preamble(instrs)
        instrs += new instructions.PushHandlerAndCheck(handler, saveHints = false)
        instrs += new instructions.Label(body)
        suspend(p.codeGen[Cont, R]) |> {
            instrs += new instructions.Label(handler)
            instrs += instr(body)
        }
    }
}
private [deepembedding] final class Many[A](val p: StrictParsley[A]) extends ManyLike[A, List[A]]("many", Nil) {
    override def instr(label: Int): instructions.Instr = new instructions.Many(label)
    override def preamble(instrs: InstrBuffer): Unit = instrs += new instructions.Fresh(mutable.ListBuffer.empty[Any])
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"many($p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class SkipMany[A](val p: StrictParsley[A]) extends ManyLike[A, Unit]("skipMany", ()) {
    override def instr(label: Int): instructions.Instr = new instructions.SkipMany(label)
    override def preamble(instrs: InstrBuffer): Unit = ()
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"skipMany($p)"
    // $COVERAGE-ON$
}
private [backend] sealed abstract class ChainLike[A](p: StrictParsley[A], op: StrictParsley[A => A]) extends StrictParsley[A] {
    def inlinable: Boolean = false
    override def optimise: StrictParsley[A] = op match {
        case _: Pure[_] => throw new NonProductiveIterationException("chain") // scalastyle:ignore throw
        case _: MZero   => p
        case _          => this
    }
    // $COVERAGE-OFF$
    final override def pretty[Cont[_, +_]: ContOps, R]: Cont[R,String] = for {c1 <- p.pretty; c2 <- op.pretty} yield pretty(c1, c2)
    protected def pretty(p: String, op: String): String
    // $COVERAGE-ON$
}
private [deepembedding] final class ChainPost[A](p: StrictParsley[A], op: StrictParsley[A => A]) extends ChainLike[A](p, op) {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val body = state.freshLabel()
        val handler = state.freshLabel()
        suspend(p.codeGen[Cont, R]) >> {
            instrs += new instructions.PushHandlerAndCheck(handler, saveHints = false)
            instrs += new instructions.Label(body)
            suspend(op.codeGen[Cont, R]) |> {
                instrs += new instructions.Label(handler)
                instrs += new instructions.ChainPost(body)
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String, op: String): String = s"chainPost($p, $op)"
    // $COVERAGE-ON$
}
private [deepembedding] final class ChainPre[A](p: StrictParsley[A], op: StrictParsley[A => A]) extends ChainLike[A](p, op) {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val body = state.freshLabel()
        val handler = state.freshLabel()
        instrs += new instructions.Push(identity[Any] _)
        instrs += new instructions.PushHandlerAndCheck(handler, saveHints = false)
        instrs += new instructions.Label(body)
        suspend(op.codeGen[Cont, R]) >> {
            instrs += new instructions.Label(handler)
            instrs += new instructions.ChainPre(body)
            suspend(p.codeGen[Cont, R]) |>
            (instrs += instructions.Apply)
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String, op: String): String = s"chainPre($op, $p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class Chainl[A, B](init: StrictParsley[B], p: StrictParsley[A], op: StrictParsley[(B, A) => B]) extends StrictParsley[B] {
    def inlinable: Boolean = false
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val body = state.freshLabel()
        val handler = state.freshLabel()
        suspend(init.codeGen[Cont, R]) >> {
            instrs += new instructions.PushHandlerAndCheck(handler, saveHints = false)
            instrs += new instructions.Label(body)
            op.codeGen[Cont, R] >>
            suspend(p.codeGen[Cont, R]) |> {
                instrs += new instructions.Label(handler)
                instrs += new instructions.Chainl(body)
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty[Cont[_, +_]: ContOps, R]: Cont[R,String] =
        for {
            s1 <- init.pretty
            s2 <- p.pretty
            s3 <- op.pretty
        } yield s"chainl1($s1, $s2, $s3)"
    // $COVERAGE-ON$
}
private [deepembedding] final class Chainr[A, B](p: StrictParsley[A], op: StrictParsley[(A, B) => B], private [Chainr] val wrap: A => B)
    extends StrictParsley[B] {
    def inlinable: Boolean = false
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit]= {
        val body = state.freshLabel()
        val handler1 = state.getLabel(instructions.ChainrWholeHandler)
        val handler2 = state.freshLabel()
        instrs += new instructions.Push(identity[Any] _)
        instrs += new instructions.PushHandlerAndCheck(handler1, saveHints = false)
        instrs += new instructions.Label(body)
        suspend(p.codeGen[Cont, R]) >> {
            instrs += new instructions.PushHandlerAndCheck(handler2, saveHints = false)
            suspend(op.codeGen[Cont, R]) |> {
                instrs += new instructions.ChainrJump(body)
                instrs += new instructions.Label(handler2)
                instrs += instructions.ChainrOpHandler(wrap)
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty[Cont[_, +_]: ContOps, R]: Cont[R,String] =
        for {
            s1 <- p.pretty
            s2 <- op.pretty
        } yield s"chainr1($s1, $s2)"
    // $COVERAGE-ON$
}
private [deepembedding] final class SepEndBy1[A, B](p: StrictParsley[A], sep: StrictParsley[B]) extends StrictParsley[List[A]] {
    def inlinable: Boolean = false
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val body = state.freshLabel()
        val handler1 = state.freshLabel()
        val handler2 = state.freshLabel()
        instrs += new instructions.Fresh(mutable.ListBuffer.empty[Any])
        instrs += new instructions.PushHandlerAndCheck(handler1, saveHints = false)
        instrs += new instructions.Label(body)
        suspend(p.codeGen[Cont, R]) >> {
            instrs += new instructions.PushHandlerAndCheck(handler2, saveHints = false)
            suspend(sep.codeGen[Cont, R]) |> {
                instrs += new instructions.SepEndBy1Jump(body)
                instrs += new instructions.Label(handler2)
                instrs += instructions.SepEndBy1SepHandler
                instrs += new instructions.Label(handler1)
                instrs += instructions.SepEndBy1WholeHandler
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty[Cont[_, +_]: ContOps, R]: Cont[R,String] =
        for {
            s1 <- p.pretty
            s2 <- sep.pretty
        } yield s"sepEndBy1($s1, $s2)"
    // $COVERAGE-ON$
}
private [deepembedding] final class ManyUntil[A](val p: StrictParsley[Any]) extends Unary[Any, List[A]] {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val start = state.freshLabel()
        val loop = state.freshLabel()
        instrs += new instructions.Fresh(mutable.ListBuffer.empty[Any])
        instrs += new instructions.PushHandler(loop)
        instrs += new instructions.Label(start)
        suspend(p.codeGen[Cont, R]) |> {
            instrs += new instructions.Label(loop)
            instrs += new instructions.ManyUntil(start)
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"manyUntil($p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class SkipManyUntil(val p: StrictParsley[Any]) extends Unary[Any, Unit] {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val start = state.freshLabel()
        val loop = state.freshLabel()
        instrs += new instructions.PushHandler(loop)
        instrs += new instructions.Label(start)
        suspend(p.codeGen[Cont, R]) |> {
            instrs += new instructions.Label(loop)
            instrs += new instructions.SkipManyUntil(start)
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"manyUntil($p)"
    // $COVERAGE-ON$
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy