From 2967d24bd7150456b6cb49ff28d3406eca162ad0 Mon Sep 17 00:00:00 2001 From: Oscar Boykin Date: Fri, 13 Dec 2024 09:26:01 -1000 Subject: [PATCH] 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[