From 2967d24bd7150456b6cb49ff28d3406eca162ad0 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 13 Dec 2024 09:26:01 -1000 Subject: [PATCH 1/4] refactor Package and PackageMap some --- .../main/scala/org/bykn/bosatsu/Package.scala | 53 ++++++++++++ .../scala/org/bykn/bosatsu/PackageMap.scala | 80 ++++--------------- 2 files changed, 70 insertions(+), 63 deletions(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index 8abad1e4a..4d4a57a33 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -49,6 +49,11 @@ final case class Package[A, B, C, +D]( newImports: List[Import[A1, B1]] ): Package[A1, B1, C, D] = Package(name, newImports, exports, program) + + def getExport[T](i: ImportedName[T]): Option[NonEmptyList[ExportedName[C]]] = { + val iname = i.originalName + NonEmptyList.fromList(exports.filter(_.name == iname)) + } } object Package { @@ -535,6 +540,54 @@ object Package { val prog1 = prog.copy(lets = prog.lets.filter { case (b, _, _) => fn(b) }) pack.copy(program = (prog1, importMap)) } + + def getImport[B]( + inside: PackageName, + i: ImportedName[B] + ): Either[PackageError, ImportedName[NonEmptyList[Referant[Kind.Arg]]]] = { + pack.getExport(i) match { + case Some(exps) => + val bs = exps.map(_.tag) + Right(i.map(_ => bs)) + case None => + val exMap = pack.exports.groupByNel(_.name) + Left( + PackageError.UnknownImportName( + inside, + pack.name, + pack.program._1.lets.iterator.map { case (n, _, _) => + (n: Identifier, ()) + }.toMap, + i, + exMap.iterator.flatMap(_._2.toList).toList + ) + ) + } + } + } + + implicit class IfaceMethods(private val iface: Interface) extends AnyVal { + def getImportIface[A]( + inside: PackageName, + i: ImportedName[A] + ): Either[PackageError, ImportedName[NonEmptyList[Referant[Kind.Arg]]]] = { + iface.getExport(i) match { + case Some(exps) => + val bs = exps.map(_.tag) + Right(i.map(_ => bs)) + case None => + val exMap = iface.exports.groupByNel(_.name) + Left( + PackageError.UnknownImportFromInterface( + inside, + iface.name, + iface.exports.map(_.name), + i, + exMap.iterator.flatMap(_._2.toList).toList + ) + ) + } + } } def orderByName[A, B, C, D]: Order[Package[A, B, C, D]] = diff --git a/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala b/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala index d5d572073..db54f9549 100644 --- a/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala +++ b/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala @@ -145,8 +145,8 @@ object PackageMap { type Inferred = Typed[Declaration] - /** This builds a DAG of actual packages where names have been replaced by the - * fully resolved packages + /** This builds a DAG of actual packages where on Import the PackageName have been replaced by the + * Either a Package.Interface (which gives exports only) or this same recursive structure. */ def resolvePackages[A, B, C]( map: PackageMap[PackageName, A, B, C], @@ -328,7 +328,7 @@ object PackageMap { // we know all the package names are unique here def foldMap( - m: Map[PackageName, (A, Package.Parsed)] + m: SortedMap[PackageName, (A, Package.Parsed)] ): (List[PackageError], PackageMap.ParsedImp) = { val initPm = PackageMap .empty[ @@ -338,7 +338,8 @@ object PackageMap { (List[Statement], ImportMap[PackageName, Unit]) ] - m.iterator.foldLeft((List.empty[PackageError], initPm)) { + // since the map is sorted, this order is deteriministic + m.foldLeft((List.empty[PackageError], initPm)) { case ((errs, pm), (_, (_, pack))) => val (lerrs, pp) = toProg(pack) (lerrs.toList ::: errs, pm + pp) @@ -350,14 +351,14 @@ object PackageMap { // combine the import errors now: val check: Ior[NonEmptyList[PackageError], Unit] = errs match { - case Nil => - Ior.right(()) + case Nil => Ior.right(()) case h :: tail => Ior.left(NonEmptyList(h, tail)) } // keep all the errors val nuEr: Ior[NonEmptyList[PackageError], Unit] = NonEmptyMap.fromMap(nonUnique) match { + case None => Ior.right(()) case Some(nenu) => val paths = nenu.map { case ((a, _), rest) => (a.show, rest.map(_._1.show)) @@ -367,8 +368,6 @@ object PackageMap { PackageError.DuplicatedPackageError(paths) ) ) - case None => - Ior.right(()) } (nuEr, check, res.toIor).parMapN((_, _, r) => r) @@ -418,54 +417,6 @@ object PackageMap { (nameToRes(p), i) } - def getImport[A, B]( - packF: Package.Inferred, - exMap: Map[Identifier, NonEmptyList[ExportedName[A]]], - i: ImportedName[B] - ): Ior[NonEmptyList[PackageError], ImportedName[NonEmptyList[A]]] = - exMap.get(i.originalName) match { - case None => - Ior.left( - NonEmptyList.one( - PackageError.UnknownImportName( - nm, - packF.name, - packF.program._1.lets.iterator.map { case (n, _, _) => - (n: Identifier, ()) - }.toMap, - i, - exMap.iterator.flatMap(_._2.toList).toList - ) - ) - ) - case Some(exps) => - val bs = exps.map(_.tag) - Ior.right(i.map(_ => bs)) - } - - def getImportIface[A, B]( - packF: Package.Interface, - exMap: Map[Identifier, NonEmptyList[ExportedName[A]]], - i: ImportedName[B] - ): Ior[NonEmptyList[PackageError], ImportedName[NonEmptyList[A]]] = - exMap.get(i.originalName) match { - case None => - Ior.left( - NonEmptyList.one( - PackageError.UnknownImportFromInterface( - nm, - packF.name, - packF.exports.map(_.name), - i, - exMap.iterator.flatMap(_._2.toList).toList - ) - ) - ) - case Some(exps) => - val bs = exps.map(_.tag) - Ior.right(i.map(_ => bs)) - } - /* * This resolves imports from PackageNames into fully typed Packages * @@ -475,6 +426,9 @@ object PackageMap { */ type IName = NonEmptyList[Referant[Kind.Arg]] + def resFromEither[A, B](either: Either[A, B]): IorT[F, NonEmptyList[A], B] = + IorT.fromEither(either.left.map(NonEmptyList.one(_))) + def stepImport( fixpack: Package.Resolved, item: ImportedName[Unit] @@ -487,21 +441,21 @@ object PackageMap { IorT(recurse(p)) .flatMap { case (_, packF) => val packInterface = Package.interfaceOf(packF) - val exMap = packF.exports.groupByNel(_.name) - val ior = getImport(packF, exMap, item) + val either = packF.getImport(nm, item) .map((packInterface, _)) - IorT.fromIor(ior) + + resFromEither(either) } case Left(iface) => /* * this import is already an interface, we can stop here */ - val exMap = iface.exports.groupByNel(_.name) // this is very fast and does not need to be done in a thread - val ior = - getImportIface(iface, exMap, item) + val e = + iface.getImportIface(nm, item) .map((iface, _)) - IorT.fromIor(ior) + + resFromEither(e) } val inferImports: FutVal[ From 14949ae3d99e14c9f5807e58b6683d7e1cc97487 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 13 Dec 2024 09:39:50 -1000 Subject: [PATCH 2/4] simplify --- core/src/main/scala/org/bykn/bosatsu/Package.scala | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index 4d4a57a33..b4e7a01e5 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -550,7 +550,6 @@ object Package { val bs = exps.map(_.tag) Right(i.map(_ => bs)) case None => - val exMap = pack.exports.groupByNel(_.name) Left( PackageError.UnknownImportName( inside, @@ -559,7 +558,7 @@ object Package { (n: Identifier, ()) }.toMap, i, - exMap.iterator.flatMap(_._2.toList).toList + pack.exports ) ) } @@ -576,14 +575,13 @@ object Package { val bs = exps.map(_.tag) Right(i.map(_ => bs)) case None => - val exMap = iface.exports.groupByNel(_.name) Left( PackageError.UnknownImportFromInterface( inside, iface.name, iface.exports.map(_.name), i, - exMap.iterator.flatMap(_._2.toList).toList + iface.exports ) ) } From cb45e721c3b943672a17226641323a83550cfb94 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 13 Dec 2024 10:23:50 -1000 Subject: [PATCH 3/4] move more code to Package --- .../main/scala/org/bykn/bosatsu/Package.scala | 33 ++++++++++++- .../scala/org/bykn/bosatsu/PackageMap.scala | 46 +++++-------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index b4e7a01e5..a5b9bcf0e 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -1,8 +1,8 @@ package org.bykn.bosatsu -import cats.{Functor, Order, Parallel} +import cats.{Functor, Order, Parallel, Applicative} import cats.data.{Ior, ValidatedNel, Validated, NonEmptyList} -import cats.implicits._ +import cats.syntax.all._ import cats.parse.{Parser0 => P0, Parser => P} import org.typelevel.paiges.{Doc, Document} import scala.util.hashing.MurmurHash3 @@ -69,6 +69,9 @@ object Package { type Parsed = Package[PackageName, Unit, Unit, List[Statement]] type Resolved = FixPackage[Unit, Unit, (List[Statement], ImportMap[PackageName, Unit])] + type ResolvedPackage = + Package[Resolved, Unit, Unit, (List[Statement], ImportMap[PackageName, Unit])] + type TypedProgram[T] = ( Program[TypeEnv[Kind.Arg], TypedExpr[T], Any], ImportMap[Interface, NonEmptyList[Referant[Kind.Arg]]] @@ -588,6 +591,32 @@ object Package { } } + implicit class ResolvedMedthods(private val resolved: Resolved) extends AnyVal { + def importName[F[_], A]( + fromPackage: PackageName, + item: ImportedName[Unit] + )(recurse: ResolvedPackage => F[Typed[A]])(implicit F: Applicative[F]): F[Either[PackageError, (Package.Interface, ImportedName[NonEmptyList[Referant[Kind.Arg]]])]] = + Package.unfix(resolved) match { + case Right(p) => + /* + * Here we have a source we need to fully resolve + */ + recurse(p) + .map { packF => + val packInterface = Package.interfaceOf(packF) + packF.getImport(fromPackage, item) + .map((packInterface, _)) + } + case Left(iface) => + /* + * this import is already an interface, we can stop here + */ + // this is very fast and does not need to be done in a thread + F.pure(iface.getImportIface(fromPackage, item) + .map((iface, _))) + } + } + def orderByName[A, B, C, D]: Order[Package[A, B, C, D]] = Order.by[Package[A, B, C, D], PackageName](_.name) } diff --git a/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala b/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala index db54f9549..fbd7781d6 100644 --- a/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala +++ b/core/src/main/scala/org/bykn/bosatsu/PackageMap.scala @@ -424,44 +424,20 @@ object PackageMap { * type can have the same name as a constructor. After this step, each * distinct object has its own entry in the list */ - type IName = NonEmptyList[Referant[Kind.Arg]] - - def resFromEither[A, B](either: Either[A, B]): IorT[F, NonEmptyList[A], B] = - IorT.fromEither(either.left.map(NonEmptyList.one(_))) - - def stepImport( - fixpack: Package.Resolved, - item: ImportedName[Unit] - ): FutVal[(Package.Interface, ImportedName[IName])] = - Package.unfix(fixpack) match { - case Right(p) => - /* - * Here we have a source we need to fully resolve - */ - IorT(recurse(p)) - .flatMap { case (_, packF) => - val packInterface = Package.interfaceOf(packF) - val either = packF.getImport(nm, item) - .map((packInterface, _)) - - resFromEither(either) - } - case Left(iface) => - /* - * this import is already an interface, we can stop here - */ - // this is very fast and does not need to be done in a thread - val e = - iface.getImportIface(nm, item) - .map((iface, _)) - - resFromEither(e) - } val inferImports: FutVal[ ImportMap[Package.Interface, NonEmptyList[Referant[Kind.Arg]]] - ] = - resolvedImports.parTraverse(stepImport(_, _)) + ] = { + // here we just need the interface, not the TypeEnv + val rec1 = recurse.andThen { res => IorT(res).map(_._2) } + + resolvedImports.parTraverse { (fixpack: Package.Resolved, item: ImportedName[Unit]) => + fixpack.importName(nm, item)(rec1(_)) + .flatMap { either => + IorT.fromEither(either.left.map(NonEmptyList.one(_))) + } + } + } val inferBody = inferImports From f89f3ad2aebe60030d018e28b26a64d7737421e5 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 13 Dec 2024 10:25:31 -1000 Subject: [PATCH 4/4] fix typo in name --- core/src/main/scala/org/bykn/bosatsu/Package.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/scala/org/bykn/bosatsu/Package.scala b/core/src/main/scala/org/bykn/bosatsu/Package.scala index a5b9bcf0e..104e50316 100644 --- a/core/src/main/scala/org/bykn/bosatsu/Package.scala +++ b/core/src/main/scala/org/bykn/bosatsu/Package.scala @@ -591,7 +591,7 @@ object Package { } } - implicit class ResolvedMedthods(private val resolved: Resolved) extends AnyVal { + implicit class ResolvedMethods(private val resolved: Resolved) extends AnyVal { def importName[F[_], A]( fromPackage: PackageName, item: ImportedName[Unit]