josie-core
Core runtime for JOSIE: Josie Omni Secure Interactive Expressions.
josie-core is the execution engine used by josie-web, josie-cli, and host apps that embed JOSIE.
What this crate gives you
- Deterministic expression evaluation
- Program/pipeline parsing and execution
- Lisp-style JOSIE input (recommended authoring format)
- JSON tree/program input (canonical machine format)
- Built-in kernel operators +
util.* + data.*
- Host extension points via custom operators
Recommended authoring style
Use JOSIE Lisp (.josie) for writing by hand.
Use JSON trees/program docs for generated or interoperable payloads.
Quickstart (Lisp-first)
use josie_core::program::{execute_program, parse_program};
use josie_core::{read_program, Operators};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let src = r#"
(set client.name "JOSIE")
(set client.msg (util.concat "Hello, " client.name))
client.msg
"#;
let doc = read_program(src)?; let program = parse_program(&doc)?; let out = execute_program(&program, &Operators::new())?;
println!("{}", out.value); Ok(())
}
JSON program format (canonical)
use josie_core::program::{execute_program, parse_program};
use josie_core::Operators;
use serde_json::json;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let doc = json!({
"state": { "client": {}, "server": {} },
"program": ["do",
["set", "client.a", 10],
["set", "client.b", 20],
["+", ["var", "client.a"], ["var", "client.b"]]
]
});
let program = parse_program(&doc)?;
let out = execute_program(&program, &Operators::new())?;
assert_eq!(out.value, json!(30.0));
Ok(())
}
Example: function + recursion (Lisp)
(def fib (n)
(if (<= n 1)
n
(+ (call fib (- n 1))
(call fib (- n 2)))))
(call fib 10)
You can run this through read_program -> parse_program -> execute_program.
Example: data wrangling (Lisp)
(set server.rows [
{region: "APAC" amount: 120}
{region: "EU" amount: 80}
{region: "APAC" amount: 30}
])
(set server.grouped
(data.group_by server.rows ["region"]))
(set server.summary
(data.aggregate server.grouped {
n: "count(*)"
total: "sum(amount)"
}))
(data.sort_by server.summary [{col: "total" dir: "desc"}])
Example: backend response shaping (Lisp)
(set server.response {
name: "people.index"
properties: {
totalCount: (len server.people)
people: (map server.people {
id: item.id
displayName: item.name
tags: item.tags
})
}
})
Host extension (x.*) example
use josie_core::{Context, EvalResult, Operator, Operators, State, evaluate};
use serde_json::{json, Value};
fn op_x_echo(args: &[Value], _ctx: &mut Context) -> EvalResult {
Ok(args.first().cloned().unwrap_or(Value::Null))
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut ops = Operators::new();
ops.register("x.echo", op_x_echo as Operator);
let expr = json!(["x.echo", {"ok": true}]);
let mut state = State::new();
let mut ctx = Context { state: &mut state, operators: &ops, event: None };
let out = evaluate(&expr, &mut ctx)?;
assert_eq!(out, json!({"ok": true}));
Ok(())
}
Program interfaces you will use most
read_program(&str) for Lisp input
parse_program(&Value) for validated program doc
execute_program(&Program, &Operators) one-shot execute
compile_program(&Program) + execute_compiled_program(...) for reuse
execute_program_with_hosts(...) when host callbacks are involved
Operator families
- kernel:
var, set, if, do, pipe, def, call, arithmetic/comparison/boolean ops
- collection:
map, filter, len, push
- util.*: strings, normalization, paths, regex, casting helpers
- data.*: select/rename/cast/chunk/flat_map/distinct/sort/group/aggregate/join
Safety model
- No implicit filesystem/network access in core runtime
- Side effects only through explicit operators/host integrations
- Host app controls what custom operators are exposed
Publish (crates.io)
Run from this crate folder:
cd /Users/mala0061/Dev/mecha.id/juice-lang/josie-rs/crates/josie-core
cargo publish
Or from workspace root:
cargo publish -p josie-core
Links