feat(compiler): Replace %last_error% with :error: [fixes LNG-239] (#883)

* %last_error% -> :error:

* Add integration test

* Fix integration tests

* Update integration test
This commit is contained in:
InversionSpaces 2023-09-26 12:28:13 +02:00 committed by GitHub
parent 91af0bf055
commit a80033b81c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 104 additions and 49 deletions

View File

@ -188,7 +188,7 @@ class AquaCompilerSpec extends AnyFlatSpec with Matchers {
SeqRes.wrap(
through(ValueModel.fromRaw(relay)),
through(initPeer),
failLastErrorRes
failErrorRes
)
),
NextRes(peer.name).leaf

View File

@ -0,0 +1,21 @@
aqua ErrorClear
export errorClearTest, FailService
service FailService("fail-srv"):
call(s: string) -> string
func errorClearTest(node: string, relay: string) -> string, i64:
stream: *string
code: ?i64
on node via relay:
try:
stream <- FailService.call("fail")
otherwise:
stream <- FailService.call("handle")
code <<- LAST_ERROR.error_code
<- stream!, code!

View File

@ -15,6 +15,7 @@ import {
nestedOnPropagateCall,
seqOnPropagateCall,
} from "../examples/onErrorPropagation.js";
import { errorClearCall } from "../examples/errorClear.js";
import { funcCall } from "../examples/funcCall.js";
import { registerPrintln } from "../compiled/examples/println.js";
import { helloWorldCall } from "../examples/helloWorldCall.js";
@ -744,6 +745,11 @@ describe("Testing examples", () => {
});
});
it("errorClear.aqua", async () => {
let errorClearResult = await errorClearCall(peer2);
expect(errorClearResult).toEqual(["handle", 0]);
});
it("complex.aqua", async () => {
let complexCallResult = await complexCall(selfPeerId, relayPeerId1);
expect(complexCallResult).toEqual([

View File

@ -0,0 +1,16 @@
import { IFluenceClient } from "@fluencelabs/js-client";
import {
errorClearTest,
registerFailService,
} from "../compiled/examples/errorClear.js";
export async function errorClearCall(peer: IFluenceClient) {
registerFailService(peer, {
call: (s: string) => {
if (s === "fail") return Promise.reject(s);
else return Promise.resolve(s);
},
});
return await errorClearTest(peer.getPeerId(), peer.getRelayPeerId());
}

View File

@ -201,7 +201,7 @@ object TagInliner extends Logging {
),
// This will return to previous topology
// and propagate error up
FailModel(ValueModel.lastError).leaf
FailModel(ValueModel.error).leaf
)
} yield TagInlined.Mapping(
toModel = toModel,

View File

@ -42,7 +42,7 @@ object ConstantRaw {
val lastError: ConstantRaw =
ConstantRaw(
"LAST_ERROR",
ValueRaw.lastError,
ValueRaw.error,
false
)

View File

@ -21,29 +21,41 @@ sealed trait ValueRaw {
}
object ValueRaw {
// TODO: move to LiteralRaw
val InitPeerId: LiteralRaw = LiteralRaw("%init_peer_id%", ScalarType.string)
val ParticleTtl: LiteralRaw = LiteralRaw("%ttl%", ScalarType.u32)
val ParticleTimestamp: LiteralRaw = LiteralRaw("%timestamp%", ScalarType.u64)
val Nil: LiteralRaw = LiteralRaw("[]", StreamType(BottomType))
val lastErrorType = StructType(
"LastError",
/**
* Type of error value
*/
val errorType = StructType(
"Error",
NonEmptyMap.of(
// These two fields are mandatory for all errors
/**
* `message` and `error_code` are always present
* For no-error state `message = ""` and `error_code = 0`
*/
"message" -> ScalarType.string,
"error_code" -> ScalarType.i64,
// These fields are specific to AquaVM's errors only
/**
* Instruction that caused error
* For no-error state accessing this leads to error
*/
"instruction" -> ScalarType.string,
/**
* Peer id that caused error
* Only set for `call` and `canon` instructions
* For no-error state accessing this leads to error
*/
"peer_id" -> ScalarType.string
)
)
val lastError: VarRaw = VarRaw(
"%last_error%",
lastErrorType
val error: VarRaw = VarRaw(
":error:",
errorType
)
type ApplyRaw = ApplyGateRaw | ApplyPropertyRaw | CallArrowRaw | CollectionRaw |

View File

@ -24,15 +24,11 @@ object ValueModel {
def errorCode(error: VarModel): Option[VarModel] =
error.intoField("error_code")
val lastError = VarModel(
name = ValueRaw.lastError.name,
baseType = ValueRaw.lastError.baseType
)
val error = VarModel.fromVarRaw(ValueRaw.error)
val errorType = ValueRaw.errorType
val lastErrorType = ValueRaw.lastErrorType
// NOTE: It should be safe as %last_error% should have `error_code` field
val lastErrorCode = errorCode(lastError).get
// NOTE: It should be safe as `:error:` should have `error_code` field
val lastErrorCode = errorCode(error).get
implicit object ValueModelEq extends Eq[ValueModel] {
override def eqv(x: ValueModel, y: ValueModel): Boolean = x == y
@ -238,3 +234,7 @@ case class VarModel(name: String, baseType: Type, properties: Chain[PropertyMode
this // Should not happen
}
}
object VarModel {
def fromVarRaw(raw: VarRaw): VarModel = VarModel(raw.name, raw.baseType)
}

View File

@ -9,7 +9,7 @@ import cats.data.Chain
import cats.free.Cofree
trait ErrorHandler {
def handleLastError: RawTag.Tree
def handleError: RawTag.Tree
}
case class CallbackErrorHandler(
@ -17,9 +17,9 @@ case class CallbackErrorHandler(
funcName: String
) extends ErrorHandler {
override def handleLastError: RawTag.Tree = {
override def handleError: RawTag.Tree = {
val call = Call(
args = ValueRaw.lastError :: LiteralRaw.number(0) :: Nil,
args = ValueRaw.error :: LiteralRaw.number(0) :: Nil,
exportTo = Nil
)

View File

@ -89,7 +89,7 @@ case class FuncPreTransformer(
returnType
)
val handleError = errorHandler.handleLastError
val handleError = errorHandler.handleError
val call = CallArrowRawTag.func(func.funcName, funcCall).leaf

View File

@ -81,7 +81,7 @@ object ModelBuilder {
ValueModel.fromRaw(bc.errorHandlingSrvId),
bc.errorFuncName,
CallRes(
ValueModel.lastError :: LiteralModel.number(i) :: Nil,
ValueModel.error :: LiteralModel.number(i) :: Nil,
None
),
on
@ -108,9 +108,9 @@ object ModelBuilder {
)
.leaf
val failLastErrorModel = FailModel(ValueModel.lastError).leaf
val failErrorModel = FailModel(ValueModel.error).leaf
val failLastErrorRes = res.FailRes(ValueModel.lastError).leaf
val failErrorRes = res.FailRes(ValueModel.error).leaf
def onRethrowModel(
peer: ValueModel,
@ -121,7 +121,7 @@ object ModelBuilder {
OnModel(peer, Chain.fromSeq(via)).wrap(
child
),
failLastErrorModel
failErrorModel
)
def fold(item: String, iter: ValueRaw, mode: Option[ForModel.Mode], body: OpModel.Tree*) = {

View File

@ -64,7 +64,7 @@ class TransformSpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relayV),
through(initPeer),
failLastErrorRes
failErrorRes
)
),
errorCall(bc, 0, initPeer)
@ -111,7 +111,7 @@ class TransformSpec extends AnyFlatSpec with Matchers {
SeqRes.wrap(
through(relayV),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
),

View File

@ -932,7 +932,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
).wrap(
callModel(0, CallModel.Export("var", ScalarType.string) :: Nil)
),
failLastErrorModel
failErrorModel
)
),
callModel(1, Nil, VarRaw("var", ScalarType.string) :: Nil)
@ -954,7 +954,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
),
@ -1036,7 +1036,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
)
@ -1081,7 +1081,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay2),
through(otherRelay),
through(otherPeerL),
failLastErrorRes
failErrorRes
)
)
),
@ -1089,7 +1089,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
)
@ -1141,14 +1141,14 @@ class TopologySpec extends AnyFlatSpec with Matchers {
SeqRes.wrap(
through(otherRelay2),
through(otherPeerN(3)),
failLastErrorRes
failErrorRes
)
)
),
SeqRes.wrap(
through(otherRelay),
through(otherPeerL),
failLastErrorRes
failErrorRes
)
)
),
@ -1156,7 +1156,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
)
@ -1193,7 +1193,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
),
XorRes.wrap(
@ -1206,7 +1206,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay2),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
)
@ -1246,7 +1246,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
),
XorRes.wrap(
@ -1258,7 +1258,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
SeqRes.wrap(
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
),
XorRes.wrap(
@ -1271,7 +1271,7 @@ class TopologySpec extends AnyFlatSpec with Matchers {
through(otherRelay2),
through(relay),
through(initPeer),
failLastErrorRes
failErrorRes
)
)
)

