Skip to content

Commit

Permalink
Add interpret for combinators
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-adam committed May 23, 2024
1 parent 553741f commit 9e0bbac
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
package pl.writeonly.catculator.core.calculators

import pl.writeonly.catculator.core.adt.calculus.Combinator.CombinatorBT
import pl.writeonly.catculator.core.adt.tree.BinaryTree.Leaf
import pl.writeonly.catculator.core.adt.tree.BinaryTree.Node
import pl.writeonly.catculator.core.adt.calculus.Combinator._
import pl.writeonly.catculator.core.adt.tree.BinaryTree._

object CombinatorCalculator {

def calculate(c: CombinatorBT): Unit = c match {
def interpret(c: CombinatorBT): CombinatorBT = c match {
case l @ Leaf(_) => l
case Node(Leaf(I), x) => x
case Node(Leaf(K), x) => Leaf(K)
case Node(Node(Leaf(K), x), y) => x
case Node(Node(Node(Leaf(S), x), y), z) =>
val first = Node(x, z)
val second = Node(y, z)
Node(first, second)

case Node(f, x) =>
case Leaf(a) =>
val reducedF = interpret(f)
val reducedX = interpret(x)
interpret(Node(reducedF, reducedX))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package pl.writeonly.catculator.core.calculators.lazyk

import pl.writeonly.catculator.core.adt.calculus.Combinator
import pl.writeonly.catculator.core.adt.calculus.Combinator._
import pl.writeonly.catculator.core.adt.tree.BinaryTree
import pl.writeonly.catculator.core.adt.tree.BinaryTree._
import pl.writeonly.catculator.core.calculators.lazyk.ADT._
import pl.writeonly.catculator.core.calculators.lazyk.Reducer.flippedApply
import spire.math.Natural

object Calculator {

val number0: ADTBT = Leaf(ADT.Num(Natural(0)))

val trueVar: ADTBT = Leaf(ADT.Com(K))

val falseVar: ADTBT = Node(trueVar, Leaf(ADT.Com(I)))

def run(program: ADTBT): Iterator[Safe[Natural]] = runWithTerminator(falseVar, program)

private def runWithTerminator(terminator: ADTBT, combinator: ADTBT): Iterator[Safe[Natural]] =
println("runWithTerminator2")
Iterator.unfold[Safe[Natural], (ADTBT, Safe[ADTBT])](terminator, Right(combinator)) { case (t: ADTBT, cM: Safe[ADTBT]) =>
val a = cM.flatMap(realizeWithTrue)
val s = cM.flatMap(Reducer.flippedApply(t, _))
Option(a, (t, s))
}

private def runWithTerminatorNumber(terminator: ADTBT, combinator: ADTBT): Safe[Unit] = realizeWithTrue(combinator).flatMap(output(terminator, combinator, _))

def realizeWithTrue(combinator: ADTBT): Safe[Natural] = flippedApply(trueVar, combinator).flatMap(realize)

def realize(combinator: ADTBT): Safe[Natural] = flippedApply(Leaf(ADT.Succ()), combinator).flatMap(flippedApply(number0, _)).flatMap(naturalSafe)

private def naturalSafe(combinator: ADTBT): Safe[Natural] = combinator match {
case Leaf(ADT.Num(x)) => Right(x)
case x => Left(s"Invalid output format. Output should be the list of Church numerals. $x")
}

private def output(terminator: ADTBT, combinator: ADTBT, number: Natural): Safe[Unit] = Reducer
.apply(combinator, terminator)
.flatMap(runWithTerminatorNumber(terminator, _))

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package pl.writeonly.catculator.core.calculators.lazyk

import pl.writeonly.catculator.core.adt.calculus.InputEncoder._
import pl.writeonly.catculator.core.adt.tree.BinaryTree.Node
import pl.writeonly.catculator.core.calculators.lazyk.ADT.ADTBT
import pl.writeonly.catculator.core.calculators.lazyk.ADT.Safe
import pl.writeonly.catculator.core.calculators.lazyk.ADT.fromCombinatorBT
import pl.writeonly.catculator.core.calculators.lazyk.Calculator.run
import pl.writeonly.catculator.core.calculators.lazyk.Reducer.reduce

object Evaluator {

def evalCombinator(combinator: ADTBT, input: String): Safe[String] =
for c <- reduce(Node(combinator, fromCombinatorBT(readInput(input))))
yield run(c).map(_.toOption.get.toBigInt.toInt.toChar).mkString

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package pl.writeonly.catculator.core.reducers

import pl.writeonly.catculator.core.Extras.ifElse
import pl.writeonly.catculator.core.adt.calculus.Combinator._
import pl.writeonly.catculator.core.adt.calculus.Combinator._
import pl.writeonly.catculator.core.adt.calculus.Lambda
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.adt.calculus._
import spire.implicits.eqOps

object AbstractionReducer {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package pl.writeonly.catculator.core.calculators.lazyk

import mouse.all.anySyntaxMouse
import org.scalatest.prop.TableFor1
import pl.writeonly.catculator.core.TableDrivenPropertySpec
import pl.writeonly.catculator.core.adt.calculus.Combinator.CombinatorBT
import pl.writeonly.catculator.core.adt.calculus.Constants._
import pl.writeonly.catculator.core.adt.calculus.InputEncoder._
import pl.writeonly.catculator.core.calculators.lazyk.ADT._
import spire.math.Natural

class CalculatorSpec extends TableDrivenPropertySpec {

val numbers: TableFor1[Long] = Table("number", 0, 1, 4, 8, 9, 16, 27, 36, 64, 81, 100, 121, 125, 256)

def realizeFromCombinatorBT(c: CombinatorBT): Safe[Natural] = c |> fromCombinatorBT |> Calculator.realize

it should "realize false" in {
val result = realizeFromCombinatorBT(falseCom)
result.value shouldBe Natural.zero
}

it should "realize I" in {
val result = realizeFromCombinatorBT(iCom)
result.value shouldBe Natural.one
}

it should "realize successor false" in {
val c = successor(falseCom)
val result = realizeFromCombinatorBT(c)
result.value shouldBe Natural.one
}

it should "realize numbers" in {
forAll(numbers) { number =>
val natural = Natural(number)
val c = church(natural)
val result = realizeFromCombinatorBT(c)
result.value shouldBe natural
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ import mouse.all.anySyntaxMouse
import org.scalatest.prop._
import pl.writeonly.catculator.core.LambdaConfig._
import pl.writeonly.catculator.core.TableDrivenPropertySpec
import pl.writeonly.catculator.core.adt.calculus.Combinator.I
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.adt.tree.BinaryTree.Leaf
import pl.writeonly.catculator.core.calculators.lazyk.ADT
import pl.writeonly.catculator.core.calculators.lazyk.ADT.ADTBT
import pl.writeonly.catculator.core.calculators.lazyk.ADT.fromCombinatorBT
import pl.writeonly.catculator.core.calculators.lazyk.Calculator
import pl.writeonly.catculator.core.calculators.lazyk.Evaluator
import pl.writeonly.catculator.core.generators.HaskellGenerator
import pl.writeonly.catculator.core.parsers.HaskellParser
import pl.writeonly.catculator.core.reducers.AbstractionReducer.reduceAbstraction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import pl.writeonly.catculator.core.TableDrivenPropertySpec
import pl.writeonly.catculator.core.adt.calculus.Lambda
import pl.writeonly.catculator.core.adt.calculus.Lambda._
import pl.writeonly.catculator.core.generators.LambdaGenerator
import pl.writeonly.catculator.core.parsers.LambdaParser
import pl.writeonly.catculator.core.reducers.AbstractionReducer.reduceAbstraction
import pl.writeonly.catculator.core.reducers.SugarReducer._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package pl.writeonly.catculator.core.reducers
import pl.writeonly.catculator.core.UnitSpec
import pl.writeonly.catculator.core.adt.calculus.Combinator.I
import pl.writeonly.catculator.core.adt.calculus.Lambda.Com
import pl.writeonly.catculator.core.reducers.SugarReducer
import pl.writeonly.catculator.core.parsers.LambdaParser
import pl.writeonly.catculator.core.reducers.SugarReducer.lambdaSugarReducer

class LambdaTest extends UnitSpec {
Expand Down

0 comments on commit 9e0bbac

Please sign in to comment.