From b661194a93c2f7ff4733d1086dea6c991d99f370 Mon Sep 17 00:00:00 2001 From: InversionSpaces Date: Fri, 7 Jul 2023 07:48:16 +0000 Subject: [PATCH] Add fail model --- .../src/main/scala/aqua/backend/air/Air.scala | 5 +++ .../main/scala/aqua/backend/air/AirGen.scala | 11 +++++++ .../main/scala/aqua/raw/value/ValueRaw.scala | 25 +++++++------- .../res/src/main/scala/aqua/res/MakeRes.scala | 2 ++ .../src/main/scala/aqua/res/ResolvedOp.scala | 4 +++ model/src/main/scala/aqua/model/OpModel.scala | 6 ++++ .../main/scala/aqua/model/ValueModel.scala | 33 +++++++++++++++++++ 7 files changed, 74 insertions(+), 12 deletions(-) diff --git a/backend/air/src/main/scala/aqua/backend/air/Air.scala b/backend/air/src/main/scala/aqua/backend/air/Air.scala index b2ed57c7e..84052e68b 100644 --- a/backend/air/src/main/scala/aqua/backend/air/Air.scala +++ b/backend/air/src/main/scala/aqua/backend/air/Air.scala @@ -24,6 +24,8 @@ object Keyword { case object Ap extends Keyword("ap") + case object Fail extends Keyword("fail") + case object Canon extends Keyword("canon") case object Seq extends Keyword("seq") @@ -110,6 +112,8 @@ object Air { case class Ap(op: DataView, result: String) extends Air(Keyword.Ap) + case class Fail(op: DataView) extends Air(Keyword.Fail) + case class Canon(op: DataView, peerId: DataView, result: String) extends Air(Keyword.Canon) case class Comment(comment: String, air: Air) extends Air(Keyword.NA) @@ -143,6 +147,7 @@ object Air { case Air.Call(triplet, args, res) ⇒ s" ${triplet.show} [${args.map(_.show).mkString(" ")}]${res.fold("")(" " + _)}" case Air.Ap(operand, result) ⇒ s" ${operand.show} $result" + case Air.Fail(operand) => s" ${operand.show}" case Air.Canon(operand, peerId, result) ⇒ s" ${peerId.show} ${operand.show} $result" case Air.Comment(_, _) => ";; Should not be displayed" }) + ")\n" diff --git a/backend/air/src/main/scala/aqua/backend/air/AirGen.scala b/backend/air/src/main/scala/aqua/backend/air/AirGen.scala index 83c065bb6..eaca0d744 100644 --- a/backend/air/src/main/scala/aqua/backend/air/AirGen.scala +++ b/backend/air/src/main/scala/aqua/backend/air/AirGen.scala @@ -118,6 +118,11 @@ object AirGen extends Logging { ApGen(valueToData(operand), exportToString(exportTo)) ) + case FailRes(operand) => + Eval.later( + FailGen(valueToData(operand)) + ) + case CanonRes(operand, peerId, exportTo) => Eval.later( CanonGen(valueToData(operand), valueToData(peerId), exportToString(exportTo)) @@ -164,6 +169,12 @@ case class ApGen(operand: DataView, result: String) extends AirGen { Air.Ap(operand, result) } +case class FailGen(operand: DataView) extends AirGen { + + override def generate: Air = + Air.Fail(operand) +} + case class CanonGen(operand: DataView, peerId: DataView, result: String) extends AirGen { override def generate: Air = diff --git a/model/raw/src/main/scala/aqua/raw/value/ValueRaw.scala b/model/raw/src/main/scala/aqua/raw/value/ValueRaw.scala index 693aa2184..84a7cebcf 100644 --- a/model/raw/src/main/scala/aqua/raw/value/ValueRaw.scala +++ b/model/raw/src/main/scala/aqua/raw/value/ValueRaw.scala @@ -27,21 +27,22 @@ object ValueRaw { val Nil: LiteralRaw = LiteralRaw("[]", StreamType(BottomType)) - val LastError: VarRaw = VarRaw( - "%last_error%", - StructType( - "LastError", - NonEmptyMap.of( - // These two fields are mandatory for all errors - "message" -> ScalarType.string, - "error_code" -> ScalarType.i64, - // These fields are specific to AquaVM's errors only - "instruction" -> ScalarType.string, - "peer_id" -> ScalarType.string - ) + val lastErrorType = StructType( + "LastError", + NonEmptyMap.of( + // These two fields are mandatory for all errors + "message" -> ScalarType.string, + "error_code" -> ScalarType.i64, + // These fields are specific to AquaVM's errors only + "instruction" -> ScalarType.string, + "peer_id" -> ScalarType.string ) ) + val LastError: VarRaw = VarRaw( + "%last_error%", + lastErrorType + ) } case class ApplyPropertyRaw(value: ValueRaw, property: PropertyRaw) extends ValueRaw { diff --git a/model/res/src/main/scala/aqua/res/MakeRes.scala b/model/res/src/main/scala/aqua/res/MakeRes.scala index 688920ec8..9e94063c4 100644 --- a/model/res/src/main/scala/aqua/res/MakeRes.scala +++ b/model/res/src/main/scala/aqua/res/MakeRes.scala @@ -76,6 +76,8 @@ object MakeRes { ApRes(operand, CallModel.Export(assignTo, ArrayType(el))).leaf case FlattenModel(operand, assignTo) => ApRes(operand, CallModel.Export(assignTo, operand.`type`)).leaf + case FailModel(value) => + FailRes(value).leaf case CallServiceModel(serviceId, funcName, CallModel(args, exportTo)) => CallServiceRes( serviceId, diff --git a/model/res/src/main/scala/aqua/res/ResolvedOp.scala b/model/res/src/main/scala/aqua/res/ResolvedOp.scala index 070ffaa55..9a9dc6126 100644 --- a/model/res/src/main/scala/aqua/res/ResolvedOp.scala +++ b/model/res/src/main/scala/aqua/res/ResolvedOp.scala @@ -54,6 +54,10 @@ case class ApRes(operand: ValueModel, exportTo: CallModel.Export) extends Resolv override def toString: String = s"(ap $operand $exportTo)" } +case class FailRes(operand: ValueModel) extends ResolvedOp { + override def toString: String = s"(fail $operand)" +} + case class CanonRes(operand: ValueModel, peerId: ValueModel, exportTo: CallModel.Export) extends ResolvedOp { override def toString: String = s"(canon $peerId $operand $exportTo)" diff --git a/model/src/main/scala/aqua/model/OpModel.scala b/model/src/main/scala/aqua/model/OpModel.scala index 770ac487e..f416edcca 100644 --- a/model/src/main/scala/aqua/model/OpModel.scala +++ b/model/src/main/scala/aqua/model/OpModel.scala @@ -146,6 +146,12 @@ case class FlattenModel(value: ValueModel, assignTo: String) extends OpModel { override def exportsVarNames: Set[String] = Set(assignTo) } +case class FailModel(value: ValueModel) extends OpModel { + override def usesVarNames: Set[String] = value.usesVarNames + + override def exportsVarNames: Set[String] = Set.empty +} + case class PushToStreamModel(value: ValueModel, exportTo: CallModel.Export) extends OpModel { override def usesVarNames: Set[String] = value.usesVarNames diff --git a/model/src/main/scala/aqua/model/ValueModel.scala b/model/src/main/scala/aqua/model/ValueModel.scala index c15af153e..4285cd1b9 100644 --- a/model/src/main/scala/aqua/model/ValueModel.scala +++ b/model/src/main/scala/aqua/model/ValueModel.scala @@ -2,8 +2,10 @@ package aqua.model import aqua.raw.value.* import aqua.types.* + import cats.Eq import cats.data.{Chain, NonEmptyMap} +import cats.syntax.option.* import scribe.Logging sealed trait ValueModel { @@ -18,6 +20,19 @@ sealed trait ValueModel { object ValueModel { + def errorCode(error: VarModel): Option[VarModel] = + error.intoField("error_code") + + val lastError = VarModel( + name = ValueRaw.LastError.name, + baseType = ValueRaw.LastError.baseType + ) + + val lastErrorType = ValueRaw.lastErrorType + + // NOTE: It should be safe as %last_error% should have `error_code` field + val lastErrorCode = errorCode(lastError).get + implicit object ValueModelEq extends Eq[ValueModel] { override def eqv(x: ValueModel, y: ValueModel): Boolean = x == y } @@ -46,9 +61,16 @@ case class LiteralModel(value: String, `type`: Type) extends ValueModel { } object LiteralModel { + + // AquaVM will return empty string for + // %last_error%.$.error_code if there is no %last_error% + val emptyErrorCode = quote("") + def fromRaw(raw: LiteralRaw): LiteralModel = LiteralModel(raw.value, raw.baseType) def quote(str: String): LiteralModel = LiteralModel(s"\"$str\"", LiteralType.string) + + def number(n: Int): LiteralModel = LiteralModel(n.toString, LiteralType.number) } sealed trait PropertyModel { @@ -117,6 +139,17 @@ case class VarModel(name: String, baseType: Type, properties: Chain[PropertyMode private def deriveFrom(vm: VarModel): VarModel = vm.copy(properties = vm.properties ++ properties) + def intoField(field: String): Option[VarModel] = `type` match { + case StructType(_, fields) => + fields(field) + .map(fieldType => + copy( + properties = properties :+ IntoFieldModel(field, fieldType) + ) + ) + case _ => none + } + override def resolveWith(vals: Map[String, ValueModel]): ValueModel = vals.get(name) match { case Some(vv: VarModel) =>