diff --git a/cli/src/test/scala/org/bykn/bosatsu/codegen/clang/ClangGenTest.scala b/cli/src/test/scala/org/bykn/bosatsu/codegen/clang/ClangGenTest.scala index 7357a930d..6fb5ce96f 100644 --- a/cli/src/test/scala/org/bykn/bosatsu/codegen/clang/ClangGenTest.scala +++ b/cli/src/test/scala/org/bykn/bosatsu/codegen/clang/ClangGenTest.scala @@ -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 => diff --git a/cli/src/test/scala/org/bykn/bosatsu/codegen/python/PythonGenTest.scala b/cli/src/test/scala/org/bykn/bosatsu/codegen/python/PythonGenTest.scala index c56aaf018..92aa7fa6c 100644 --- a/cli/src/test/scala/org/bykn/bosatsu/codegen/python/PythonGenTest.scala +++ b/cli/src/test/scala/org/bykn/bosatsu/codegen/python/PythonGenTest.scala @@ -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) @@ -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) diff --git a/core/src/main/scala/org/bykn/bosatsu/Evaluation.scala b/core/src/main/scala/org/bykn/bosatsu/Evaluation.scala index ba7e6c631..501da9cce 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Evaluation.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Evaluation.scala @@ -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]] = diff --git a/core/src/main/scala/org/bykn/bosatsu/MatchlessFromTypedExpr.scala b/core/src/main/scala/org/bykn/bosatsu/MatchlessFromTypedExpr.scala index 6a0754812..49a53e4ee 100644 --- a/core/src/main/scala/org/bykn/bosatsu/MatchlessFromTypedExpr.scala +++ b/core/src/main/scala/org/bykn/bosatsu/MatchlessFromTypedExpr.scala @@ -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, _)) } } diff --git a/core/src/main/scala/org/bykn/bosatsu/MatchlessToValue.scala b/core/src/main/scala/org/bykn/bosatsu/MatchlessToValue.scala index 127bf224e..5d58d1dd7 100644 --- a/core/src/main/scala/org/bykn/bosatsu/MatchlessToValue.scala +++ b/core/src/main/scala/org/bykn/bosatsu/MatchlessToValue.scala @@ -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) @@ -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) @@ -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 @@ -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) @@ -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 diff --git a/core/src/main/scala/org/bykn/bosatsu/codegen/clang/ClangTranspiler.scala b/core/src/main/scala/org/bykn/bosatsu/codegen/clang/ClangTranspiler.scala index c45a5b400..56d3f7fba 100644 --- a/core/src/main/scala/org/bykn/bosatsu/codegen/clang/ClangTranspiler.scala +++ b/core/src/main/scala/org/bykn/bosatsu/codegen/clang/ClangTranspiler.scala @@ -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] @@ -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] diff --git a/core/src/main/scala/org/bykn/bosatsu/codegen/python/PythonTranspiler.scala b/core/src/main/scala/org/bykn/bosatsu/codegen/python/PythonTranspiler.scala index 02f1e0273..dd43c109f 100644 --- a/core/src/main/scala/org/bykn/bosatsu/codegen/python/PythonTranspiler.scala +++ b/core/src/main/scala/org/bykn/bosatsu/codegen/python/PythonTranspiler.scala @@ -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 = diff --git a/core/src/main/scala/org/bykn/bosatsu/library/DecodedLibrary.scala b/core/src/main/scala/org/bykn/bosatsu/library/DecodedLibrary.scala new file mode 100644 index 000000000..3e399bbc4 --- /dev/null +++ b/core/src/main/scala/org/bykn/bosatsu/library/DecodedLibrary.scala @@ -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)) + ) + } +} diff --git a/core/src/main/scala/org/bykn/bosatsu/library/LibConfig.scala b/core/src/main/scala/org/bykn/bosatsu/library/LibConfig.scala index bbc68ba87..ff742309e 100644 --- a/core/src/main/scala/org/bykn/bosatsu/library/LibConfig.scala +++ b/core/src/main/scala/org/bykn/bosatsu/library/LibConfig.scala @@ -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} @@ -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)) - ) - } -} diff --git a/core/src/test/scala/org/bykn/bosatsu/TestUtils.scala b/core/src/test/scala/org/bykn/bosatsu/TestUtils.scala index f4a78d4b5..24e30da0d 100644 --- a/core/src/test/scala/org/bykn/bosatsu/TestUtils.scala +++ b/core/src/test/scala/org/bykn/bosatsu/TestUtils.scala @@ -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) }