Skip to content
docs
Arxo ↗

The structural layer, form by form

For LLMs6 sections

A structural query names its tables in from, narrows rows in where, and shapes the answer in select. Every query below runs against the two-package reference fixture: a base package with rules, duties, interpretations and a pinned article, and a second package that imports it. Column aliases follow as.

LawQL
from r in rules
where r.head_predicate == "urn:law:demo:lawqlbase#eligible"
select r.id as producer, r.strength as strength, anchor(r.id) as anchors

The answer is rows with provenance: every row names the model nodes it was assembled from and the anchors into the pinned text. There is no row without a node.

let binds a name; eval materializes a stored answer document for a package and its case. The number of such materializations is always bounded explicitly.

LawQL
let doc = eval("demo.lawqlbase", "verify/ci/gates/release/lawql_reference_fixtures/base")
from r in doc.results
select r.query as query

Any top-level key of the stored document reads as a table afterwards: results, positions, issues, derivations. Reading the document is not recomputing it: truth, defeat and the reason something did not follow are computed by the core.

A relation accepts a package scope in front of it. corpus takes a glob over package names, package names one package exactly.

LawQL
from r in corpus("demo.lawql*").rules
where r.strength == "strict"
select r.id as rule, r.package as package
LawQL
from n in package("demo.lawqlbase").nodes
where n.kind == "rule"
select n.id as rule

exists and not exists quantify over an already bound variable: the inner query may compare its rows with the outer row. Rules that share their head predicate with another rule:

LawQL
from r in rules
where exists(s in rules where s.head_predicate == r.head_predicate and s.id != r.id)
select r.id as rule

Rules whose head predicate no body ever mentions:

LawQL
from r in rules
where not exists(l in literals where l.predicate == r.head_predicate)
select r.id as rule

Whatever needs recursion, negation or ordering goes to an inference query: it compiles into a short-lived package over the named model and runs the core. The facts of a case travel in the case clause.

LawQL
query eligible_ann over "demo.lawqlbase" {
for a: Applicant;
case "verify/ci/gates/release/lawql_reference_fixtures/base/case.json";
where resident(a);
select eligible(a);
}

The structural layer reserves exactly these words, in both implementations:

from, in, where, select, as, and, or, exists, not, let, eval, true, false, null, query, over

Every reserved word above is listed here; no other word is reserved.

The user-facing flags of law query, checked against the command itself:

  • --corpus — scope by package name or glob; without it the whole slice is read.
  • --pkg — the package argument of a named question.
  • --json — the canonical answer document instead of human text.
  • --format — human, json or tsv output.
  • --explain — row counts after every clause, the same funnel the answer document carries.
  • --limit — bound on eval materializations; required whenever the query materializes.
  • --param — a named-question argument as name and value; repeatable.
  • --schema — the live dictionary of relations and functions instead of an answer.
  • --list — the catalog of named questions instead of an answer.

Documentation for Arxo. Writings — blog.arxo.io.

Anonymous visit counts on stats.arxo.io, no cookies.