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

parsley.internal.deepembedding.SelectiveEmbedding.scala Maven / Gradle / Ivy

The newest version!
package parsley.internal.deepembedding

import ContOps.{result, ContAdapter}
import parsley.internal.machine.instructions

import scala.language.higherKinds

import Branch.FlipApp

private [deepembedding] sealed abstract class BranchLike[A, B, C, D](_b: =>Parsley[A], _p: =>Parsley[B], _q: =>Parsley[C],
                                                                     pretty: (String, String, String) => String, empty: =>BranchLike[A, B, C, D],
                                                                     instr: Int => instructions.Instr, finaliser: Option[instructions.Instr])
    extends Ternary[A, B, C, D](_b, _p, _q)(pretty, empty) {
    final override val numInstrs = 2
    final override def codeGen[Cont[_, +_], R](implicit ops: ContOps[Cont, R], instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        val toSecond = state.freshLabel()
        val end = state.freshLabel()
        first.codeGen >> {
            instrs += instr(toSecond)
            third.codeGen >> {
                for (instr <- finaliser) instrs += instr
                instrs += new instructions.Jump(end)
                instrs += new instructions.Label(toSecond)
                second.codeGen |> {
                    for (instr <- finaliser) instrs += instr
                    instrs += new instructions.Label(end)
                }
            }
        }
    }
}

private [parsley] final class Branch[A, B, C](_b: =>Parsley[Either[A, B]], _p: =>Parsley[A => C], _q: =>Parsley[B => C])
    extends BranchLike[Either[A, B], A => C, B => C, C](_b, _p, _q, (f, s, t) => s"branch($f, $s, $t)", Branch.empty, new instructions.Case(_), Some(FlipApp)) {

    override def optimise: Parsley[C] = first match {
        case Pure(Left(x)) => <*>(second, new Pure(x)).optimise
        case Pure(Right(y)) => <*>(third, new Pure(y)).optimise
        case _ => (second, third) match {
            case (Pure(f), Pure(g)) => <*>(new Pure((x: Either[A, B]) => x.fold(f, g)), first)
            case _ => this
        }
    }
}

private [parsley] final class If[A](_b: =>Parsley[Boolean], _p: =>Parsley[A], _q: =>Parsley[A])
    extends BranchLike[Boolean, A, A, A](_b, _p, _q, (f, s, t) => s"($f ? $s : $t)", If.empty, new instructions.If(_), None) {
    override def optimise: Parsley[A] = first match {
        case Pure(true) => second
        case Pure(false) => third
        case _ => this
    }
}

private [deepembedding] sealed abstract class FilterLike[A, B](_p: =>Parsley[A], pretty: String => String, empty: =>FilterLike[A, B],
                                                               fail: A => Parsley[B], instr: instructions.Instr, pred: A => Boolean)
    extends Unary[A, B](_p)(pretty, empty) {
    final override val numInstrs = 1
    final override def optimise: Parsley[B] = p match {
        case px@Pure(x) => if (!pred(x)) px.asInstanceOf[Parsley[B]] else fail(x)
        case z: MZero => z
        case _ => this
    }
    final override def codeGen[Cont[_, +_], R](implicit ops: ContOps[Cont, R], instrs: InstrBuffer, state: CodeGenState): Cont[R, Unit] = {
        p.codeGen |> (instrs += instr)
    }
}
private [parsley] final class FastFail[A](_p: =>Parsley[A], msggen: A => String)
    extends FilterLike[A, Nothing](_p, c => s"$c ! ?", FastFail.empty(msggen),
                                   x => new Fail(msggen(x)), new instructions.FastFail(msggen), _ => true) with MZero
private [parsley] final class FastUnexpected[A](_p: =>Parsley[A], msggen: A => String)
    extends FilterLike[A, Nothing](_p, c => s"$c.unexpected(?)", FastUnexpected.empty(msggen),
                                   x => new Unexpected(msggen(x)), new instructions.FastUnexpected(msggen), _ => true) with MZero
private [parsley] final class Filter[A](_p: =>Parsley[A], pred: A => Boolean)
    extends FilterLike[A, A](_p, c => s"$c.filter(?)", Filter.empty(pred),
                             _ => Empty, new instructions.Filter(pred), !pred(_))
private [parsley] final class FilterOut[A](_p: =>Parsley[A], pred: PartialFunction[A, String])
    extends FilterLike[A, A](_p, c => s"$c.filterOut(?)", FilterOut.empty(pred),
                             x => ErrorExplain(Empty, pred(x)), new instructions.FilterOut(pred), pred.isDefinedAt(_))
private [parsley] final class GuardAgainst[A](_p: =>Parsley[A], pred: PartialFunction[A, String])
    extends FilterLike[A, A](_p, c => s"$c.guardAgainst(?)", GuardAgainst.empty(pred),
                            x => new Fail(pred(x)), new instructions.GuardAgainst(pred), pred.isDefinedAt(_))

private [deepembedding] object Branch {
    def empty[A, B, C]: Branch[A, B, C] = new Branch(???, ???, ???)
    val FlipApp = new instructions.Lift2[Any, Any => Any, Any]((x, f) => f(x))
}
private [deepembedding] object If {
    def empty[A]: If[A] = new If(???, ???, ???)
}

private [deepembedding] object FastFail {
    def empty[A](msggen: A => String): FastFail[A] = new FastFail(???, msggen)
}
private [deepembedding] object FastUnexpected {
    def empty[A](msggen: A => String): FastUnexpected[A] = new FastUnexpected(???, msggen)
}
private [deepembedding] object Filter {
    def empty[A](pred: A => Boolean): Filter[A] = new Filter(???, pred)
}
private [deepembedding] object FilterOut {
    def empty[A](pred: PartialFunction[A, String]): FilterOut[A] = new FilterOut(???, pred)
}
private [deepembedding] object GuardAgainst {
    def empty[A](pred: PartialFunction[A, String]): GuardAgainst[A] = new GuardAgainst(???, pred)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy