Continuation 和控制流原语
| 操作码 | Fift 语法 | 堆栈 | Gas | 描述 |
|---|---|---|---|---|
| Please enter a search query | ||||
| No results found | ||||
TVM 指令内容列表
Continuation 和控制流原语
无条件控制流原语
| xxxxxxx 操作码 | xxxxxxxxxxxxxxxxxxxxxxxxxxxx Fift 语法 | xxxxxxxxxxxxxxxxx 堆栈 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 描述 | xxxx Gas |
|---|---|---|---|---|
D8 | EXECUTECALLX | 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 | RETRETTRUE | 返回 到 continuation c0。当前 continuation cc的剩余部分被丢弃。大致相当于 c0 PUSHCTR JMPX。 | 26 | |
DB31 | RETALTRETFALSE | 返回 到 continuation c1。大致相当于 c1 PUSHCTR JMPX。 | 26 | |
DB32 | BRANCHRETBOOL | 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 | IFRETIFNOT: | f - | 如果整数 f 非零,则执行 RET。如果 f 是 NaN, 抛出一个整数溢出异常。 | 18 |
DD | IFNOTRETIF: | 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 | REPEATENDREPEAT: | 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 | UNTILENDUNTIL: | - | 类似于 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 | AGAINENDAGAIN: | - | 类似于 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 | UNTILENDBRKUNTILBRK: | - | 等同于 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 | AGAINENDBRKAGAINBRK: | - | 等同于 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] PUSHCTRc[i] PUSH | - x | 推送控制寄存器 c(i) 的当前值。如果当前代码页不支持该控制寄存器,或者它没有值,则触发异常。 | 26 |
ED44 | c4 PUSHCTRc4 PUSH | - x | 推送“全局数据根”cell引用,从而使访问持久智能合约数据成为可能。 | 26 |
ED5i | c[i] POPCTRc[i] POP | x - | 从栈中弹出一个值 x 并存储到控制寄存器 c(i) 中(如果当前代码页支持)。注意,如果控制寄存器仅接受特定类型的值,则可能发生类型检查异常。 | 26 |
ED54 | c4 POPCTRc4 POP | x - | 设置“全局数据根”cell引用,从而允许修改持久智能合约数据。 | 26 |
ED6i | c[i] SETCONTc[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] POPSAVEc[i] POPCTRSAVE | x - | 类似于 c[i] POPCTR,但还将 c[i] 的旧值保存到 continuation c0 中。等同于(直到异常) c[i] SAVECTR c[i] POPCTR。 | 26 |
EDAi | c[i] SAVEc[i] SAVECTR | 将 c(i) 的当前值保存到 continuation c0 的 savelist 中。如果 c0 的 savelist 中已存在 c[i] 的条目,则不做任何操作。等同于 c[i] PUSHCTR c[i] SETRETCTR。 | 26 | |
EDBi | c[i] SAVEALTc[i] SAVEALTCTR | 类似于 c[i] SAVE,但将 c[i] 的当前值保存到 c1(而不是 c0)的 savelist 中。 | 26 | |
EDCi | c[i] SAVEBOTHc[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 | COMPOSBOOLAND | c c' - c'' | 计算组合 compose0(c, c’),它的意义为“执行 c,如果成功,执行 c'”(如果 c 是布尔电路)或简单地“执行 c,然后执行 c'”。等同于 SWAP c0 SETCONT。 | 26 |
EDF1 | COMPOSALTBOOLOR | 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。 |