View File

@ -22,7 +22,7 @@ class CatchSem[S[_]](val expr: CatchExpr[S]) extends AnyVal {
): Prog[Alg, Raw] =
Prog
.around(
N.define(expr.name, ValueRaw.lastError.baseType),
N.define(expr.name, ValueRaw.errorType),
(_, g: Raw) =>
g match {
case FuncOp(op) =>
@ -31,7 +31,7 @@ class CatchSem[S[_]](val expr: CatchExpr[S]) extends AnyVal {
tag = TryTag.Catch
.wrap(
SeqTag.wrap(
AssignmentTag(ValueRaw.lastError, expr.name.value).leaf,
AssignmentTag(ValueRaw.error, expr.name.value).leaf,
restricted
)
)

View File

@ -204,7 +204,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
TryTag.wrap(
testServiceCallStr("try"),
SeqTag.wrap(
AssignmentTag(ValueRaw.lastError, "e").leaf,
AssignmentTag(ValueRaw.error, "e").leaf,
testServiceCallStr("catch")
)
)
@ -230,11 +230,11 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
TryTag.wrap(
testServiceCallStr("try"),
SeqTag.wrap(
AssignmentTag(ValueRaw.lastError, "e").leaf,
AssignmentTag(ValueRaw.error, "e").leaf,
testServiceCallStr("catch1")
),
SeqTag.wrap(
AssignmentTag(ValueRaw.lastError, "e").leaf,
AssignmentTag(ValueRaw.error, "e").leaf,
testServiceCallStr("catch2")
)
)
@ -557,7 +557,7 @@ class SemanticsSpec extends AnyFlatSpec with Matchers with Inside {
val expected = TryTag.wrap(
declareStreamPush("stream", "a"),
SeqTag.wrap(
AssignmentTag(ValueRaw.lastError, "e").leaf,
AssignmentTag(ValueRaw.error, "e").leaf,
declareStreamPush("stream", "b")
),
declareStreamPush("stream", "c")