文档/进阶/嵌入式使用

嵌入式使用

在 Java/Kotlin 项目中嵌入 NovaLang

嵌入式使用

NovaLang 可以轻松嵌入到 Java/Kotlin 项目中,作为规则引擎、配置脚本或扩展系统使用。

添加依赖

// Gradle
implementation 'com.novalang:nova-runtime:0.1.1'

// JSR-223 支持 (可选)
implementation 'com.novalang:nova-script:0.1.1'

方式一:Nova 便捷 API(推荐)

import nova.runtime.Nova;

Nova nova = new Nova();

// 执行代码
nova.eval("println(\"Hello from Nova!\")");

// 注入变量
nova.set("name", "Alice");
nova.set("scores", Arrays.asList(90, 85, 92));
nova.eval("println(\"$name 的成绩: $scores\")");

// 读取结果
nova.eval("val result = 1 + 2");
int result = nova.get("result", int.class);  // 3

// 调用 Nova 函数
nova.eval("fun add(a: Int, b: Int): Int = a + b");
int sum = nova.call("add", int.class, 10, 20);  // 30

Builder DSL API

通过 Receiver Lambda 实现 Kotlin 风格的 DSL builder:

// 定义 builder 函数
nova.defineBuilderFunction("serverConfig", ServerConfig::new, config -> {
    config.validate();
    return config;
});

Nova 脚本侧使用:

val cfg = serverConfig {
    host = "0.0.0.0"
    port = 8080
}
println(cfg.host)  // 0.0.0.0

以接收者调用 Nova lambda:

// 获取 Nova 中定义的 lambda
Object block = nova.get("myBlock");

// 以 receiver 调用,block 内可直接访问 receiver 的属性和方法
nova.invokeWithReceiver(block, receiver);

方式二:JSR-223 ScriptEngine

通过标准 javax.script API,支持引擎可替换:

import javax.script.*;

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nova");

// 执行
Object result = engine.eval("1 + 2");  // 3

// 变量绑定
engine.put("name", "Alice");
engine.eval("println(\"Hello, $name!\")");
String name = (String) engine.get("name");

// 预编译
Compilable compilable = (Compilable) engine;
CompiledScript compiled = compilable.compile("n * n + 1");
engine.put("n", 7);
System.out.println(compiled.eval());  // 50

注册自定义函数

@NovaFunc 注解批量注册

import nova.runtime.interpreter.NovaFunc;

public class MathUtils {
    @NovaFunc("square")
    public static int square(int x) {
        return x * x;
    }

    @NovaFunc("clamp")
    public static double clamp(double value, double min, double max) {
        return Math.max(min, Math.min(max, value));
    }
}

// 注册
Nova nova = new Nova();
nova.getInterpreter().registerAll(MathUtils.class);
nova.eval("println(square(5))");  // 25

NovaNativeFunction

import nova.runtime.interpreter.*;

NovaNativeFunction greet = NovaNativeFunction.create("greet",
    (name) -> new NovaString("Hello, " + name.asString() + "!")
);

nova.getInterpreter().getGlobals().defineVal("greet", greet);
nova.eval("println(greet(\"Nova\"))");  // Hello, Nova!

安全策略

嵌入式场景下通过安全策略限制脚本行为:

import nova.runtime.interpreter.NovaSecurityPolicy;

// 预定义级别
Nova nova = new Nova(NovaSecurityPolicy.strict());

// 自定义策略
NovaSecurityPolicy policy = NovaSecurityPolicy.custom()
    .allowJavaInterop(true)
    .allowPackage("java.util")
    .allowPackage("java.math")
    .denyClass("java.lang.Runtime")
    .denyMethod("java.lang.System", "exit")
    .maxExecutionTime(5000)
    .maxRecursionDepth(128)
    .build();
Nova nova = new Nova(policy);

类型转换

Java 和 Nova 之间的值自动双向转换。NovaValue 提供类型安全的 toJava() 方法:

NovaValue result = interpreter.eval("1 + 2");
int safe = result.toJava(int.class);
String s = result.toJava(String.class);