Rewrite the block system so that I can implement the catamorphism easily
This commit is contained in:
parent
33df0eb120
commit
8b52321920
|
@ -20,9 +20,12 @@ lazy val graph = (project in file("graph")).settings(
|
||||||
name := "fancadegraph",
|
name := "fancadegraph",
|
||||||
version := "0.1.0",
|
version := "0.1.0",
|
||||||
scalaVersion := "2.13.3",
|
scalaVersion := "2.13.3",
|
||||||
|
resolvers += Resolver.bintrayRepo("alexknvl", "maven"),
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
"org.scala-graph" %% "graph-core" % "1.13.2",
|
"org.scala-graph" %% "graph-core" % "1.13.2",
|
||||||
|
"com.alexknvl" %% "polymorphic" % "0.5.0",
|
||||||
),
|
),
|
||||||
|
addCompilerPlugin("org.typelevel" %% "kind-projector" % "0.11.0" cross CrossVersion.full),
|
||||||
).dependsOn(scodec)
|
).dependsOn(scodec)
|
||||||
|
|
||||||
lazy val tagless = (project in file("tagless")).settings(
|
lazy val tagless = (project in file("tagless")).settings(
|
||||||
|
@ -36,6 +39,7 @@ lazy val tagless = (project in file("tagless")).settings(
|
||||||
"org.typelevel" %% "cats-core" % "2.1.1",
|
"org.typelevel" %% "cats-core" % "2.1.1",
|
||||||
"org.typelevel" %% "cats-effect" % "2.1.3",
|
"org.typelevel" %% "cats-effect" % "2.1.3",
|
||||||
"io.chrisdavenport" %% "fuuid" % "0.4.0",
|
"io.chrisdavenport" %% "fuuid" % "0.4.0",
|
||||||
|
"io.higherkindness" %% "droste-core" % "0.8.0",
|
||||||
"org.scalameta" %% "munit" % "0.7.9" % Test,
|
"org.scalameta" %% "munit" % "0.7.9" % Test,
|
||||||
),
|
),
|
||||||
testFrameworks += new TestFramework("munit.Framework"),
|
testFrameworks += new TestFramework("munit.Framework"),
|
||||||
|
|
|
@ -1,22 +1,14 @@
|
||||||
package tf.bug.fancadegraph
|
package tf.bug.fancadegraph
|
||||||
|
|
||||||
|
import polymorphic._
|
||||||
import tf.bug.fancadescodec.{Metadata, Position}
|
import tf.bug.fancadescodec.{Metadata, Position}
|
||||||
|
|
||||||
case class Block[T](
|
case class Block(
|
||||||
position: Position,
|
position: Position,
|
||||||
definition: BlockDefinition[T],
|
template: Exists[Template]
|
||||||
argument: T
|
|
||||||
)(
|
|
||||||
implicit ev: Argument[T]
|
|
||||||
) {
|
) {
|
||||||
def metadata: Vector[Metadata] = ev.encode(argument)(position)
|
def metadata: Vector[Metadata] = {
|
||||||
}
|
val t = Exists.unwrap(template)
|
||||||
|
t.ev.encode(t.args)(position)
|
||||||
object Block {
|
}
|
||||||
def apply(position: Position, definition: BlockDefinition[Unit]): Block[Unit] =
|
|
||||||
new Block(
|
|
||||||
position,
|
|
||||||
definition,
|
|
||||||
()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
package tf.bug.fancadegraph
|
package tf.bug.fancadegraph
|
||||||
|
|
||||||
import cats.data._
|
import cats.data._
|
||||||
|
import polymorphic._
|
||||||
import scalax.collection.Graph
|
import scalax.collection.Graph
|
||||||
import scalax.collection.GraphEdge.DiHyperEdge
|
import scalax.collection.GraphEdge.DiHyperEdge
|
||||||
import tf.bug.{fancadescodec => fansc}
|
import tf.bug.{fancadescodec => fansc}
|
||||||
|
|
||||||
case class Level(
|
case class Level(
|
||||||
blocks: Set[Block[_]],
|
blocks: Set[Block],
|
||||||
wires: Graph[Pin, DiHyperEdge]
|
wires: Graph[Pin, DiHyperEdge]
|
||||||
)
|
) {
|
||||||
|
def boundary =
|
||||||
|
blocks.foldLeft(fansc.Boundary(0, 0, 0)) {
|
||||||
|
case (fansc.Boundary(lr, du, nf), block) =>
|
||||||
|
val tlr = block.position.lr + Exists.unwrap(block.template).definition.width
|
||||||
|
val tdu = block.position.du + Exists.unwrap(block.template).definition.height
|
||||||
|
val tnf = block.position.nf + Exists.unwrap(block.template).definition.depth
|
||||||
|
fansc.Boundary(lr.max(tlr), du.max(tdu), nf.max(tnf))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object Level {
|
object Level {
|
||||||
|
|
||||||
|
@ -17,26 +27,21 @@ object Level {
|
||||||
}
|
}
|
||||||
|
|
||||||
def encode(level: Level): tf.bug.fancadescodec.Entry = {
|
def encode(level: Level): tf.bug.fancadescodec.Entry = {
|
||||||
val boundary = level.blocks.foldLeft(fansc.Boundary(0, 0, 0)) {
|
val boundary = level.boundary
|
||||||
case (fansc.Boundary(lr, du, nf), block) =>
|
|
||||||
val tlr = block.position.lr + block.definition.width
|
|
||||||
val tdu = block.position.du + block.definition.height
|
|
||||||
val tnf = block.position.nf + block.definition.depth
|
|
||||||
fansc.Boundary(lr.max(tlr), du.max(tdu), nf.max(tnf))
|
|
||||||
}
|
|
||||||
val objs: Vector[fansc.Obj] = {
|
val objs: Vector[fansc.Obj] = {
|
||||||
val initialVector = Vector.fill(boundary.sizeNF, boundary.sizeDU, boundary.sizeLR)(fansc.Obj.empty)
|
val initialVector = Vector.fill(boundary.sizeNF, boundary.sizeDU, boundary.sizeLR)(fansc.Obj.empty)
|
||||||
level.blocks.foldLeft(initialVector) {
|
level.blocks.foldLeft(initialVector) {
|
||||||
case (ew, nb) =>
|
case (ew, nb) =>
|
||||||
val fansc.Position(sx, sy, sz) = nb.position
|
val fansc.Position(sx, sy, sz) = nb.position
|
||||||
(0 until nb.definition.depth).foldLeft(ew) {
|
val nbd = Exists.unwrap(nb.template).definition
|
||||||
|
(0 until nbd.depth).foldLeft(ew) {
|
||||||
case (zw, z) =>
|
case (zw, z) =>
|
||||||
(0 until nb.definition.height).foldLeft(zw) {
|
(0 until nbd.height).foldLeft(zw) {
|
||||||
case (yw, y) =>
|
case (yw, y) =>
|
||||||
(0 until nb.definition.width).foldLeft(yw) {
|
(0 until nbd.width).foldLeft(yw) {
|
||||||
case (xw, x) =>
|
case (xw, x) =>
|
||||||
val objInd = x + (y * nb.definition.width) + (z * nb.definition.width * nb.definition.height)
|
val objInd = x + (y * nbd.width) + (z * nbd.width * nbd.height)
|
||||||
xw.updated(sz + z, xw(sz + z).updated(sy + y, xw(sz + z)(sy + y).updated(sx + x, nb.definition.ids(objInd))))
|
xw.updated(sz + z, xw(sz + z).updated(sy + y, xw(sz + z)(sy + y).updated(sx + x, nbd.ids(objInd))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package tf.bug.fancadegraph
|
||||||
import cats.effect.{Blocker, ExitCode, IO, IOApp}
|
import cats.effect.{Blocker, ExitCode, IO, IOApp}
|
||||||
import fs2._
|
import fs2._
|
||||||
import java.nio.file.{Paths, StandardOpenOption}
|
import java.nio.file.{Paths, StandardOpenOption}
|
||||||
|
import polymorphic._
|
||||||
import scalax.collection.Graph
|
import scalax.collection.Graph
|
||||||
import scalax.collection.GraphEdge.DiHyperEdge
|
import scalax.collection.GraphEdge.DiHyperEdge
|
||||||
import scodec.stream.StreamEncoder
|
import scodec.stream.StreamEncoder
|
||||||
|
@ -11,8 +12,8 @@ import tf.bug.fancadescodec.{Cartridge, Codecs, Position}
|
||||||
object Main extends IOApp {
|
object Main extends IOApp {
|
||||||
|
|
||||||
override def run(args: List[String]): IO[ExitCode] = {
|
override def run(args: List[String]): IO[ExitCode] = {
|
||||||
val winBlock = Block(Position(0, 0, 0), BlockDefinition.Win, true)
|
val winBlock = Block(Position(0, 0, 0), Exists(Template(BlockDefinition.Win, true)))
|
||||||
val loseBlock = Block(Position(0, 0, 3), BlockDefinition.Lose, true)
|
val loseBlock = Block(Position(0, 0, 3), Exists(Template(BlockDefinition.Lose, true)))
|
||||||
val loseAfter = Pin(loseBlock, BlockDefinition.Lose.after)
|
val loseAfter = Pin(loseBlock, BlockDefinition.Lose.after)
|
||||||
val winBefore = Pin(winBlock, BlockDefinition.Win.before)
|
val winBefore = Pin(winBlock, BlockDefinition.Win.before)
|
||||||
val level = Level(
|
val level = Level(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package tf.bug.fancadegraph
|
package tf.bug.fancadegraph
|
||||||
|
|
||||||
case class Pin(
|
case class Pin(
|
||||||
owner: Block[_],
|
owner: Block,
|
||||||
definition: PinDefinition
|
definition: PinDefinition
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
package tf.bug.fancadegraph
|
||||||
|
|
||||||
|
case class Template[T](definition: BlockDefinition[T], args: T)(implicit val ev: Argument[T])
|
|
@ -1,35 +1,56 @@
|
||||||
package tf.bug.fancadetagless
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
import tf.bug.fancadegraph.Level
|
import cats._
|
||||||
import tf.bug.fancadegraph.BlockDefinition
|
import cats.implicits._
|
||||||
|
import higherkindness.droste._
|
||||||
|
import polymorphic._
|
||||||
import tf.bug.fancadegraph.PinDefinition
|
import tf.bug.fancadegraph.PinDefinition
|
||||||
|
import tf.bug.fancadegraph.Level
|
||||||
import tf.bug.fancadegraph.Block
|
import tf.bug.fancadegraph.Block
|
||||||
|
import tf.bug.fancadegraph.Template
|
||||||
import tf.bug.fancadescodec.Position
|
import tf.bug.fancadescodec.Position
|
||||||
import scalax.collection.Graph
|
|
||||||
import tf.bug.fancadegraph.Argument
|
|
||||||
|
|
||||||
sealed trait Fancade {
|
sealed trait Fancade[A] {
|
||||||
|
val template: Exists[Template]
|
||||||
val pins: Vector[PinDefinition]
|
val pins: Vector[PinDefinition]
|
||||||
|
|
||||||
def render: Level
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Fancade {
|
object Fancade {
|
||||||
|
|
||||||
final case class Capture[T](newBlock: BlockDefinition[T], args: T, pins: Vector[PinDefinition])(implicit arg: Argument[T]) extends Fancade {
|
implicit val fancadeFunctor: Functor[Fancade] = new Functor[Fancade] {
|
||||||
override def render: Level = {
|
override def map[A, B](fa: Fancade[A])(f: A => B): Fancade[B] =
|
||||||
Level(
|
fa match {
|
||||||
Set(
|
case Capture(template, pins) =>
|
||||||
Block(
|
Capture(template, pins)
|
||||||
Position(0, 0, 0),
|
case Use(children, template, inputs, pins) =>
|
||||||
newBlock,
|
Use(children.map(f), template, inputs, pins)
|
||||||
args
|
}
|
||||||
)
|
}
|
||||||
),
|
|
||||||
Graph.empty
|
case class Capture[A](template: Exists[Template], pins: Vector[PinDefinition]) extends Fancade[A]
|
||||||
)
|
case class Use[A](children: Vector[A], template: Exists[Template], inputs: Vector[PinDefinition], pins: Vector[PinDefinition]) extends Fancade[A]
|
||||||
}
|
|
||||||
|
def flatten: Algebra[Fancade, PointerChain[Fancade]] = Algebra {
|
||||||
|
case Capture(template, pins) =>
|
||||||
|
PointerChain.single(Capture(template, pins))
|
||||||
|
case Use(children, template, inputs, pins) =>
|
||||||
|
???
|
||||||
|
}
|
||||||
|
val stack: FancadeF => PointerChain[Fancade] = scheme.cata(flatten)
|
||||||
|
def render(f: FancadeF): Level = {
|
||||||
|
val pointerChain = stack(f)
|
||||||
|
val blocks = pointerChain.map {
|
||||||
|
case (ind, fc) =>
|
||||||
|
Block(
|
||||||
|
Position(0, ind, 0),
|
||||||
|
fc.template
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Level(
|
||||||
|
blocks.toSet,
|
||||||
|
???
|
||||||
|
)
|
||||||
}
|
}
|
||||||
final case class Use(inputs: Vector[Fancade])
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
package tf.bug.fancadetagless
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
import higherkindness.droste.data._
|
||||||
|
import polymorphic._
|
||||||
import tf.bug.fancadetagless.Fanscript.{Position, ScreenSize}
|
import tf.bug.fancadetagless.Fanscript.{Position, ScreenSize}
|
||||||
|
import tf.bug.fancadescodec.Metadata.Sample
|
||||||
|
import tf.bug.fancadegraph.BlockDefinition
|
||||||
|
import tf.bug.fancadegraph.Template
|
||||||
|
|
||||||
trait Fanscript[F[_]] {
|
trait Fanscript[F[_]] {
|
||||||
|
|
||||||
|
@ -25,7 +30,7 @@ trait Fanscript[F[_]] {
|
||||||
def createObj(original: F[Obj]): F[Obj]
|
def createObj(original: F[Obj]): F[Obj]
|
||||||
def destroyObj(obj: F[Obj]): F[Obj]
|
def destroyObj(obj: F[Obj]): F[Obj]
|
||||||
|
|
||||||
def playSound(loop: Boolean, sound: Nothing)(volume: F[Float], pitch: F[Float]): F[Float]
|
def playSound(loop: Boolean, sound: Sample)(volume: F[Float], pitch: F[Float]): F[Float]
|
||||||
def stopSound(channel: F[Float]): F[Unit]
|
def stopSound(channel: F[Float]): F[Unit]
|
||||||
def volumePitch(channel: F[Float], volume: F[Float], pitch: F[Float]): F[Unit]
|
def volumePitch(channel: F[Float], volume: F[Float], pitch: F[Float]): F[Unit]
|
||||||
|
|
||||||
|
@ -70,6 +75,92 @@ trait Fanscript[F[_]] {
|
||||||
|
|
||||||
object Fanscript {
|
object Fanscript {
|
||||||
|
|
||||||
|
trait Program[R] {
|
||||||
|
def run[F[_]](implicit interp: Fanscript[F]): F[R]
|
||||||
|
}
|
||||||
|
|
||||||
|
implicit object fancade extends Fanscript[FancadeW] {
|
||||||
|
|
||||||
|
override def lift(value: Float): FancadeW[Float] =
|
||||||
|
Fix(Fancade.Capture(
|
||||||
|
Exists(Template(
|
||||||
|
BlockDefinition.NumberValue,
|
||||||
|
value
|
||||||
|
)),
|
||||||
|
Vector(BlockDefinition.NumberValue.output)
|
||||||
|
))
|
||||||
|
override def lift(value: Vector3): FancadeW[Vector3] = ???
|
||||||
|
override def lift(value: Rotation): FancadeW[Rotation] = ???
|
||||||
|
override def lift(value: Boolean): FancadeW[Boolean] = ???
|
||||||
|
|
||||||
|
override def win(stop: Boolean): FancadeW[Unit] = ???
|
||||||
|
override def lose(stop: Boolean): FancadeW[Unit] = ???
|
||||||
|
override def setScore(score: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def setCamera(position: FancadeW[Vector3], rotation: FancadeW[Rotation], distance: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def setLight(position: FancadeW[Vector3], rotation: FancadeW[Rotation]): FancadeW[Unit] = ???
|
||||||
|
override def screenSize: FancadeW[ScreenSize] = ???
|
||||||
|
override def accelerometer: FancadeW[Vector3] = ???
|
||||||
|
|
||||||
|
override def getPosition(obj: FancadeW[Obj]): FancadeW[Position] =
|
||||||
|
Fix(Fancade.Use(
|
||||||
|
Vector(obj),
|
||||||
|
Exists(Template(
|
||||||
|
BlockDefinition.GetPosition,
|
||||||
|
()
|
||||||
|
)),
|
||||||
|
Vector(BlockDefinition.GetPosition.obj),
|
||||||
|
Vector(BlockDefinition.GetPosition.position)
|
||||||
|
))
|
||||||
|
override def setPosition(obj: FancadeW[Obj], position: FancadeW[Vector3], rotation: FancadeW[Rotation]): FancadeW[Unit] = ???
|
||||||
|
override def raycast(from: FancadeW[Vector3], to: FancadeW[Vector3]): FancadeW[Raycast] = ???
|
||||||
|
override def getSize(obj: FancadeW[Obj]): FancadeW[Size] = ???
|
||||||
|
override def setVisible(obj: FancadeW[Obj], visible: FancadeW[Boolean]): FancadeW[Unit] = ???
|
||||||
|
override def createObj(original: FancadeW[Obj]): FancadeW[Obj] = ???
|
||||||
|
override def destroyObj(obj: FancadeW[Obj]): FancadeW[Obj] = ???
|
||||||
|
|
||||||
|
override def playSound(loop: Boolean, sound: Sample)(volume: FancadeW[Float], pitch: FancadeW[Float]): FancadeW[Float] = ???
|
||||||
|
override def stopSound(channel: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def volumePitch(channel: FancadeW[Float], volume: FancadeW[Float], pitch: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
|
||||||
|
override def addForce(obj: FancadeW[Obj], force: FancadeW[Vector3], applyAt: FancadeW[Vector3], torque: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def getVelocity(obj: FancadeW[Obj]): FancadeW[Velocity] = ???
|
||||||
|
override def setVelocity(obj: FancadeW[Obj], velocity: FancadeW[Vector3], spin: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def setLocked(obj: FancadeW[Obj], position: FancadeW[Vector3], rotation: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def setMass(obj: FancadeW[Obj], mass: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def setFriction(obj: FancadeW[Obj], friction: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def setBounciness(obj: FancadeW[Obj], bounciness: FancadeW[Float]): FancadeW[Unit] = ???
|
||||||
|
override def setGravity(gravity: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def addConstraint(base: FancadeW[Obj], part: FancadeW[Obj], pivot: FancadeW[Vector3]): FancadeW[Constraint] = ???
|
||||||
|
override def linearLimits(constraint: FancadeW[Constraint], lower: FancadeW[Vector3], upper: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def angularLimits(constraint: FancadeW[Constraint], lower: FancadeW[Vector3], upper: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def linearSpring(constraint: FancadeW[Constraint], stiffness: FancadeW[Vector3], damping: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def angularSpring(constraint: FancadeW[Constraint], stiffness: FancadeW[Vector3], damping: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def linearMotor(constraint: FancadeW[Constraint], speed: FancadeW[Vector3], force: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
override def angularMotor(constraint: FancadeW[Constraint], speed: FancadeW[Vector3], force: FancadeW[Vector3]): FancadeW[Unit] = ???
|
||||||
|
|
||||||
|
override def ifElse(cond: FancadeW[Boolean])(ifTrue: FancadeW[Unit])(ifFalse: FancadeW[Unit]): FancadeW[Unit] = ???
|
||||||
|
override def onPlay(onPlay: FancadeW[Unit]): FancadeW[Unit] = ???
|
||||||
|
override def onBoxArt(onBoxArt: FancadeW[Unit]): FancadeW[Unit] = ???
|
||||||
|
override def onTouch(onTouch: FancadeW[Touch] => FancadeW[Unit]): FancadeW[Unit] = ???
|
||||||
|
|
||||||
|
override def screenSizeWidth(screenSize: FancadeW[ScreenSize]): FancadeW[Float] = ???
|
||||||
|
override def screenSizeHeight(screenSize: FancadeW[ScreenSize]): FancadeW[Float] = ???
|
||||||
|
|
||||||
|
override def positionPosition(position: FancadeW[Position]): FancadeW[Vector3] = ???
|
||||||
|
override def positionRotation(position: FancadeW[Position]): FancadeW[Rotation] = ???
|
||||||
|
|
||||||
|
override def raycastHit(raycast: FancadeW[Raycast]): FancadeW[Boolean] = ???
|
||||||
|
override def raycastPosition(raycast: FancadeW[Raycast]): FancadeW[Vector3] = ???
|
||||||
|
override def raycastObj(raycast: FancadeW[Raycast]): FancadeW[Obj] = ???
|
||||||
|
|
||||||
|
override def sizeMin(size: FancadeW[Size]): FancadeW[Vector3] = ???
|
||||||
|
override def sizeMax(size: FancadeW[Size]): FancadeW[Vector3] = ???
|
||||||
|
|
||||||
|
override def velocityVelocity(velocity: FancadeW[Velocity]): FancadeW[Vector3] = ???
|
||||||
|
override def velocitySpin(velocity: FancadeW[Velocity]): FancadeW[Vector3] = ???
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
case class ScreenSize(width: Float, height: Float)
|
case class ScreenSize(width: Float, height: Float)
|
||||||
case class Position(position: Vector3, rotation: Rotation)
|
case class Position(position: Vector3, rotation: Rotation)
|
||||||
case class Raycast(hit: Boolean, position: Vector3, obj: Obj)
|
case class Raycast(hit: Boolean, position: Vector3, obj: Obj)
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package tf.bug.fancadetagless
|
||||||
|
|
||||||
|
import cats._
|
||||||
|
import cats.implicits._
|
||||||
|
|
||||||
|
case class PointerChain[F[_]](internal: Map[Int, F[Int]])(implicit functor: Functor[F]) {
|
||||||
|
|
||||||
|
def ++(other: PointerChain[F]): PointerChain[F] = {
|
||||||
|
???
|
||||||
|
}
|
||||||
|
|
||||||
|
def map[B](f: ((Int, F[Int])) => B): Vector[B] = internal.map(f).toVector
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
object PointerChain {
|
||||||
|
|
||||||
|
def empty[F[_] : Functor]: PointerChain[F] = PointerChain(Map.empty)
|
||||||
|
|
||||||
|
def single[F[_] : Functor](value: F[Nothing]): PointerChain[F] = PointerChain(Map(0 -> value.widen))
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
package tf.bug
|
package tf.bug
|
||||||
|
|
||||||
|
import higherkindness.droste.data.Fix
|
||||||
|
|
||||||
package object fancadetagless {
|
package object fancadetagless {
|
||||||
|
|
||||||
type FancadeW[A] = Fancade
|
type FancadeF = Fix[Fancade]
|
||||||
|
type FancadeW[A] = FancadeF
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,51 @@ import tf.bug.fancadegraph.BlockDefinition
|
||||||
class FancadeSuite extends munit.FunSuite {
|
class FancadeSuite extends munit.FunSuite {
|
||||||
|
|
||||||
test("A capture creates one block") {
|
test("A capture creates one block") {
|
||||||
val capture = Fancade.Capture[String](BlockDefinition.GetNumber, "hello", Vector(
|
val capture: FancadeF = Fix(Fancade.Capture[String](BlockDefinition.GetNumber, "hello", Vector(
|
||||||
BlockDefinition.GetNumber.output
|
BlockDefinition.GetNumber.output
|
||||||
|
)))
|
||||||
|
assertEquals(Fancade.render(capture).blocks.size, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Stacking 1 + 1 results in a 2-element map") {
|
||||||
|
val one: FancadeF = Fix(Fancade.Capture(BlockDefinition.NumberValue, 1.0f, Vector(
|
||||||
|
BlockDefinition.NumberValue.output
|
||||||
|
)))
|
||||||
|
val add: FancadeF = Fix(Fancade.Use(
|
||||||
|
Vector(one, one),
|
||||||
|
BlockDefinition.AddNumbers,
|
||||||
|
(),
|
||||||
|
Vector(
|
||||||
|
BlockDefinition.AddNumbers.input1,
|
||||||
|
BlockDefinition.AddNumbers.input2
|
||||||
|
),
|
||||||
|
Vector(
|
||||||
|
BlockDefinition.AddNumbers.output
|
||||||
|
)
|
||||||
|
))
|
||||||
|
val stacked = Fancade.stack(add)
|
||||||
|
assertEquals(stacked, Map(
|
||||||
|
1 -> Fancade.Capture(BlockDefinition.NumberValue, 1.0f, Vector(BlockDefinition.NumberValue.output)),
|
||||||
|
0 -> Fancade.Use(Vector(1, 1), BlockDefinition.AddNumbers, (),
|
||||||
|
Vector(
|
||||||
|
BlockDefinition.AddNumbers.input1,
|
||||||
|
BlockDefinition.AddNumbers.input2
|
||||||
|
),
|
||||||
|
Vector(BlockDefinition.AddNumbers.output)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
test("A constant creates a capture") {
|
||||||
|
val program = new Fanscript.Program[Float] {
|
||||||
|
override def run[F[_]](implicit interp: Fanscript[F]): F[Float] = interp.lift(1.0f)
|
||||||
|
}
|
||||||
|
val result = program.run[FancadeW]
|
||||||
|
assertEquals(result, Fancade.Capture(
|
||||||
|
BlockDefinition.NumberValue,
|
||||||
|
1.0f,
|
||||||
|
Vector(BlockDefinition.NumberValue.output)
|
||||||
))
|
))
|
||||||
assertEquals(capture.render.blocks.size, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue