///|
fn option(
args : Array[String],
name : String,
) -> String raise @types.EngineError {
for i, arg in args {
if arg == name && i + 1 < args.length() {
return args[i + 1]
}
}
raise @types.fail("E_CLI_ARGUMENT", "missing " + name)
}
///|
fn run(args : Array[String]) -> Unit raise Error {
if args.length() < 3 {
raise @types.fail(
"E_CLI_USAGE", "usage: moondmn feel [--context file] [--now ISO-datetime] | eval --decision name --input file | lint | tck [--json out]",
)
}
let clock = if args.contains("--now") {
let fixed = @types.parse_datetime(option(args, "--now"))
Some(fn() { fixed })
} else {
None
}
match args[1] {
"lint" =>
println(
@model.lint(@lib.parse_model(@fs.read_file_to_string(args[2]))).stringify(
indent=2,
),
)
"tck" => {
let report = @tck.run(args[2]).stringify(indent=2)
if args.contains("--json") {
@fs.write_string_to_file(option(args, "--json"), report)
} else {
println(report)
}
}
"feel" => {
let context = if args.contains("--context") {
@fs.read_file_to_string(option(args, "--context"))
} else {
"{}"
}
println(@lib.feel_eval(args[2], context~, clock~))
}
"eval" => {
let model = @lib.parse_model(@fs.read_file_to_string(args[2]))
println(
@lib.evaluate_decision(
model,
option(args, "--decision"),
@fs.read_file_to_string(option(args, "--input")),
clock~,
),
)
}
_ => raise @types.fail("E_CLI_USAGE", "unknown command")
}
}
///|
fn main {
run(@env.args()) catch {
@types.Failure(code, line, column, message) => {
println(
Json::object(
Map([
("error", Json(code)),
("line", Json(line)),
("column", Json(column)),
("message", Json(message)),
]),
).stringify(),
)
@sys.exit(1)
}
e => {
println(
Json::object(
Map([("error", Json("E_IO")), ("message", Json(e.to_string()))]),
).stringify(),
)
@sys.exit(1)
}
}
}