Skip to content

Commit

Permalink
LF: add context in LookupError
Browse files Browse the repository at this point in the history
This is part of #9974.

CHANGELOG_BEGIN
CHANGELOG_END
  • Loading branch information
remyhaemmerle-da committed Jul 19, 2021
1 parent 159728d commit 39eb5d3
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,9 @@ object Error {
}

private[engine] object MissingPackage {
def apply(pkgId: Ref.PackageId): Lookup =
Lookup(language.LookupError.Package(pkgId))
def unapply(error: Lookup): Option[Ref.PackageId] =
error.lookupError match {
case language.LookupError.Package(packageId) => Some(packageId)
case language.LookupError(language.Reference.Package(packageId), _) => Some(packageId)
case _ => None
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class ValueEnricher(engine: Engine) {

private[this] def handleLookup[X](lookup: => Either[LookupError, X]) = lookup match {
case Right(value) => ResultDone(value)
case Left(LookupError.Package(pkgId)) =>
case Left(LookupError.MissingPackage(pkgId)) =>
engine
.loadPackages(List(pkgId))
.flatMap(_ =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private[engine] final class Preprocessor(compiledPackages: MutableCompiledPackag
tyConAlreadySeen0 + tyCon,
tmplsAlreadySeen0,
)
case Left(LookupError.Package(pkgId)) =>
case Left(LookupError.MissingPackage(pkgId)) =>
pullPackage(pkgId)
case Left(e) =>
ResultError(Error.Preprocessing.Lookup(e))
Expand All @@ -107,7 +107,7 @@ private[engine] final class Preprocessor(compiledPackages: MutableCompiledPackag
if (tyConAlreadySeen0(tmplId)) typs0 else Ast.TTyCon(tmplId) :: typs0
val typs2 = template.key.fold(typs1)(_.typ :: typs1)
go(typs2, tmplsToProcess, tyConAlreadySeen0, tmplsAlreadySeen0)
case Left(LookupError.Package(pkgId)) =>
case Left(LookupError.MissingPackage(pkgId)) =>
pullPackage(pkgId)
case Left(error) =>
ResultError(Error.Preprocessing.Lookup(error))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,9 @@ class EngineTest
val res = preprocessor
.preprocessCommands(ImmArray(command))
.consume(lookupContract, lookupPackage, lookupKey)
inside(res) { case Left(Error.Preprocessing(Error.Preprocessing.Lookup(error))) =>
error shouldBe a[language.LookupError.TemplateKey]
inside(res) {
case Left(Error.Preprocessing(Error.Preprocessing.Lookup(language.LookupError(ref, _)))) =>
ref shouldBe a[language.Reference.TemplateKey]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ private[lf] final class Compiler(
case Compiler.NoPackageValidation =>
case Compiler.FullPackageValidation =>
Validation.checkPackage(interface, pkgId, pkg).left.foreach {
case EUnknownDefinition(_, LookupError.Package(pkgId_)) =>
case EUnknownDefinition(_, LookupError.MissingPackage(pkgId_)) =>
logger.trace(s"compilePackage: Missing $pkgId_, requesting it...")
throw PackageNotFound(pkgId_)
case e =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,123 +11,225 @@ private[lf] class Interface(signatures: PartialFunction[PackageId, PackageSignat

import Interface._

private[this] def lookupPackage(
pkgId: PackageId,
context: => Reference,
): Either[LookupError, PackageSignature] =
signatures.lift(pkgId).toRight(LookupError(Reference.Package(pkgId), context))

def lookupPackage(pkgId: PackageId): Either[LookupError, PackageSignature] =
signatures.lift(pkgId).toRight(LookupError.Package(pkgId))
lookupPackage(pkgId, Reference.Package(pkgId))

def lookupModule(
private[this] def lookupModule(
pkgId: PackageId,
modName: ModuleName,
context: => Reference,
): Either[LookupError, ModuleSignature] =
lookupPackage(pkgId).flatMap(_.modules.get(modName).toRight(LookupError.Module(pkgId, modName)))
lookupPackage(pkgId, context).flatMap(
_.modules.get(modName).toRight(LookupError(Reference.Module(pkgId, modName), context))
)

def lookupDefinition(name: TypeConName): Either[LookupError, DefinitionSignature] =
lookupModule(name.packageId, name.qualifiedName.module).flatMap(
_.definitions.get(name.qualifiedName.name).toRight(LookupError.Definition(name))
def lookupModule(pkgId: PackageId, modName: ModuleName): Either[LookupError, ModuleSignature] =
lookupModule(pkgId, modName, Reference.Module(pkgId, modName))

private[this] def lookupDefinition(
name: TypeConName,
context: => Reference,
): Either[LookupError, DefinitionSignature] =
lookupModule(name.packageId, name.qualifiedName.module, context).flatMap(
_.definitions
.get(name.qualifiedName.name)
.toRight(LookupError(Reference.Definition(name), context))
)

def lookupDefinition(name: TypeConName): Either[LookupError, DefinitionSignature] =
lookupDefinition(name, Reference.Definition(name))

// Throws a Definition LookupError, if name does not maps to a Definition.
// Throws a TypeSyn LookupError, if name map to a Definition which is not a DTypeSyn.
def lookupTypeSyn(name: TypeSynName): Either[LookupError, DTypeSyn] =
lookupDefinition(name).flatMap {
private[this] def lookupTypeSyn(
name: TypeSynName,
context: => Reference,
): Either[LookupError, DTypeSyn] =
lookupDefinition(name, context).flatMap {
case typeSyn: DTypeSyn => Right(typeSyn)
case _ => Left(LookupError.TypeSyn(name))
case _ => Left(LookupError(Reference.TypeSyn(name), context))
}

def lookupTypeSyn(name: TypeSynName): Either[LookupError, DTypeSyn] =
lookupTypeSyn(name, Reference.TypeSyn(name))

// Throws a Definition LookupError, if name does not maps to a Definition.
// Throws a TypeSyn LookupError, if name map to a Definition which is not a DDataType.
def lookupDataType(name: TypeConName): Either[LookupError, DDataType] =
lookupDefinition(name).flatMap {
private[this] def lookupDataType(
name: TypeConName,
context: => Reference,
): Either[LookupError, DDataType] =
lookupDefinition(name, context).flatMap {
case dataType: DDataType => Right(dataType)
case _ => Left(LookupError.DataType(name))
case _ => Left(LookupError(Reference.DataType(name), context))
}

def lookupDataRecord(
tyCon: TypeConName
def lookupDataType(name: TypeConName): Either[LookupError, DDataType] =
lookupDataType(name, Reference.DataType(name))

private[this] def lookupDataRecord(
tyCon: TypeConName,
context: => Reference,
): Either[LookupError, DataRecordInfo] =
lookupDataType(tyCon).flatMap { dataType =>
lookupDataType(tyCon, context).flatMap { dataType =>
dataType.cons match {
case record: DataRecord => Right(DataRecordInfo(dataType, record))
case _ => Left(LookupError.DataRecord(tyCon))
case _ => Left(LookupError(Reference.DataRecord(tyCon), context))
}
}

def lookupRecordFieldInfo(
def lookupDataRecord(tyCon: TypeConName): Either[LookupError, DataRecordInfo] =
lookupDataRecord(tyCon, Reference.DataRecord(tyCon))

private[this] def lookupRecordFieldInfo(
tyCon: TypeConName,
fieldName: FieldName,
context: => Reference,
): Either[LookupError, RecordFieldInfo] =
lookupDataRecord(tyCon).flatMap { recordDataInfo =>
lookupDataRecord(tyCon, context).flatMap { recordDataInfo =>
recordDataInfo.dataRecord.fieldInfo.get(fieldName) match {
case Some((typ, index)) => Right(RecordFieldInfo(recordDataInfo, typ, index))
case None => Left(LookupError.DataRecordField(tyCon, fieldName))
case None => Left(LookupError(Reference.DataRecordField(tyCon, fieldName), context))
}
}

def lookupDataVariant(
tyCon: TypeConName
def lookupRecordFieldInfo(
tyCon: TypeConName,
fieldName: FieldName,
): Either[LookupError, RecordFieldInfo] =
lookupRecordFieldInfo(tyCon, fieldName, Reference.DataRecordField(tyCon, fieldName))

private[this] def lookupDataVariant(
tyCon: TypeConName,
context: => Reference,
): Either[LookupError, DataVariantInfo] =
lookupDataType(tyCon).flatMap(dataType =>
lookupDataType(tyCon, context).flatMap(dataType =>
dataType.cons match {
case cons: DataVariant => Right(DataVariantInfo(dataType, cons))
case _ => Left(LookupError.DataVariant(tyCon))
case _ => Left(LookupError(Reference.DataVariant(tyCon), context))
}
)

def lookupVariantConstructor(
def lookupDataVariant(tyCon: TypeConName): Either[LookupError, DataVariantInfo] =
lookupDataVariant(tyCon, Reference.DataVariant(tyCon))

private[this] def lookupVariantConstructor(
tyCon: TypeConName,
consName: VariantConName,
context: => Reference,
): Either[LookupError, VariantConstructorInfo] =
lookupDataVariant(tyCon).flatMap(variantInfo =>
lookupDataVariant(tyCon, context).flatMap(variantInfo =>
variantInfo.dataVariant.constructorInfo.get(consName) match {
case Some((typ, rank)) => Right(VariantConstructorInfo(variantInfo, typ, rank))
case None => Left(LookupError.DataVariantConstructor(tyCon, consName))
case None => Left(LookupError(Reference.DataVariantConstructor(tyCon, consName), context))
}
)

def lookupDataEnum(
tyCon: TypeConName
def lookupVariantConstructor(
tyCon: TypeConName,
consName: VariantConName,
): Either[LookupError, VariantConstructorInfo] =
lookupVariantConstructor(tyCon, consName, Reference.DataVariantConstructor(tyCon, consName))

private[this] def lookupDataEnum(
tyCon: TypeConName,
context: => Reference,
): Either[LookupError, DataEnumInfo] =
lookupDataType(tyCon).flatMap { dataType =>
lookupDataType(tyCon, context).flatMap { dataType =>
dataType.cons match {
case cons: DataEnum => Right(DataEnumInfo(dataType, cons))
case _ => Left(LookupError.DataEnum(tyCon))
case _ => Left(LookupError(Reference.DataEnum(tyCon), context))
}
}

def lookupEnumConstructor(tyCon: TypeConName, consName: EnumConName): Either[LookupError, Int] =
lookupDataEnum(tyCon).flatMap { dataEnumInfo =>
def lookupDataEnum(tyCon: TypeConName): Either[LookupError, DataEnumInfo] =
lookupDataEnum(tyCon, Reference.DataEnum(tyCon))

private[this] def lookupEnumConstructor(
tyCon: TypeConName,
consName: EnumConName,
context: => Reference,
): Either[LookupError, Int] =
lookupDataEnum(tyCon, context).flatMap { dataEnumInfo =>
dataEnumInfo.dataEnum.constructorRank.get(consName) match {
case Some(rank) => Right(rank)
case None => Left(LookupError.DataVariantConstructor(tyCon, consName))
case None => Left(LookupError(Reference.DataVariantConstructor(tyCon, consName), context))
}
}

def lookupEnumConstructor(tyCon: TypeConName, consName: EnumConName): Either[LookupError, Int] =
lookupEnumConstructor(tyCon, consName, Reference.DataEnumConstructor(tyCon, consName))

private[this] def lookupTemplate(
name: TypeConName,
context: => Reference,
): Either[LookupError, TemplateSignature] =
lookupModule(name.packageId, name.qualifiedName.module, context).flatMap(
_.templates
.get(name.qualifiedName.name)
.toRight(LookupError(Reference.Template(name), context))
)

def lookupTemplate(name: TypeConName): Either[LookupError, TemplateSignature] =
lookupModule(name.packageId, name.qualifiedName.module).flatMap(
_.templates.get(name.qualifiedName.name).toRight(LookupError.Template(name))
lookupTemplate(name, Reference.Template(name))

private[this] def lookupChoice(
tmpName: TypeConName,
chName: ChoiceName,
context: => Reference,
): Either[LookupError, TemplateChoiceSignature] =
lookupTemplate(tmpName, context).flatMap(
_.choices.get(chName).toRight(LookupError(Reference.Choice(tmpName, chName), context))
)

def lookupChoice(
tmpName: TypeConName,
chName: ChoiceName,
): Either[LookupError, TemplateChoiceSignature] =
lookupTemplate(tmpName).flatMap(
_.choices.get(chName).toRight(LookupError.Choice(tmpName, chName))
lookupChoice(tmpName, chName, Reference.Choice(tmpName, chName))

private[this] def lookupTemplateKey(
name: TypeConName,
context: => Reference,
): Either[LookupError, TemplateKeySignature] =
lookupTemplate(name, context).flatMap(
_.key.toRight(LookupError(Reference.TemplateKey(name), context))
)

def lookupTemplateKey(name: TypeConName): Either[LookupError, TemplateKeySignature] =
lookupTemplate(name).flatMap(_.key.toRight(LookupError.TemplateKey(name)))
lookupTemplateKey(name, Reference.TemplateKey(name))

def lookupValue(name: ValueRef): Either[LookupError, DValueSignature] =
lookupDefinition(name).flatMap {
private[this] def lookupValue(
name: ValueRef,
context: => Reference,
): Either[LookupError, DValueSignature] =
lookupDefinition(name, context).flatMap {
case valueDef: DValueSignature => Right(valueDef)
case _ => Left(LookupError.Value(name))
case _ => Left(LookupError(Reference.Value(name), context))
}

def lookupException(name: TypeConName): Either[LookupError, DefExceptionSignature] =
lookupModule(name.packageId, name.qualifiedName.module).flatMap(
_.exceptions.get(name.qualifiedName.name).toRight(LookupError.Exception(name))
def lookupValue(name: ValueRef): Either[LookupError, DValueSignature] =
lookupValue(name, Reference.Value(name))

private[this] def lookupException(
name: TypeConName,
context: => Reference,
): Either[LookupError, DefExceptionSignature] =
lookupModule(name.packageId, name.qualifiedName.module, context).flatMap(
_.exceptions
.get(name.qualifiedName.name)
.toRight(LookupError(Reference.Exception(name), context))
)

def lookupException(name: TypeConName): Either[LookupError, DefExceptionSignature] =
lookupException(name, Reference.Exception(name))

val packageLanguageVersion: PartialFunction[PackageId, LanguageVersion] =
signatures andThen (_.languageVersion)

Expand Down
Loading

0 comments on commit 39eb5d3

Please sign in to comment.