评估器
Liquor Java 语言评估器。支持完整的 Java 语法及各版本特性(具体看运行时版本)。评估器由“三个”关键类及两个工具组成:
部件 | 描述 |
---|---|
CodeSpec | 代码申明 |
LiquorEvaluator | 评估器。用于管理 CodeSpec 的编译、缓存 |
Execable | 可执行接口。由 CodeSpec 编译后会产生 |
::Scripts | 评估器的脚本工具 |
::Exprs | 评估器的表达式工具 |
1、CodeSpec 类结构及编译效果
字段 | 描述 |
---|---|
code | 申明代码(一般包含,代码头?和代码主体!) |
imports | 申明类头导入 |
parameters | 申明参数 |
returnType | 申明返回类型 |
cached | 申明缓存的(默认为 true)。当代码无限变化时,不能用缓存(否则有 OOM 风险) |
CodeSpec 会被编译成一个静态函数(并转换为 Execable)。格式效果如下:
#imports#
public class Execable$... {
public static #returnType# _main$(#parameters#) {
#code#
}
}
其中 #imports#
,由三部分组成:
LiquorEvaluator:globalImports
(一般不用,避免产生相互干扰。特殊定制时可用)CodeSpec:imports
code:header-imports
(代码头部的 import 语句)
其中 CodeSpec:code
+ CodeSpec:imports
会形成:
- 缓存键,用于缓存控制
2、LiquorEvaluator 接口及 eval 过程分解(使用时以 Scripts 和 Exprs 为主)
方法列表:
方法 | 描述 |
---|---|
printable(bool) | 配置可打印的 |
compile(codeSpec) | 预编译 |
eval(codeSpec, args) | 评估 |
eval 过程分解:
3、Exprs 代码展示(Scripts 类似)
也可以定制特定业务的体验工具。比如,Exprs 在接收 CodeSpec 时会自动申明 returnType。
public interface Exprs {
static Execable compile(String code) {
return compile(new CodeSpec(code));
}
static Execable compile(CodeSpec codeSpec) {
//强制有估评结果
if (codeSpec.getReturnType() == null) {
codeSpec.returnType(Object.class);
}
return LiquorEvaluator.getInstance().compile(codeSpec);
}
static Object eval(String code) throws InvocationTargetException {
return eval(new CodeSpec(code));
}
static Object eval(CodeSpec codeSpec, Object... args) throws InvocationTargetException {
//强制有估评结果
if (codeSpec.getReturnType() == null) {
codeSpec.returnType(Object.class);
}
return LiquorEvaluator.getInstance().eval(codeSpec, args);
}
static Object eval(String code, Map<String, Object> context) throws InvocationTargetException {
assert context != null;
ParamSpec[] parameters = new ParamSpec[context.size()];
Object[] args = new Object[context.size()];
int idx = 0;
for (Map.Entry<String, Object> entry : context.entrySet()) {
parameters[idx] = new ParamSpec(entry.getKey(), entry.getValue().getClass());
args[idx] = entry.getValue();
idx++;
}
return eval(new CodeSpec(code).parameters(parameters), args);
}
}