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

parsley.internal.deepembedding.backend.PrimitiveEmbedding.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 parsley.debug.{Breakpoint, EntryBreak, ExitBreak, FullBreak}
import parsley.errors.ErrorBuilder
import parsley.registers.Reg

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

import StrictParsley.InstrBuffer
private [deepembedding] final class Attempt[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A](false) {
    override val instr: instructions.Instr = instructions.PopHandlerAndState
    override def instrNeedsLabel: Boolean = false
    override def handlerLabel(state: CodeGenState): Int  = state.getLabel(instructions.RestoreAndFail)
    override def optimise: StrictParsley[A] = p match {
        case p: CharTok => p
        case p: Attempt[_] => p
        case StringTok(s) if s.size == 1 => p
        case _ => this
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"attempt($p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class Look[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A](true) {
    override val instr: instructions.Instr = instructions.RestoreHintsAndState
    override def instrNeedsLabel: Boolean = false
    override def handlerLabel(state: CodeGenState): Int  = state.getLabel(instructions.PopStateRestoreHintsAndFail)
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"lookAhead($p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class NotFollowedBy[A](val p: StrictParsley[A]) extends Unary[A, Unit] {
    /*override def optimise: StrictParsley[Unit] = p match {
        case _: MZero => new Pure(())
        case _        => this
    }*/
    final override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.PushHandlerAndState(handler, saveHints = true, hideHints = true)
        suspend[Cont, R, Unit](p.codeGen) |> {
            instrs += instructions.NegLookFail
            instrs += new instructions.Label(handler)
            instrs += instructions.NegLookGood
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"notFollowedBy($p)"
    // $COVERAGE-ON$
}

private [deepembedding] final class Rec[A](val call: instructions.Call) extends StrictParsley[A] {
    def inlinable: Boolean = true
    // Must be a def, since call.label can change!
    def label: Int = call.label

    final override def codeGen[Cont[_, +_], R](implicit ops: ContOps[Cont], instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = result(instrs += call)

    // $COVERAGE-OFF$
    def pretty[Cont[_, +_]: ContOps, R]: Cont[R, String] = result(this.toString())
    // $COVERAGE-ON$
}
private [deepembedding] final class Let[A](val p: StrictParsley[A]) extends StrictParsley[A] {
    def inlinable: Boolean = true
    def label(implicit state: CodeGenState): Int = state.getLabel(this)
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        result(instrs += new instructions.Call(label))
    }

    // $COVERAGE-OFF$
    def pretty[Cont[_, +_]: ContOps, R]: Cont[R, String] = result(this.toString())
    // $COVERAGE-ON$
}
private [deepembedding] final class Put[S](reg: Reg[S], val p: StrictParsley[S]) extends Unary[S, Unit] {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        suspend(p.codeGen[Cont, R]) |>
        (instrs += new instructions.Put(reg.addr))
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"put(r${reg.addr}, $p)"
    // $COVERAGE-ON$
}

private [deepembedding] final class NewReg[S, A](reg: Reg[S], init: StrictParsley[S], body: StrictParsley[A]) extends StrictParsley[A] {
    def inlinable: Boolean = false
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val handler = state.getLabelForPutAndFail(reg)
        suspend(init.codeGen[Cont, R]) >> {
            instrs += new instructions.Get(reg.addr)
            instrs += new instructions.SwapAndPut(reg.addr)
            instrs += new instructions.PushHandler(handler)
            suspend(body.codeGen[Cont, R]) |> {
                instrs += new instructions.SwapAndPut(reg.addr)
                instrs += instructions.PopHandler
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty[Cont[_, +_]: ContOps, R]: Cont[R,String] =
        for {
            s1 <- init.pretty
            s2 <- body.pretty
        } yield s"newreg(r${reg.addr}, $s1, $s2)"
    // $COVERAGE-ON$
}

// $COVERAGE-OFF$
private [deepembedding] final class Debug[A](val p: StrictParsley[A], name: String, ascii: Boolean, break: Breakpoint) extends Unary[A, A] {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.LogBegin(handler, name, ascii, (break eq EntryBreak) || (break eq FullBreak))
        suspend(p.codeGen[Cont, R]) |> {
            instrs += new instructions.Label(handler)
            instrs += new instructions.LogEnd(name, ascii, (break eq ExitBreak) || (break eq FullBreak))
        }
    }
    final override def pretty(p: String): String = p
}
private [deepembedding] final class DebugError[A](val p: StrictParsley[A], name: String, ascii: Boolean, errBuilder: ErrorBuilder[_]) extends Unary[A, A] {
    override def codeGen[Cont[_, +_]: ContOps, R](implicit instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.LogErrBegin(handler, name, ascii)(errBuilder)
        suspend(p.codeGen[Cont, R]) |> {
            instrs += instructions.Swap
            instrs += new instructions.Label(handler)
            instrs += new instructions.LogErrEnd(name, ascii)(errBuilder)
        }
    }
    final override def pretty(p: String): String = p
}
// $COVERAGE-ON$

private [backend] object Attempt {
    def unapply[A](self: Attempt[A]): Some[StrictParsley[A]] = Some(self.p)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy