| Crates.io | lemma-engine |
| lib.rs | lemma-engine |
| version | 0.7.2 |
| created_at | 2025-10-19 18:05:55.669044+00 |
| updated_at | 2026-01-25 20:25:56.858563+00 |
| description | A language that means business. |
| homepage | https://github.com/benrogmans/lemma |
| repository | https://github.com/benrogmans/lemma |
| max_upload_size | |
| id | 1890726 |
| size | 1,447,062 |
A language that means business.
Lemma Engine is the Rust crate behind the Lemma language. It lets you parse, validate, and evaluate Lemma docs from your own applications while keeping the same natural, auditable semantics that the CLI exposes.
Lemma is still early-stage and not yet recommended for production use. Expect breaking changes, evolving semantics, and incomplete tooling while the project matures.
Add the crate:
[dependencies]
lemma-engine = "0.7.2"
use lemma::Engine;
let mut engine = Engine::new();
engine.add_lemma_code(r#"
doc compensation
fact base_salary = 60000
fact bonus_rate = 10%
rule bonus = base_salary * bonus_rate
rule total = base_salary + bonus?
"#, "compensation.lemma")?;
let response = engine.evaluate("compensation", None, None)?;
for result in response.results {
if let Some(value) = result.result {
println!("{}: {}", result.rule_name, value);
}
}
use lemma::Engine;
use std::collections::HashMap;
let mut engine = Engine::new();
engine.add_lemma_code(r#"
doc shipping
fact weight = 5 kilogram
fact destination = "domestic"
rule rate = 10
unless weight > 10 kilogram then 15
unless destination is "international" then 25
rule valid = weight <= 30 kilogram
unless veto "Package too heavy for shipping"
"#, "shipping.lemma")?;
let mut values = HashMap::new();
values.insert("weight".to_string(), "12 kilogram".to_string());
values.insert("destination".to_string(), "international".to_string());
let response = engine.evaluate("shipping", None, Some(values))?;
Inversion allows you to find what input values produce a desired output. This is useful for questions like "What quantity gives me a 30% discount?" or "What salary produces a total compensation of €100,000?"
use lemma::{Engine, Target, LiteralValue};
use std::collections::HashMap;
use rust_decimal::Decimal;
let mut engine = Engine::new();
engine.add_lemma_code(r#"
doc pricing
fact quantity = [number]
fact is_vip = false
rule discount = 0%
unless quantity >= 10 then 10%
unless quantity >= 50 then 20%
unless is_vip then 25%
"#, "pricing.lemma")?;
// Find what quantity gives a 30% discount
use rust_decimal::Decimal;
let response = engine.invert(
"pricing",
"discount",
Target::value(LiteralValue::Percentage(Decimal::from(30))),
HashMap::new()
)?;
// Response contains solutions showing: is_vip must be true
1. invert() - String-based values (user-friendly)
Accepts string values that are automatically parsed based on document types:
let mut values = HashMap::new();
values.insert("is_vip".to_string(), "true".to_string());
let response = engine.invert(
"pricing",
"discount",
Target::value(LiteralValue::Percentage(Decimal::from(25))),
values
)?;
2. invert_json() - JSON input (convenience)
Accepts JSON bytes directly:
let json = br#"{"is_vip": true}"#;
let response = engine.invert_json(
"pricing",
"discount",
Target::value(LiteralValue::Percentage(Decimal::from(25))),
json
)?;
Use Target to specify the desired outcome:
use lemma::{Target, TargetOp, OperationResult};
// Exact value (equality)
Target::value(LiteralValue::Percentage(Decimal::from(30)))
// Comparison operators
Target::with_op(
TargetOp::Gt,
OperationResult::Value(LiteralValue::number(100))
) // > 100
Target::with_op(
TargetOp::Lte,
OperationResult::Value(LiteralValue::number(50))
) // <= 50
// Find any veto
Target::any_veto()
// Find specific veto message
Target::veto(Some("Invalid input".to_string()))
InversionResponse contains:
solutions: Concrete domain constraints for each free variableshape: Symbolic representation of the solution space (piecewise function)free_variables: Facts that are not fully determinedis_fully_constrained: Whether all facts have concrete valueslet response = engine.invert(...)?;
if response.is_fully_constrained {
println!("All variables are determined");
} else {
println!("Free variables: {:?}", response.free_variables);
}
for (var, domain) in &response.solutions {
println!("{}: {:?}", var, domain);
}
npm install @benrogmans/lemma-engine to run Lemma in browsers and at the edgecargo add lemma-engine
cargo install lemma-cli
lemma run pricing quantity=10
cargo install lemma-cli
lemma server --port 8080
npm install @benrogmans/lemma-engine
Contributions are very welcome! See documentation/contributing.md and the project roadmap for ideas.
Apache 2.0