Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LF: add context in LookupError #10314

Merged
merged 1 commit into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -355,7 +355,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