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_0000LTRUE和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-ddnow.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,
