Continuation 和控制流原语
操作码 | Fift 语法 | 堆栈 | Gas | 描述 |
---|---|---|---|---|
Please enter a search query | ||||
No results found |
TVM 指令内容列表
Continuation 和控制流原语
无条件控制流原语
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
D8 | EXECUTE CALLX | c - | 调用 或 执行 Continuation c 。 | 18 |
D9 | JMPX | c - | 跳转 或 控制转移到 Continuation c 。之前当前continuation cc 的剩余部分被丢弃。 | 18 |
DApr | [p] [r] CALLXARGS | c - | 用 p 参数 调用 continuation c 并期待 r 返回值0 <= p <= 15 , 0 <= r <= 15 | 26 |
DB0p | [p] -1 CALLXARGS | c - | 用 0 <= p <= 15 参数 调用 continuation c , 期望任意数量的返回值。 | 26 |
DB1p | [p] JMPXARGS | c - | 跳转 到 continuation c , 只将当前栈顶的 0 <= p <= 15 个值传递给它(当前栈的其余部分被丢弃)。 | 26 |
DB2r | [r] RETARGS | 返回 到 c0 , 携带 0 <= r <= 15 个从当前栈中取得的返回值。 | 26 | |
DB30 | RET RETTRUE | 返回 到 continuation c0 。当前 continuation cc 的剩余部分被丢弃。大致相当于 c0 PUSHCTR JMPX 。 | 26 | |
DB31 | RETALT RETFALSE | 返回 到 continuation c1 。大致相当于 c1 PUSHCTR JMPX 。 | 26 | |
DB32 | BRANCH RETBOOL | f - | 如果整数 f!=0 , 执行 RETTRUE ,如果 f=0 ,执行 RETFALSE 。 | 26 |
DB34 | CALLCC | c - | 带当前 continuation 调用,控制权转移到 c ,将旧的 cc 值推入 c 的栈中(而不是丢弃它或将其写入新的 c0 中)。 | 26 |
DB35 | JMPXDATA | c - | 类似于 CALLCC ,但是当前 continuation 的剩余部分(旧的 cc 值)在推入 c 的栈之前被转换成一个 Slice。 | 26 |
DB36pr | [p] [r] CALLCCARGS | c - | 类似于 CALLXARGS ,但是将旧的 cc 值(连同最初栈顶的 0 <= p <= 15 个值)推入被调用 continuation c 的栈中,设置 cc.nargs 为 -1 <= r <= 14 。 | 34 |
DB38 | CALLXVARARGS | c p r - | 类似于 CALLXARGS ,但从栈中取 -1 <= p,r <= 254 。接下来的三个操作也从栈中取 p 和 r ,范围都是 -1...254 。 | 26 |
DB39 | RETVARARGS | p r - | 类似于 RETARGS 。 | 26 |
DB3A | JMPXVARARGS | c p r - | 类似于 JMPXARGS 。 | 26 |
DB3B | CALLCCVARARGS | c p r - | 类似于 CALLCCARGS 。 | 26 |
DB3C | [ref] CALLREF | 等同于 PUSHREFCONT CALLX 。 | 126/51 | |
DB3D | [ref] JMPREF | 等同于 PUSHREFCONT JMPX 。 | 126/51 | |
DB3E | [ref] JMPREFDATA | 等同于 PUSHREFCONT JMPXDATA 。 | 126/51 | |
DB3F | RETDATA | 等同于 c0 PUSHCTR JMPXDATA 。这样,当前 continuation 的剩余部分被转换成一个 Slice 并返回给调用者。 | 26 |
条件控制流原语
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
DC | IFRET IFNOT: | f - | 如果整数 f 非零,则执行 RET 。如果 f 是 NaN , 抛出一个整数溢出异常。 | 18 |
DD | IFNOTRET IF: | f - | 如果整数 f 为零,则执行 RET 。 | 18 |
DE | IF | f c - | 如果整数 f 非零,执行 c (即,执行 c ),否则简单地丢弃两个值。 | 18 |
DE | IF:<{ code }> <{ code }>IF | f - | 等同于 <{ code }> CONT IF 。 | |
DF | IFNOT | f c - | 如果整数 f 为零,则执行 continuation c ,否则简单地丢弃两个值。 | 18 |
DF | IFNOT:<{ code }> <{ code }>IFNOT | f - | 等同于 <{ code }> CONT IFNOT 。 | |
E0 | IFJMP | f c - | 只有当 f 非零时,跳转到 c (类似于 JMPX )。 | 18 |
E0 | IFJMP:<{ code }> | f - | 等同于 <{ code }> CONT IFJMP 。 | |
E1 | IFNOTJMP | f c - | 只有当 f 为零时,跳转到 c (类似于 JMPX )。 | 18 |
E1 | IFNOTJMP:<{ code }> | f - | 等同于 <{ code }> CONT IFNOTJMP 。 | |
E2 | IFELSE | f c c' - | 如果整数 f 非零,执行 c ,否则执行 c' 。等同于 CONDSELCHK EXECUTE 。 | 18 |
E2 | IF:<{ code1 }>ELSE<{ code2 }> | f - | 等同于 <{ code1 }> CONT <{ code2 }> CONT IFELSE 。 | |
E300 | [ref] IFREF | f - | 等同于 PUSHREFCONT IF ,但优化了cell引用不实际加载入一个 Slice 再转换成一个普通 Continuation 如果 f=0 。这个原语的 Gas 消耗取决于 f=0 以及引用是否之前加载过。类似的评论适用于接受 continuation 作为引用的其他原语。 | 26/126/51 |
E301 | [ref] IFNOTREF | f - | 等同于 PUSHREFCONT IFNOT 。 | 26/126/51 |
E302 | [ref] IFJMPREF | f - | 等同于 PUSHREFCONT IFJMP 。 | 26/126/51 |
E303 | [ref] IFNOTJMPREF | f - | 等同于 PUSHREFCONT IFNOTJMP 。 | 26/126/51 |
E304 | CONDSEL | f x y - x 或 y | 如果整数 f 非零,返回 x ,否则返回 y 。注意 x 和 y 上不执行类型检查;因此,它更像是一个条件栈操作。大致等同于 ROT ISZERO INC ROLLX NIP 。 | 26 |
E305 | CONDSELCHK | f x y - x 或 y | 与 CONDSEL 相同,但首先检查 x 和 y 是否类型相同。 | 26 |
E308 | IFRETALT | f - | 如果整数 f!=0 执行 RETALT 。 | 26 |
E309 | IFNOTRETALT | f - | 如果整数 f=0 执行 RETALT 。 | 26 |
E30D | [ref] IFREFELSE | f c - | 等同于 PUSHREFCONT SWAP IFELSE ,但优化了在 f=0 时,实际上并不需要将cell引用加载进一个Slice,然后再转换成普通的 Continuation。对接下来的两个原语也适用类似的备注:只有在必要时,才将cell转换成 continuations。 | 26/126/51 |
E30E | [ref] IFELSEREF | f c - | 等同于 PUSHREFCONT IFELSE 。 | 26/126/51 |
E30F | [ref] [ref] IFREFELSEREF | f - | 等同于 PUSHREFCONT PUSHREFCONT IFELSE 。 | 126/51 |
E39_n | [n] IFBITJMP | x c - x | 检查整数 x 中是否设置了位 0 <= n <= 31 ,如果是,则执行 JMPX 跳转到 continuation c 。值 x 保留在栈中。 | 26 |
E3B_n | [n] IFNBITJMP | x c - x | 如果整数 x 中位 0 <= n <= 31 未设置,跳转到 c 。 | 26 |
E3D_n | [ref] [n] IFBITJMPREF | x - x | 如果整数 x 中设置了位 0 <= n <= 31 ,执行 JMPREF 。 | 126/51 |
E3F_n | [ref] [n] IFNBITJMPREF | x - x | 如果整数 x 中未设置位 0 <= n <= 31 ,执行 JMPREF 。 | 126/51 |
控制流原语:循环
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
E4 | REPEAT | n c - | 如果整数 n 为非负数,则执行 continuation c n 次。如果 n>=2^31 或 n<-2^31 ,会生成一个范围检查异常。注意,在 c 的代码内部的 RET 作为 continue 使用,而不是 break 。应使用另一种(实验性的)循环或者 RETALT (循环前与 SETEXITALT 一起使用)来从循环中 break 出去。 | 18 |
E4 | REPEAT:<{ code }> <{ code }>REPEAT | n - | 等同于 <{ code }> CONT REPEAT 。 | |
E5 | REPEATEND REPEAT: | n - | 类似于 REPEAT ,但它应用于当前 continuation cc 。 | 18 |
E6 | UNTIL | c - | 执行 continuation c ,然后从结果栈中弹出一个整数 x 。如果 x 为零,执行此循环的另一次迭代。这个原语的实际实现涉及一个特殊的 continuation ec_until ,其参数设置为循环体(continuation c )和原始的当前 continuation cc 。然后这个特殊的 continuation 被保存到 c 的 savelist 作为 c.c0 ,然后执行修改后的 c 。其他循环原语也类似地借助适当的特殊 continuations 实现。 | 18 |
E6 | UNTIL:<{ code }> <{ code }>UNTIL | - | 等同于 <{ code }> CONT UNTIL 。 | |
E7 | UNTILEND UNTIL: | - | 类似于 UNTIL ,但在循环中执行当前 continuation cc 。当满足循环退出条件时,执行 RET 。 | 18 |
E8 | WHILE | c' c - | 执行 c' 并从结果栈中弹出一个整数 x 。如果 x 为零,则退出循环并将控制权转移给原始 cc 。如果 x 非零,则执行 c ,然后开始新的迭代。 | 18 |
E8 | WHILE:<{ cond }>DO<{ code }> | - | 等同于 <{ cond }> CONT <{ code }> CONT WHILE 。 | |
E9 | WHILEEND | c' - | 类似于 WHILE ,但使用当前 continuation cc 作为循环体。 | 18 |
EA | AGAIN | c - | 类似于 REPEAT ,但无限次执行 c 。一个 RET 只是开始一个无限循环的新迭代,只能通过异常或 RETALT (或显式的 JMPX )退出。 | 18 |
EA | AGAIN:<{ code }> <{ code }>AGAIN | - | 等同于 <{ code }> CONT AGAIN 。 | |
EB | AGAINEND AGAIN: | - | 类似于 AGAIN ,但相对于当前 continuation cc 执行。 | 18 |
E314 | REPEATBRK | n c - | 类似于 REPEAT ,但在将旧的 c1 值保存到原始 cc 的 savelist 后,还将 c1 设置为原始 cc 。这样,RETALT 可以用来退出循环体。 | 26 |
E314 | REPEATBRK:<{ code }> <{ code }>REPEATBRK | n - | 等同于 <{ code }> CONT REPEATBRK 。 | |
E315 | REPEATENDBRK | n - | 类似于 REPEATEND ,但在将旧的 c1 值保存到原始 c0 的 savelist 后,还将 c1 设置为原始 c0 。等同于 SAMEALTSAVE REPEATEND 。 | 26 |
E316 | UNTILBRK | c - | 类似于 UNTIL ,但也以与 REPEATBRK 相同的方式修改 c1 。 | 26 |
E316 | UNTILBRK:<{ code }> | - | 等同于 <{ code }> CONT UNTILBRK 。 | |
E317 | UNTILENDBRK UNTILBRK: | - | 等同于 SAMEALTSAVE UNTILEND 。 | 26 |
E318 | WHILEBRK | c' c - | 类似于 WHILE ,但也以与 REPEATBRK 相同的方式修改 c1 。 | 26 |
E318 | WHILEBRK:<{ cond }>DO<{ code }> | - | 等同于 <{ cond }> CONT <{ code }> CONT WHILEBRK 。 | |
E319 | WHILEENDBRK | c - | 等同于 SAMEALTSAVE WHILEEND 。 | 26 |
E31A | AGAINBRK | c - | 类似于 AGAIN ,但也以与 REPEATBRK 相同的方式修改 c1 。 | 26 |
E31A | AGAINBRK:<{ code }> | - | 等同于 <{ code }> CONT AGAINBRK 。 | |
E31B | AGAINENDBRK AGAINBRK: | - | 等同于 SAMEALTSAVE AGAINEND 。 | 26 |
操作 continuation 栈
这里的 s"
是在 continuations 之间移动栈元素的费用。它等于结果栈的大小减去32(如果栈大小小于32,则为0)。
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
ECrn | [r] [n] SETCONTARGS | x_1 x_2...x_r c - c' | 类似于 [r] -1 SETCONTARGS ,但将 c.nargs 设置为 c' 的栈的最终大小加上 n 。换句话说,将 c 转换成一个闭包或部分应用函数,缺少 0 <= n <= 14 个参数。 | 26+s” |
EC0n | [n] SETNUMARGS | c - c' | 设置 c.nargs 为 n 加上 c 的当前栈的深度,其中 0 <= n <= 14 。如果 c.nargs 已经设置为非负值,则不进行任何操作。 | 26 |
ECrF | [r] -1 SETCONTARGS | x_1 x_2...x_r c - c' | 将 0 <= r <= 15 个值 x_1...x_r 推入(复制的)continuation c 的栈中,从 x_1 开始。如果 c 的栈最终深度超过了 c.nargs ,将生成栈溢出异常。 | 26+s” |
ED0p | [p] RETURNARGS | - | 仅保留当前栈顶的 0 <= p <= 15 个值(类似于 ONLYTOPX ),所有未使用的底部值不被丢弃,而是以与 SETCONTARGS 相同的方式保存到 continuation c0 中。 | 26+s” |
ED10 | RETURNVARARGS | p - | 类似于 RETURNARGS ,但从栈中取整数 0 <= p <= 255 。 | 26+s” |
ED11 | SETCONTVARARGS | x_1 x_2...x_r c r n - c' | 类似于 SETCONTARGS ,但从栈中取 0 <= r <= 255 和 -1 <= n <= 255 。 | 26+s” |
ED12 | SETNUMVARARGS | c n - c' | -1 <= n <= 255 如果 n=-1 ,此操作不进行任何操作(c'=c )。否则其行为类似于 [n] SETNUMARGS ,但 n 是从栈中取得的。 | 26 |
创建简单的 continuations 和 闭包
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
ED1E | BLESS | s - c | 将 Slice s 转换为简单的普通 continuation c ,其中 c.code=s ,并且栈和 savelist 为空。 | 26 |
ED1F | BLESSVARARGS | x_1...x_r s r n - c | 等同于 ROT BLESS ROTREV SETCONTVARARGS 。 | 26+s” |
EErn | [r] [n] BLESSARGS | x_1...x_r s - c | 0 <= r <= 15 , -1 <= n <= 14 等同于 BLESS [r] [n] SETCONTARGS 。n 的值由 4 位整数 n mod 16 内部表示。 | 26 |
EE0n | [n] BLESSNUMARGS | s - c | 也将 Slice s 转换为 Continuation c ,但将 c.nargs 设置为 0 <= n <= 14 。 | 26 |
Continuation 保存列表和控制寄存器的操作
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
ED4i | c[i] PUSHCTR c[i] PUSH | - x | 推送控制寄存器 c(i) 的当前值。如果当前代码页不支持该控制寄存器,或者它没有值,则触发异常。 | 26 |
ED44 | c4 PUSHCTR c4 PUSH | - x | 推送“全局数据根”cell引用,从而使访问持久智能合约数据成为可能。 | 26 |
ED5i | c[i] POPCTR c[i] POP | x - | 从栈中弹出一个值 x 并存储到控制寄存器 c(i) 中(如果当前代码页支持)。注意,如果控制寄存器仅接受特定类型的值,则可能发生类型检查异常。 | 26 |
ED54 | c4 POPCTR c4 POP | x - | 设置“全局数据根”cell引用,从而允许修改持久智能合约数据。 | 26 |
ED6i | c[i] SETCONT c[i] SETCONTCTR | x c - c' | 将 x 存储到 continuation c 的 savelist 中作为 c(i) ,并返回结果 continuation c' 。几乎所有与 continuations 的操作都可以用 SETCONTCTR 、POPCTR 和 PUSHCTR 来表达。 | 26 |
ED7i | c[i] SETRETCTR | x - | 等同于 c0 PUSHCTR c[i] SETCONTCTR c0 POPCTR 。 | 26 |
ED8i | c[i] SETALTCTR | x - | 等同于 c1 PUSHCTR c[i] SETCONTCTR c0 POPCTR 。 | 26 |
ED9i | c[i] POPSAVE c[i] POPCTRSAVE | x - | 类似于 c[i] POPCTR ,但还将 c[i] 的旧值保存到 continuation c0 中。等同于(直到异常) c[i] SAVECTR c[i] POPCTR 。 | 26 |
EDAi | c[i] SAVE c[i] SAVECTR | 将 c(i) 的当前值保存到 continuation c0 的 savelist 中。如果 c0 的 savelist 中已存在 c[i] 的条目,则不做任何操作。等同于 c[i] PUSHCTR c[i] SETRETCTR 。 | 26 | |
EDBi | c[i] SAVEALT c[i] SAVEALTCTR | 类似于 c[i] SAVE ,但将 c[i] 的当前值保存到 c1 (而不是 c0 )的 savelist 中。 | 26 | |
EDCi | c[i] SAVEBOTH c[i] SAVEBOTHCTR | 等同于 DUP c[i] SAVE c[i] SAVEALT 。 | 26 | |
EDE0 | PUSHCTRX | i - x | 类似于 c[i] PUSHCTR ,但 i , 0 <= i <= 255 , 来自栈。注意,这个原语是少数“异乎寻常”的原语之一,它们不像栈操作原语那样是多态的,同时参数和返回值的类型也没有良好定义,因为 x 的类型取决于 i 。 | 26 |
EDE1 | POPCTRX | x i - | 类似于 c[i] POPCTR ,但 0 <= i <= 255 来自栈。 | 26 |
EDE2 | SETCONTCTRX | x c i - c' | 类似于 c[i] SETCONTCTR ,但 0 <= i <= 255 来自栈。 | 26 |
EDF0 | COMPOS BOOLAND | c c' - c'' | 计算组合 compose0(c, c’) ,它的意义为“执行 c ,如果成功,执行 c' ”(如果 c 是布尔电路)或简单地“执行 c ,然后执行 c' ”。等同于 SWAP c0 SETCONT 。 | 26 |
EDF1 | COMPOSALT BOOLOR | c c' - c'' | 计算替代组合 compose1(c, c’) ,它的意义为“执行 c ,如果不成功,执行 c' ”(如果 c 是布尔电路)。等同于 SWAP c1 SETCONT 。 | 26 |
EDF2 | COMPOSBOTH | c c' - c'' | 计算组合 compose1(compose0(c, c’), c’) ,它的意义为“计算布尔电路 c ,然后无论 c 的结果如何,都计算 c' ”。 | 26 |
EDF3 | ATEXIT | c - | 将 c0 设置为 compose0(c, c0) 。换句话说,c 将在退出当前子程序之前执行。 | 26 |
EDF3 | ATEXIT:<{ code }> <{ code }>ATEXIT | - | 等同于 <{ code }> CONT ATEXIT 。 | |
EDF4 | ATEXITALT | c - | 将 c1 设置为 compose1(c, c1) 。换句话说,c 将在通过其替代返回路径退出当前子程序之前执行。 | 26 |
EDF4 | ATEXITALT:<{ code }> <{ code }>ATEXITALT | - | 等同于 <{ code }> CONT ATEXITALT 。 | |
EDF5 | SETEXITALT | c - | 将 c1 设置为 compose1(compose0(c, c0), c1) ,这样,后续的 RETALT 将首先执行 c ,然后将控制权转移给原始的 c0 。例如,这可以用来从嵌套循环中退出。 | 26 |
EDF6 | THENRET | c - c' | 计算 compose0(c, c0) 。 | 26 |
EDF7 | THENRETALT | c - c' | 计算 compose0(c, c1) | 26 |
EDF8 | INVERT | - | 交换 c0 和 c1 。 | 26 |
EDF9 | BOOLEVAL | c - ? | 执行 cc:=compose1(compose0(c, compose0(-1 PUSHINT, cc)), compose0(0 PUSHINT, cc)) 。如果 c 代表一个布尔电路,其最终效果是评估它,并在继续执行之前将 -1 或 0 推入栈中。 | 26 |
EDFA | SAMEALT | - | 将 c1 设置为 c0 。等同于 c0 PUSHCTR c1 POPCTR 。 | 26 |
EDFB | SAMEALTSAVE | - | 将 c1 设置为 c0 ,但首先将 c1 的旧值保存到 c0 的 savelist 中。等同于 c1 SAVE SAMEALT 。 | 26 |
字典子程序调用和跳转
xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
---|---|---|---|---|
F0nn | [nn] CALL [nn] CALLDICT | - nn | 调用 c3 中的 continuation,将整数 0 <= nn <= 255 作为参数推入其栈。大致相当于 [nn] PUSHINT c3 PUSHCTR EXECUTE 。 | |
F12_n | [n] CALL [n] CALLDICT | - n | 对于 0 <= n < 2^14 ,这是更大值的 n 的 [n] CALL 的编码。 | |
F16_n | [n] JMP | - n | 跳转到 c3 中的 continuation,将整数 0 <= n < 2^14 作为其参数推入。大致相当于 n PUSHINT c3 PUSHCTR JMPX 。 | |
F1A_n | [n] PREPARE [n] PREPAREDICT | - n c | 等同于 n PUSHINT c3 PUSHCTR ,适用于 0 <= n < 2^14 。这样, [n] CALL 大致等同于 [n] PREPARE EXECUTE ,而 [n] JMP 大致等同于 [n] PREPARE JMPX 。例如,这里可以使用 CALLXARGS 或 CALLCC 代替 EXECUTE 。 |