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

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

The newest version!
/*
 * Copyright 2020 Parsley Contributors 
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
package parsley.internal.deepembedding.backend

import parsley.debug.{Breakpoint, EntryBreak, ExitBreak, FullBreak, Profiler}
import parsley.errors.ErrorBuilder
import parsley.state.Ref

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

import StrictParsley.InstrBuffer
import org.typelevel.scalaccompat.annotation.nowarn3

private [deepembedding] final class Attempt[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A] {
    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"atomic($p)"
    // $COVERAGE-ON$
}
private [deepembedding] final class Look[A](val p: StrictParsley[A]) extends ScopedUnaryWithState[A, A] {
    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] {
    final override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.PushHandlerAndState(handler)
        suspend[M, R, Unit](p.codeGen(producesResults = false)) |> {
            instrs += instructions.NegLookFail
            instrs += new instructions.Label(handler)
            instrs += instructions.NegLookGood
            if (producesResults) instrs += instructions.Push.Unit
        }
    }
    // $COVERAGE-OFF$
    final override def pretty(p: String): String = s"notFollowedBy($p)"
    // $COVERAGE-ON$
}

private [deepembedding] final class Let[A] extends StrictParsley[A] {
    def inlinable: Boolean = true
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = result {
        instrs += new instructions.Call(state.getLabel(this, producesResults))
    }

    // $COVERAGE-OFF$
    def pretty: String = this.toString
    // $COVERAGE-ON$
}
private [deepembedding] final class Opaque[A](p: StrictParsley[A]) extends StrictParsley[A] {
    def inlinable: Boolean = p.inlinable
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R,Unit] = {
        // this blocks result suppression, because the ErrorGen combinators have non-inspectible control flow
        p.codeGen(producesResults = true) |> {
            if (!producesResults) instrs += instructions.Pop
        }
    }
    // $COVERAGE-OFF$
    def pretty: String = p.pretty
    // $COVERAGE-ON$
}

private [deepembedding] final class Put[S](reg: Ref[S], val p: StrictParsley[S]) extends Unary[S, Unit] {
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        suspend(p.codeGen[M, R](producesResults = true)) |> {
            instrs += new instructions.Put(reg.addr)
            if (producesResults) instrs += instructions.Push.Unit
        }
    }
    // $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: Ref[S], init: StrictParsley[S], body: StrictParsley[A]) extends StrictParsley[A] {
    def inlinable: Boolean = false
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        val handler = state.getLabelForPutAndFail(reg)
        suspend(init.codeGen[M, R](producesResults = true)) >> {
            instrs += new instructions.Get(reg.addr)
            instrs += new instructions.SwapAndPut(reg.addr)
            instrs += new instructions.PushHandler(handler)
            suspend(body.codeGen[M, R](producesResults)) |> {
                instrs += (if (producesResults) new instructions.SwapAndPut(reg.addr) else new instructions.Put(reg.addr))
                instrs += instructions.PopHandler
            }
        }
    }
    // $COVERAGE-OFF$
    final override def pretty: String = s"newreg(r${reg.addr}, ${init.pretty}, ${body.pretty})"
    // $COVERAGE-ON$
}

private [deepembedding] final class Span(p: StrictParsley[_]) extends StrictParsley[String] {
    def inlinable: Boolean = false
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        if (producesResults) {
            val handler = state.getLabel(instructions.PopStateAndFail)
            instrs += new instructions.PushHandlerAndState(handler)
            suspend[M, R, Unit](p.codeGen(producesResults = false)) |> {
                instrs += instructions.Span
            }
        }
        else p.codeGen(producesResults = false)
    }
    // $COVERAGE-OFF$
    final override def pretty: String = s"${p.pretty}.span"
    // $COVERAGE-ON$
}

// $COVERAGE-OFF$
private [deepembedding] final class Debug[A](val p: StrictParsley[A], name: String, ascii: Boolean,
                                             break: Breakpoint, watchedRefs: scala.Seq[(Ref[_], String)] @nowarn3)
    extends Unary[A, A] {
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        val watchedAddrs = watchedRefs.map {
            case (r, name) => (r.addr, name)
        }: @nowarn3
        val handler = state.freshLabel()
        instrs += new instructions.LogBegin(handler, name, ascii, (break eq EntryBreak) || (break eq FullBreak), watchedAddrs)
        suspend(p.codeGen[M, R](producesResults)) |> {
            instrs += new instructions.Label(handler)
            instrs += new instructions.LogEnd(name, ascii, (break eq ExitBreak) || (break eq FullBreak), watchedAddrs)
        }
    }
    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[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R, Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.LogErrBegin(handler, name, ascii)(errBuilder)
        suspend(p.codeGen[M, R](producesResults)) |> {
            if (producesResults) instrs += instructions.Swap
            instrs += new instructions.Label(handler)
            instrs += new instructions.LogErrEnd(name, ascii)(errBuilder)
        }
    }
    final override def pretty(p: String): String = p
}

private [deepembedding] final class Profile[A](val p: StrictParsley[A], name: String, profiler: Profiler) extends Unary[A, A] {
    override def codeGen[M[_, +_]: ContOps, R](producesResults: Boolean)(implicit instrs: InstrBuffer, state: CodeGenState): M[R,Unit] = {
        val handler = state.freshLabel()
        instrs += new instructions.ProfileEnter(handler, name, profiler)
        suspend(p.codeGen[M, R](producesResults)) |> {
            instrs += new instructions.Label(handler)
            instrs += new instructions.ProfileExit(name, profiler)
        }
    }
    final override def pretty(p: String): String = p
}
private [backend] object Profile {
    def unapply[A](p: Profile[A]): Some[StrictParsley[A]] = Some(p.p)
}
// $COVERAGE-ON$

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy