Files
paradigms/javascript/jstest/JSExpressionEngine.java
2026-04-08 21:25:17 +03:00

67 lines
2.0 KiB
Java

package jstest;
import common.Engine;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
* Expression-aware JavaScript engine.
*
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
*/
public class JSExpressionEngine implements Engine<Object> {
private final JSEngine engine;
private final String evaluate;
private final String parse;
private final String toString;
public JSExpressionEngine(final Path script, final String evaluate, final String parse, final String toString) {
engine = new JSEngine(script);
this.evaluate = evaluate;
this.parse = parse;
this.toString = toString;
}
@Override
public Result<Object> prepare(final String expression) {
return parse("eval", expression);
}
@Override
public Result<Object> parse(final String expression) {
return parse(parse, expression);
}
private Result<Object> parse(final String parse, final String expression) {
return engine.eval(expression, "%s(\"%s\")".formatted(parse, expression), Object.class);
}
@Override
public Result<Number> evaluate(final Result<Object> prepared, final double[] vars) {
final String code = "expr%s(%s);".formatted(
evaluate,
Arrays.stream(vars).mapToObj("%.20f"::formatted).collect(Collectors.joining(","))
);
return evaluate(prepared, code, Number.class);
}
public Result<String> toString(final Result<Object> prepared) {
return evaluate(prepared, "expr." + toString + "()", String.class);
}
protected <T> Engine.Result<T> evaluate(
final Engine.Result<Object> prepared,
final String code,
final Class<T> result
) {
engine.set("expr", prepared);
return engine.eval(
"%n in %s%n where expr = %s%n".formatted(code, prepared.context()),
code,
result
);
}
}