Skip to content

Commit

Permalink
Move DecodedLibrary to its own file (#1373)
Browse files Browse the repository at this point in the history
* Move DecodedLibrary to its own file

* fix tests
  • Loading branch information
johnynek authored Feb 3, 2025
1 parent 4d4de44 commit 1647008
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ClangGenTest extends munit.FunSuite {
println(exCode.render(80))
sys.error("stop")
*/
val matchlessMap = MatchlessFromTypedExpr.compile(pm)
val matchlessMap = MatchlessFromTypedExpr.compile((), pm)
val topoSort = pm.topoSort.toSuccess.get
val sortedEnv =
cats.Functor[Vector].compose[NonEmptyList].map(topoSort) { pn =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class PythonGenTest extends AnyFunSuite {
val natPathBosatu: String = "test_workspace/Nat.bosatsu"

val bosatsuPM = compileFile(natPathBosatu)
val matchless = MatchlessFromTypedExpr.compile(bosatsuPM)
val matchless = MatchlessFromTypedExpr.compile((), bosatsuPM)

val packMap =
PythonGen.renderAll(matchless, Map.empty, Map.empty, Map.empty)
Expand Down Expand Up @@ -148,7 +148,7 @@ class PythonGenTest extends AnyFunSuite {
val intr = new PythonInterpreter()

val bosatsuPM = compileFile(path)
val matchless = MatchlessFromTypedExpr.compile(bosatsuPM)
val matchless = MatchlessFromTypedExpr.compile((), bosatsuPM)

val packMap =
PythonGen.renderAll(matchless, Map.empty, Map.empty, Map.empty)
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/org/bykn/bosatsu/Evaluation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ case class Evaluation[T](pm: PackageMap.Typed[T], externals: Externals) {
.run
.value

val evalFn: (PackageName, Identifier) => Eval[Value] = { (p, i) =>
val evalFn: (Unit, PackageName, Identifier) => Eval[Value] = { (_, p, i) =>
if (p == thisPack) Eval.defer(evaluate(p)(i))
else evaluate(p)(i)
}

type F[A] = List[(Bindable, A)]
val ffunc = cats.Functor[List].compose(cats.Functor[(Bindable, *)])
MatchlessToValue.traverse[F](exprs)(evalFn)(ffunc)
MatchlessToValue.traverse[F, Unit](exprs)(evalFn)(ffunc)
}

private def evaluate(packName: PackageName): Map[Identifier, Eval[Value]] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,29 @@ import cats.implicits._
object MatchlessFromTypedExpr {
type Compiled[+A] = Map[PackageName, List[(Bindable, Matchless.Expr[A])]]
// compile a set of packages given a set of external remappings
def compile[A](
def compile[K, A](
from: K,
pm: PackageMap.Typed[A]
)(implicit ec: Par.EC): Compiled[Unit] = {
)(implicit ec: Par.EC): Compiled[K] = {

val gdr = pm.getDataRepr

// on JS Par.F[A] is actually Id[A], so we need to hold hands a bit

val allItemsList = pm.toMap.toList
.traverse[Par.F, (PackageName, List[(Bindable, Matchless.Expr[Unit])])] {
.traverse[Par.F, (PackageName, List[(Bindable, Matchless.Expr[K])])] {
case (pname, pack) =>
val lets = pack.lets

Par.start {
val exprs: List[(Bindable, Matchless.Expr[Unit])] =
val exprs: List[(Bindable, Matchless.Expr[K])] =
rankn.RefSpace.allocCounter
.flatMap { c =>
lets
.traverse { case (name, rec, te) =>
// TODO: add from so we can resolve packages correctly
Matchless
.fromLet((), name, rec, te, gdr, c)
.fromLet(from, name, rec, te, gdr, c)
.map((name, _))
}
}
Expand Down
81 changes: 41 additions & 40 deletions core/src/main/scala/org/bykn/bosatsu/MatchlessToValue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ object MatchlessToValue {
import Matchless._

// reuse some cache structures across a number of calls
def traverse[F[_]: Functor](
me: F[Expr[Unit]]
)(resolve: (PackageName, Identifier) => Eval[Value]): F[Eval[Value]] = {
def traverse[F[_]: Functor, A](
me: F[Expr[A]]
)(resolve: (A, PackageName, Identifier) => Eval[Value]): F[Eval[Value]] = {
val env = new Impl.Env(resolve)
val fns = Functor[F].map(me) { expr =>
env.loop(expr)
Expand All @@ -28,41 +28,42 @@ object MatchlessToValue {
}
}

private[this] val zeroNat: Value = ExternalValue(BigInteger.ZERO)
private[this] val succNat: Value = {
def inc(v: Value): Value = {
val bi = v.asExternal.toAny.asInstanceOf[BigInteger]
ExternalValue(bi.add(BigInteger.ONE))
}
FnValue { case NonEmptyList(a, _) => inc(a) }
}
private object Impl {

def makeCons(c: ConsExpr): Value =
c match {
case MakeEnum(variant, arity, _) =>
if (arity == 0) SumValue(variant, UnitValue)
else if (arity == 1) {
FnValue { case NonEmptyList(v, _) =>
SumValue(variant, ProductValue.single(v))
}
} else
// arity > 1
FnValue { args =>
val prod = ProductValue.fromList(args.toList)
SumValue(variant, prod)
}
case MakeStruct(arity) =>
if (arity == 0) UnitValue
else if (arity == 1) FnValue.identity
else
FnValue { args =>
ProductValue.fromList(args.toList)
}
case ZeroNat => zeroNat
case SuccNat => succNat
private[this] val zeroNat: Value = ExternalValue(BigInteger.ZERO)
private[this] val succNat: Value = {
def inc(v: Value): Value = {
val bi = v.asExternal.toAny.asInstanceOf[BigInteger]
ExternalValue(bi.add(BigInteger.ONE))
}
FnValue { case NonEmptyList(a, _) => inc(a) }
}

private object Impl {
def makeCons(c: ConsExpr): Value =
c match {
case MakeEnum(variant, arity, _) =>
if (arity == 0) SumValue(variant, UnitValue)
else if (arity == 1) {
FnValue { case NonEmptyList(v, _) =>
SumValue(variant, ProductValue.single(v))
}
} else
// arity > 1
FnValue { args =>
val prod = ProductValue.fromList(args.toList)
SumValue(variant, prod)
}
case MakeStruct(arity) =>
if (arity == 0) UnitValue
else if (arity == 1) FnValue.identity
else
FnValue { args =>
ProductValue.fromList(args.toList)
}
case ZeroNat => zeroNat
case SuccNat => succNat
}

case object Uninitialized
val uninit: Value = ExternalValue(Uninitialized)

Expand Down Expand Up @@ -206,9 +207,9 @@ object MatchlessToValue {
}
}

class Env(resolve: (PackageName, Identifier) => Eval[Value]) {
class Env[F](resolve: (F, PackageName, Identifier) => Eval[Value]) {
// evaluating boolExpr can mutate an existing value in muts
private def boolExpr(ix: BoolExpr[Unit]): Scoped[Boolean] =
private def boolExpr(ix: BoolExpr[F]): Scoped[Boolean] =
ix match {
case EqualsLit(expr, lit) =>
val litAny = lit.unboxToAny
Expand Down Expand Up @@ -300,7 +301,7 @@ object MatchlessToValue {
}

// the locals can be recusive, so we box into Eval for laziness
def loop(me: Expr[Unit]): Scoped[Value] =
def loop(me: Expr[F]): Scoped[Value] =
me match {
case Lambda(Nil, None, args, res) =>
val resFn = loop(res)
Expand Down Expand Up @@ -360,8 +361,8 @@ object MatchlessToValue {
}
scope.muts(result.ident).get()
}
case Global(_, p, n) =>
val res = resolve(p, n)
case Global(f, p, n) =>
val res = resolve(f, p, n)

// this has to be lazy because it could be
// in this package, which isn't complete yet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ case object ClangTranspiler extends Transpiler {
validMain(t) match {
case Right(mainRun) =>
val pm1 = args.emit(pm, Set((p, b)))
val matchlessMap = MatchlessFromTypedExpr.compile(pm1)
val matchlessMap = MatchlessFromTypedExpr.compile((), pm1)
val sortedEnv = cats
.Functor[Vector]
.compose[NonEmptyList]
Expand Down Expand Up @@ -344,7 +344,7 @@ case object ClangTranspiler extends Transpiler {
)
case nonEmpty =>
val pm1 = args.emit(pm, nonEmpty.toSet)
val matchlessMap = MatchlessFromTypedExpr.compile(pm1)
val matchlessMap = MatchlessFromTypedExpr.compile((), pm1)
val sortedEnv = cats
.Functor[Vector]
.compose[NonEmptyList]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ case object PythonTranspiler extends Transpiler {

import args.platformIO._

val cmp = MatchlessFromTypedExpr.compile(pm)
val cmp = MatchlessFromTypedExpr.compile((), pm)
args.read.flatMap { case (externals, evaluators) =>
moduleIOMonad.fromTry(Try {
val parsedExt =
Expand Down
40 changes: 40 additions & 0 deletions core/src/main/scala/org/bykn/bosatsu/library/DecodedLibrary.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package org.bykn.bosatsu.library

import _root_.bosatsu.{TypedAst => proto}
import cats.MonadError
import cats.syntax.all._
import org.bykn.bosatsu.hashing.{Hashed, HashValue}
import org.bykn.bosatsu.{Package, PackageName, PackageMap, ProtoConverter}
import scala.collection.immutable.{SortedMap, SortedSet}

case class DecodedLibrary[A](
hashValue: HashValue[A],
protoLib: proto.Library,
interfaces: List[Package.Interface],
implementations: PackageMap.Typed[Unit]
) {
lazy val publicPackageNames: SortedSet[PackageName] =
interfaces.iterator.map(_.name).to(SortedSet)
}

object DecodedLibrary {
def decode[F[_], A](
protoLib: Hashed[A, proto.Library]
)(implicit F: MonadError[F, Throwable]): F[DecodedLibrary[A]] =
F.fromTry(
ProtoConverter
.packagesFromProto(
protoLib.arg.exportedIfaces,
protoLib.arg.internalPackages
)
).map { case (ifs, impls) =>
// TODO: should verify somewhere that all the package names are distinct, but since this is presumed to be
// a good library maybe that's a waste
DecodedLibrary[A](
protoLib.hash,
protoLib.arg,
ifs,
PackageMap(impls.iterator.map(pack => (pack.name, pack)).to(SortedMap))
)
}
}
46 changes: 3 additions & 43 deletions core/src/main/scala/org/bykn/bosatsu/library/LibConfig.scala
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
package org.bykn.bosatsu.library

import _root_.bosatsu.{TypedAst => proto}
import cats.MonadError
import cats.data.{NonEmptyChain, NonEmptyList, Validated, ValidatedNec}
import cats.syntax.all._
import java.util.regex.Pattern
import java.util.regex.PatternSyntaxException
import org.bykn.bosatsu.{
Json,
Package,
PackageName,
PackageMap,
ProtoConverter,
Kind
}
import org.bykn.bosatsu.{Json, Kind, Package, PackageName, ProtoConverter}
import org.bykn.bosatsu.tool.CliException
import org.bykn.bosatsu.rankn.TypeEnv
import org.bykn.bosatsu.hashing.{Hashed, HashValue, Algo}
import org.bykn.bosatsu.hashing.{HashValue, Algo}
import org.typelevel.paiges.{Doc, Document}
import scala.util.{Failure, Success, Try}
import scala.collection.immutable.{SortedMap, SortedSet}
import scala.collection.immutable.SortedMap

import LibConfig.{Error, LibMethods, LibHistoryMethods, ValidationResult}

Expand Down Expand Up @@ -996,35 +988,3 @@ object LibConfig {
)
}
}

case class DecodedLibrary[A](
hashValue: HashValue[A],
protoLib: proto.Library,
interfaces: List[Package.Interface],
implementations: PackageMap.Typed[Unit]
) {
lazy val publicPackageNames: SortedSet[PackageName] =
interfaces.iterator.map(_.name).to(SortedSet)
}

object DecodedLibrary {
def decode[F[_], A](
protoLib: Hashed[A, proto.Library]
)(implicit F: MonadError[F, Throwable]): F[DecodedLibrary[A]] =
F.fromTry(
ProtoConverter
.packagesFromProto(
protoLib.arg.exportedIfaces,
protoLib.arg.internalPackages
)
).map { case (ifs, impls) =>
// TODO: should verify somewhere that all the package names are distinct, but since this is presumed to be
// a good library maybe that's a waste
DecodedLibrary[A](
protoLib.hash,
protoLib.arg,
ifs,
PackageMap(impls.iterator.map(pack => (pack.name, pack)).to(SortedMap))
)
}
}
2 changes: 1 addition & 1 deletion core/src/test/scala/org/bykn/bosatsu/TestUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ object TestUtils {
val srv = Par.newService()
try {
implicit val ec = Par.ecFromService(srv)
val comp = MatchlessFromTypedExpr.compile(pm)
val comp = MatchlessFromTypedExpr.compile((), pm)
fn(comp)
} finally Par.shutdownService(srv)
}
Expand Down

0 comments on commit 1647008

Please sign in to comment.