B4.执行引擎
B4.执行引擎
其中各引擎
的实现和执行上下文是不一样的,即变量作用域不一样,存在以下2个级别,
session
级,一次merge内的多次eval,同一context,eval间有影响,如js
。nothing
级,每次eval的上下文无关联,eval间无影响,如sh
依赖于bash设置。
执行中的引擎环境,在每次eval时,可以被context覆盖,也可以不覆盖,依赖于引擎实现。
B4.1.字典引擎map
session
级,每次eval共享context,context不覆盖引擎环境。
- 以
功能体
为参数
(key
),依次查找,找到非null
即返回 - 顺序为context,System.property,System.env,Builtin
key
中不可包含管道符|
,或使用\
转义key
中的引号'"
作为变量边界,或使用\
转义。- 转义如
\t
,\r
,\n
,此外仅保留\
后字符。
1a.以句点分隔的导航类对象
支持简单的导航类
对象,即key中以.
分隔对象,会存在以下干扰情况,
- java的System中有大量
.
型变量,如os.name
,user.home
- 如果用户存有
os
或user
,使用.
导航,则会发生混乱
因为有.
分隔的字符串变量存在,所以在各实现引擎中对环境变量的使用,遵循以下规则。
存入(put)时,尽量保证读取时,以整key和对象导航方式都可正确读取。
- 必须以整key存入。
- 可以
.
分隔,逐级存入分段的key(map引擎未实现)
读取(get)时,优先使用整key读取,不存在则使用对象导航形式读取。
- 以key直接查找,有
非null
值,则return - 如key中存在
:
,如out:it:name
分隔为out
,it
和name
- 依次以
out
和it
为对象key递归查找对象。- 若为任意递归中返回null,则return
字符串空
。 - 若为Map类型,则以getKey的方式取值。
- 其他类型,通过反射取值,以Getter命名规则和Field查找。
- 若为任意递归中返回null,则return
- 递归中的最终对象,以
name
为key取值(map或反射)
1b.管道符链接函数,链式处理
可以用|
分隔多个处理函数,第一个为key,其后的都是函数
,格式下。
key
|
funA
|
funB arg1 "arg 2"
以上等同于调用链,funB(ctx, funA(ctx.get("key")), "arg1", "arg 2")
key
- 字符串key,可以是.
的对象导航格式。- key对应的值可以是
Object
,Supplier<Object>
或fun arg
。
- key对应的值可以是
fun
- 管道语法的第一个字符串- 必须
Function
或JavaEval
类型 - 函数名字,不用使用
.
,建议以fun:
开头 - Function.apply(obj),obj为管道输出或
key
或arg
- JavaEval.eval(ctx, obj, arg...);
- 必须
arg
- 用户定义的变量,即管道语法的第二个参数起。- arg默认类型为字符串,可使用引号(
"
或'
)括起来 - 若arg中需要保留空格,需要引号括起来,其内的引号用
\
转义。 - 数值类型,可
,_
分隔数字,^([-+])?([0-9_,.]+)([DFNL]?)$
1,000
,1_0000
,10,000.0
,1_0000.00
(Integer或Float)- 可分别使用后缀,表示具体类型BigDecimal(N),Double(D), Float(F),Long(L)
1,000.00D
,1_0000.00F
,1_0000N
,1_0000L
TRUE
和FALSE
表示boolean类型,要表达字符串需要引号括起来- 不支持科学记数法
- arg默认类型为字符串,可使用引号(
函数,可以通过以下3中方式设置,
- RnaManager全局注册,如内置
变量
或方法 - merger时存入context中注册,如java的lambda
- 可以通过
RNA:PUT
指令fun
引擎,动态编译注册 - 注册的方法名,必须以
fun:
为前缀,以避免与其他变量冲突 - 使用时,
fun:
可以省略,也建议省略。
内置函数列表,参考函数列表
1c.内置以下变量
米波内置了很少的变量和方法,以下是java system.property和env的举例
user.name
- String, 当前系统用户,java内置user.dir
- String, 当前的工作目录,java内置
以下是,内置日期和时间的变量
now.date
- String:Supplier, 动态计算,系统日期yyyy-MM-dd
now.time
- String:Supplier, 动态计算,系统时间HH:mm:ss
B4.2.来啥回啥raw
nothing
级,直接把功能体
当字符串返回,但mute时返回字符串空
。
B4.3.内容引入uri
nothing
级,把uri的内容以UTF8输出为字符串。首次读入,后续缓存。 注意,仅作为String类型,不会做任何解析和动态执行。
http://
,https://
时,以GET读取file://
时,从file system读取classpath:
时,从classloader读入,注意没有//
- 其他,以URLConnection读取,超时为3秒
- 以
/
或.
开头,在程序pwd为相对路径,但不建议使用。 - 读入的内容,会以uri为key,缓存到context中
B4.4.直接执行exe
nothing
级,解析引号块和转义,捕获std_out输出。 注意的是,每次eval时,engine会用context覆盖环境变量。
exe
- 直接执行命令。cmd
- 在window系,以cmd /c
执行。sh
- 在unx系,以bash -c
执行。
B4.5.执行js脚本js
session
级,以java的ScriptEngine执行js脚本,捕获最后一个求值。 执行context,以ctx
对象存在于js环境,可以通过ctx.xxx
获得环境变量。
对于在context读入和写入导航类
对象,参考map引擎的规则。
注意: Java 15 removed Nashorn JavaScript Engine
B4.6.动态java代码java
session
级,通过米波模板动态编译java代码,并以context为参加执行。
- 头部
import java.util.*,java.util.Map;
,可以,
分隔多个 - 简单方法体单行(java不能简单),复杂的多行,以增加可读性。
- 尾部以
return obj
返回,;
可以省略。 - 通过Java模板动态编译java。
- 编译的java实现了
pro.fessional.meepo.eval.JavaEval
接口 - 传入
RngContext ctx
,可读取context - 已经import的class有,
- org.jetbrains.annotations.NotNull;
- pro.fessional.meepo.poof.impl.JavaEngine;
- java.util.Map;
B4.7.动态java函数fun
可以通过以下方式,灵活的将自定义java函数注册到模板引擎。但不建议在模板中使用函数,模板应该只负责显示。
- 模板内动态编译java代码,并
PUT fun/
,供USE
执行。 - 通过
RnaManager.register
全局注册函数 - 在context的Map中,put以
fun:
前缀的java函数 - 运行时注册的函数,一般是Function或JavaEval类型的lambda,