| id | instruction |
|---|---|
| sidebar_position | 6 |
| title | 8.6 QIL 指令参考 |
| description | DataQL 引擎,QIL 指令集、构造指令、存储指令、结束指令、运算指令、控制指令、函数指令、辅助指令 |
QIL 是 DataQL 的编译结果。普通查询通过 Query 执行,需要分析编译结果时可查阅本页指令;编译入口见独立使用。
| 助记符 | 指令代码 | 含义 |
|---|---|---|
| 构造指令 | ||
LDC_D |
11 | 将数字压入栈(例:LDC_D 12345) |
LDC_B |
12 | 将布尔数据压入栈(例:INSN_B true) |
LDC_S |
13 | 将字符串数据压入栈(例:LDC_S “ssssss”) |
LDC_N |
14 | 将null压入栈(例:INSN_N) |
NEW_O |
15 | 构造一个键值对对象并压入栈 |
NEW_A |
16 | 构造一个集合对象并压入栈 |
| 存储指令 | ||
STORE |
21 | 栈顶数据存储到堆(例:STORE,2) |
LOAD |
22 | 从指定深度的堆中加载n号元素到栈(例:LOAD 1 ,1 ) |
GET |
23 | 获取栈顶对象元素的属性(例:GET,”xxxx”) |
PUT |
24 | 将栈顶对象元素放入对象元素中(例:GET,”xxxx”) |
PULL |
25 | 获取集合的指定索引元素。(例:PULL 123) |
PUSH |
26 | 将栈顶元素压入集合(例:PUSH) |
| 结束指令 | ||
EXIT |
31 | 结束所有指令序列的执行并返回数据和状态 |
RETURN |
32 | 结束当前指令序列的执行,并返回数据和状态给上一个指令序列。 |
THROW |
33 | 结束所有指令序列的执行,并抛出异常 |
| 运算指令 | ||
UO |
41 | 一元运算 |
DO |
42 | 二元运算,堆栈结构:【第一个操作数,第二个操作数】 |
TYPEOF |
43 | 计算值的类(string、number、boolean、object、list、udf、null) |
| 控制指令 | ||
IF |
51 | 如果条件判断失败那么 GOTO 到指定位置,否则继续往下执行 |
GOTO |
52 | 执行跳转 |
CAST_I |
53 | 将栈顶元素转换为迭代器 |
CAST_O |
54 | 将栈顶元素转换为一个对象,如果是集合那么取第一条记录 |
E_PUSH |
55 | 取出当前栈顶数据,并压入环境栈 |
E_POP |
56 | 丢弃环境栈顶的元素 |
E_LOAD |
57 | 加载环境栈顶的数据到数据栈 |
LOAD_C |
58 | 加载自定义路由 |
POP |
59 | 丢弃栈顶数据 |
| 函数指令 | ||
CALL |
61 | 发起服务调用(例:CALL,2) |
M_DEF |
62 | 函数定义,将栈顶元素转换为 UDF |
M_REF |
63 | 引用另一处的指令序列地址,并将其作为 UDF 形态存放到栈顶 |
M_TYP |
64 | 加载一个类型对象到栈顶,该类型是一个有效的 UDF。 |
M_FRAG |
65 | 引用外部片段执行器,并将其作为 UDF 形态存放到栈顶 |
LOCAL |
66 | 将入参存入堆,也用于标记变量名称 |
| 辅助指令 | ||
HINT |
71 | 设置 Hint,影响执行引擎的参数选项。 |
LABEL |
72 | 协助GOTO定位用,无实际作用 |
LINE |
73 | 行号,无实际作用 |
定义数字,将数字压入栈(例:LDC_D 12345)
- 参数说明:共 1 参数;参数 1:数据;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return 134
指令:
#00 LDC_D 134
#01 RETURN 0
定义布尔,将布尔数据压入栈(例:LDC_B true)
- 参数说明:共 1 参数;参数 1:数据;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return true
指令:
#00 LDC_B true
#01 RETURN 0
定义字符串,将字符串数据压入栈(例:LDC_S "ssssss")
- 参数说明:共 1 参数;参数 1:数据;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return "ssss"
指令:
#00 LDC_S ssss
#01 RETURN 0
定义 NULL,将 null 压入栈(例:LDC_N)
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return null
指令:
#00 LDC_N
#01 RETURN 0
定义对象,构造一个键值对对象并压入栈
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码1:return {}
指令1:
#00 NEW_O
#01 RETURN 0
代码2:return {'field_1':'f1','field_2':'f2'}
指令2:
#0 NEW_O
...(部分略)...
#5 RETURN 0
定义集合,构造一个集合对象并压入栈
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码1:return []
指令1:
#00 NEW_A
#01 RETURN 0
代码2:return [1,2,3]
指令2:
#0 NEW_A
...(部分略)...
#7 RETURN 0
堆保存操作,栈顶数据存储到堆(例:STORE,2)
- 参数说明:共 1 参数;参数 1 :存入堆的位置;
- 栈行为:消费 1,产出 0
- 堆行为:存入数据
代码:var a = 123 ; return a
指令:
#0 LDC_D 123
#1 STORE 0
#2 LOAD 0, 0
#3 RETURN 0
堆读取操作,从指定深度的堆中加载n号元素到栈(例:LOAD 1 ,1 )
- 参数说明:共 2 参数;参数 1:堆深度(栈顶深度为 0);参数 2:元素序号;
- 栈行为:消费 0,产出 1
- 堆行为:取出数据(不删除)
代码:var a = 123 ; return a
指令:
#0 LDC_D 123
#1 STORE 0
#2 LOAD 0, 0
#3 RETURN 0
从对象中读取数据,获取栈顶对象元素的属性(例:GET,"xxxx")
- 参数说明:共 1 参数;参数 1:属性名称(Map 的 Key 或 对象的属性名)
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:var a = {'abc':true} ; return a.abc
指令: ...(部分略)...
#4 LOAD 0, 0
#5 GET abc
#6 RETURN 0
向对象写入数据,将栈顶对象元素放入对象元素中(例:PUT,"xxxx")
- 参数说明:共 1 参数;参数 1:属性名称(Map 的 Key 或 对象的属性名)
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:return {'field_1':'f1','field_2':'f2'}
指令:
#0 NEW_O
#1 LDC_S f1
#2 PUT field_1
#3 LDC_S f2
#4 PUT field_2
#5 RETURN 0
从集合中获取数据,栈顶元素是一个集合类型,获取集合的指定索引元素。(例:PULL 123)
- 参数说明:共 1 参数;参数 1:元素位置(负数表示从后向前,正数表示从前向后)
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:var a = [1,2,3,4,5] ; return a指令:
...(部分略)...
#11 STORE 0
#12 LOAD 0, 0
#13 PULL 2
#14 RETURN 0
向对象中写入数据,将栈顶元素压入集合(例:PUSH)
- 参数说明:共 0 参数;
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:return [1,2,3]
指令:
...(部分略)...
#1 LDC_D 1
#2 PUSH
#3 LDC_D 2
#4 PUSH
...(部分略)...
将栈顶的元素 Copy 一个(浅拷贝)
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return abc[a]
指令:
[0]
#000 E_LOAD #
#001 GET abc
#002 E_LOAD #
#003 GET a
#004 COPY
#005 TYPEOF
#006 COPY
#007 LDC_S string
#008 DO ==
...(部分略)...
终止所有后续指令的执行并正常退出。结束所有指令序,执行并返回数据和状态
- 参数说明:共 1 参数;参数 1:退出码
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:exit 123 , []
指令:
#0 NEW_A
#1 EXIT 123
终止当前指令序列的执行并正常退出。结束当前指令序列的执行,并返回数据和状态给上一个指令序列。如果没有上一个指令序列那么结束整个查询
- 参数说明:共 1 参数;参数 1:返回码
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:return 123 , []
指令:
#0 NEW_A
#1 RETURN 123
终止所有后续指令的执行并抛出异常。结束所有指令序列的执行,并抛出异常
- 参数说明:共 1 参数;参数 1:错误码
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:throw 123 , []
指令:
#0 NEW_A
#1 THROW 123
一元运算。一元操作符有:"!" 对 boolean 值进行取反,"-",对 number 值取相反值。
- 参数说明:共 1 参数;参数 1:一元操作符
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:return -(-1)
指令:
#0 LDC_D -1
#1 UO -
#2 RETURN 0
二元运算。堆栈【第一个操作数,第二个操作数】支持的运算参考 语法 -> 运算符
- 参数说明:共 1 参数;参数 1:二元操作符
- 栈行为:消费 2,产出 1
- 堆行为:无
代码:return 1 + 2
指令:
#0 LDC_D 1
#1 LDC_D 2
#2 DO +
#3 RETURN 0
计算堆栈顶元素的类型
- 参数说明:共 1 参数;参数 1:二元操作符
- 栈行为:消费 1,产出 1
- 堆行为:无
产出的数据类型为字符产,取值如下表:
| 类型字符 | 含义 |
|---|---|
string |
通过 typeOf 计算得到的类型是 字符串。 |
number |
通过 typeOf 计算得到的类型是 数字。 |
boolean |
通过 typeOf 计算得到的类型是 布尔值。 |
vobject |
通过 typeOf 计算得到的类型是 对象。 |
list |
通过 typeOf 计算得到的类型是 集合。 |
udf |
通过 typeOf 计算得到的类型是 Udf 或 Lambda函数。 |
null |
通过 typeOf 计算得到的类型是 NULL 或 不存在这个属性。 |
代码:return abc[a]
指令:
[0]
#000 E_LOAD #
#001 GET abc
#002 E_LOAD #
#003 GET a
#004 COPY
#005 TYPEOF
#006 COPY
#007 LDC_S string
...
条件判断。如果条件判断失败那么 GOTO 到指定位置,否则继续往下执行
- 参数说明:共 1 参数;参数 1:GOTO 的位置
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:if (1 == 1) return true; else return false
指令:
...(部分略)...
#02 DO ==
#03 IF 7 <- 如果判断失败那么跳转到 #07 行指令
...(部分略)...
#07 LABEL 7 <- LABEL 7 之后的相当于 else 部分
...(部分略)...
执行跳转,指令执行序列指针跳转,DataQL 语言本身并不支持 goto 语句。goto 的产生会在 if/数组类型结果转换时产生。
- 参数说明:共 1 参数;参数 1:GOTO 的位置
- 栈行为:消费 0,产出 0
- 堆行为:无
代码:if (1 == 1) return true; else return false
指令:
...(部分略)...
#06 GOTO 11 <- 通常 goto 会跳转到一个 LABEL 指令上
...(部分略)...
#11 LABEL 11
类型转换指令(转换为迭代器)。将栈顶元素转换为迭代器,作为迭代器有三个特殊操作:data(数据)、next(移动到下一个,如果成功返回true)
- 参数说明:共 0 参数
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:return a => [ field1 ]
指令:
...(部分略)...
#01 GET a
#02 CAST_I
#03 E_PUSH
...(部分略)...
类型转换指令(转换为对象),将栈顶元素转换为一个对象,如果是集合那么取第一条记录(可以通过 CAST_I 方式解决,但会多消耗大约8条左右的指令)
- 参数说明:共 0 参数
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:return a => { 'field1','field2' }
指令:
...(部分略)...
#01 GET a
#02 CAST_O
#03 E_PUSH
...(部分略)...
加载用户数据集,通过 CustomizeScope 接口获取用户数据集
- 参数说明:共 1 参数;参数 1:@#$ 符号之一
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:return ${a}.b
指令:
#0 LOAD_C $ <- 可能的符号参数有三个"@#$",例如:${a} 产生 $,#{a} 产生 #
#1 GET a
#2 GET b
#3 RETURN 0
丢弃栈顶数据。丢弃栈顶数据,该指令目前在编译结果转换时会通过转换语句优化产生,平常语句不会编译出该指令。
- 参数说明:共 0 参数;
- 栈行为:消费 1,产出 0
- 堆行为:无
代码:return a => []
指令:
#0 E_LOAD #
#1 GET a
#2 POP
#3 NEW_A
#4 RETURN 0
数据交换到环境栈。取出当前栈顶数据,并压入环境栈。通常和 CAST_I 与 CAST_O 联合出现,每一个 E_PUSH 都会存在一个对应的 E_POP。
- 参数说明:共 0 参数;
- 栈行为:消费 1,产出 0
- 环境栈行为:消费 0,产出 1
- 堆行为:无
代码:return a => { 'field1','field2' }
指令:
...(部分略)...
#01 GET a
#02 CAST_O
#03 E_PUSH
...(部分略)...
#11 E_POP
#12 RETURN 0
丢弃环境栈元素。
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 0
- 环境栈行为:消费 1,产出 0
- 堆行为:无
代码:return a => [ field1 ]
指令:
...(部分略)...
#01 GET a
#02 CAST_I
#03 E_PUSH
...(部分略)...
#18 E_POP
#19 RETURN 0
数据从环境栈交换到数据栈,加载环境栈顶的数据到数据栈,一个有效的 E_LOAD 前面肯定会有一个 E_PUSH;除此之外E_LOAD也有单独出现的时候,但通常都不具备运行上的任何意义。 例如:"return a => []" 的编译结果中的 E_LOAD 就拿不到任何数据,除了编译毫无任何意义。因为根层的 E_LOAD 数据肯定是空的。
- 参数说明:共 1 参数;参数 1:操作符号 @#$
- 栈行为:消费 0,产出 1
- 环境栈行为:消费 0,产出 0
- 堆行为:无
代码:return a => { 'field1','field2' }
指令:
...(部分略)...
#03 E_PUSH
#04 NEW_O
#05 E_LOAD #
#06 GET field1
#07 PUT field1
...(部分略)...
发起 UDF 调用。发起服务调用(例:CALL,2)
- 参数说明:共 1 参数;参数 1:发起调用时需要用到的调用参数个数 n
- 栈行为:消费:n + 1(n是参数,1 是函数入口),产出 1
- 堆行为:无
代码:return abs(-1)
指令:
...(部分略)...
#2 M_DEF
#3 LDC_D -1
#4 CALL 1 <- 在 CALL 发起函数调用之前通常会有 M_DEF、M_TYP、M_REF 三种之一的函数定义行为。
...(部分略)...
函数定义,将栈顶元素转换为 UDF
- 参数说明:共 0 参数;
- 栈行为:消费 1,产出 1
- 堆行为:无
代码:return abs(-1)
指令:
#0 E_LOAD #
#1 GET abs
#2 M_DEF <= 前面 GET 出来的 abs 定义为函数
...(部分略)...
加载一个对象到栈顶。通过 Finder 的 findBean 方法加载一个对象到栈顶。一般情况下对应的操作是 import。
- 参数说明:共 1 参数;参数为要加载的 Bean 名
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:import 'net.hasor.test.dataql.udfs.DemoUdf' as foo; return foo().name
指令:
#0 M_TYP net.hasor.test.dataql.udfs.DemoUdf
#1 STORE 0
#2 LOAD 0, 0
#3 M_DEF
#4 CALL 0
...(部分略)...
加载代码执行片段执行器,片段执行器允许通过扩展方式集成一个非 DataQL 语法的脚本块。
- 参数说明:共 1 参数;参数 1:片段类型
- 栈行为:消费 0,产出 1
- 堆行为:无
[1]
...(部分略)...
#03 M_FRAG sql <- 加载类型为 sql 的外部片段执行器。
#04 LOAD 0, 0
...(部分略)...
将指令序列作为函数。引用另一处的指令序列地址,并将其作为 UDF 形态存放到栈顶。lambda 被调用的开始会像栈顶放入一个入参数组。
- 参数说明:共 1 参数;参数 1:内置 lambda 函数的入口地址
- 栈行为:消费 0,产出 1
- 堆行为:无
代码:var foo = () -> return {"name" : true}; return foo().name
指令:
[0]
#0 M_REF 1 <- 引用 [1] 指令序列作为函数
#1 STORE 0
#2 LOAD 0, 0
#3 M_DEF
#4 CALL 0
...(部分略)...
[1]
...(部分略)...
参数入堆。将入参存入堆,也用于标记变量名称。
- 参数说明:共 3 参数;参数 1:调用时的入参位置;参数 2:存储到堆中的位置;参数3:参数名助记符;
- 栈行为:消费 0,产出 0
- 堆行为:存入数据
代码:var foo = (a,b,c) -> return {"name" : a}; return foo().name
指令:
[0]
...(部分略)...
[1]
#0 LOCAL 0, 0, a
#1 LOCAL 1, 1, b
#2 LOCAL 2, 2, c
...(部分略)...
设置 Hint,影响执行引擎的参数选项。
- 参数说明:共 2 参数;参数 1:选项Key;参数 2:选项Value
- 栈行为:消费 2,产出 0
- 堆行为:无
代码:hint a = 'abc' return 1
指令:
#0 LDC_S a
#1 LDC_S abc
#2 HINT
...(部分略)...
协助GOTO定位用,无实际作用
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 0
- 堆行为:无
代码:if (1 == 1) return true; else return false
指令:
...(部分略)...
#02 DO ==
#03 IF 7 <- 如果判断失败那么跳转到 #07 行指令
...(部分略)...
#07 LABEL 7 <- LABEL 7 之后的相当于 else 部分
...(部分略)...
行号,无实际作用
- 参数说明:共 0 参数;
- 栈行为:消费 0,产出 0
- 堆行为:无