Nelumbo is a declarative logic meta-language. You define the syntax and semantics of your language in a .nl file, and the same file runs and tests it. Because Nelumbo reasons about facts and falsehoods as peers, it has genuine logical negation — not Prolog's negation-as-failure — and produces results as a two-sided [facts][falsehoods] structure.
Status: Nelumbo is at an early stage of development. Some features are still evolving; where that matters, individual pages note it.
This folder contains the user documentation. For the project overview, build instructions, and release notes, see the repository README. For the presentation-deck version of this material, see NELUMBO.md.
- Reading a query and test — the first thing to read. Without this, every
.nlfile in the repo is unreadable because every example ends with tests in the? [facts][falsehoods]notation. - Your first program — line-by-line walkthrough of
fibonacci.nl, exercising imports, patterns, rules with guards, and tests.
Thirty minutes with those two pages is enough to open any .nl file in the repo and follow what's going on.
Different readers want different things. Pick the path that matches your goal.
- Reading a query and test — the language's headline feature, three-valued logic
- Architecture — how Nelumbo is layered — Java core →
lang.nl(syntactic bootstrap) →logic.nl(three-valued logic +<=>/fact/?) → numeric/data stdlib → user code - Three-valued logic — the semantic foundation, with truth tables
nelumbo.lang— the.nlfile that declares the whole syntax, including::,::=,::>, and the pattern meta-grammarnelumbo.logic— the.nlfile that declaresBoolean, the connectives, equality, and thefact/<=>/?statement forms
- The starting pair above, then
- Grammar and Operators — reference
- Writing rules —
<=>, guards, merging, contradictions - Language transformations — the
::>mechanism for defining new keywords (status: under construction) - Writing your own module — packaging a reusable library
- Architecture — understand the layering first
- Native API — the
Predicate,InferResult,infer()surface - Native classes catalogue — what's already shipped
- Native cookbook — five recipes with complete skeletons
- Standard library tour — all seven modules in dependency order
stdlib/lang.md,logic.md,integers.md,rationals.md,strings.md,collections.md,datetime.md— per-module reference
Jump straight to the reference section below. Everything in reference/ is organised as a lookup, not a read-through.
The irreducible facts about the language.
- Grammar — the core syntax of
.nlfiles - Operators — complete operator catalogue
- Built-in tokens and pattern holes —
<NUMBER>,<STRING>,<Variable>, etc. - Precedence and associativity — the
#Nsystem - Visibility —
private,hidden,visible, and scope blocks - Three-valued logic — truth tables and identities
- Test expression semantics — formal definition of when a test passes
- Writing rules —
<=>, guards, merging, contradictions - Native API — implementing predicates in Java
- Native classes catalogue — every shipped
@-bound class - Formatting — the canonical whitespace layout the LSP formatter produces
nelumbo.lang— the bootstrap layer: token types, object hierarchy, pattern meta-grammar, top-level statementsnelumbo.logic— Boolean, connectives, quantifiers, equalitynelumbo.integers— arbitrary-precision integer arithmeticnelumbo.rationals— exact rationalsnelumbo.strings— strings, concatenation, conversionnelumbo.collections— genericSet<E>andList<E>, set-builder notation, and operations (cardinality, membership, subset, union/intersection/difference, concatenation, indexing)nelumbo.datetime— ISO 8601 dates, times, date-times, and durations
Task-oriented how-tos.
- Standard library tour — reading all seven stdlib modules in order
- Writing your own module — packaging a reusable library
- Language transformations — the
::>meta-feature (under construction) - Native cookbook — recipes for writing Java natives
Background and design.
The .nl files under src/main/resources/org/modelingvalue/nelumbo/examples/ are the canonical worked examples. A short guide to what's in each:
| File | What it demonstrates |
|---|---|
fibonacci.nl |
Integer arithmetic, recursive rule with guards, basic tests |
family.nl |
Types, subtypes, FactType, literal enumerations, ancestor/descendant recursion |
friends.nl |
Mutually-recursive relations, symmetric + transitive closure |
even.nl |
Simplest useful predicate using an existential quantifier |
max.nl, ternary.nl |
Generic types (Type T), conditional expressions, user-defined operators |
power.nl, maxFib.nl |
Composed recursive definitions |
belasting.nl |
Natural-language DSL (Dutch tax rules) using multi-word pattern syntax |
transformation.nl, deHet.nl |
Language transformations with ::> — defining new top-level keywords |
scoping.nl, hidden.nl |
Scope blocks and hidden-variable patterns |
whoIs.nl |
Importing a user-written module (not just stdlib) |
queryOnly.nl |
Bare queries without [..][..] — useful during development |
*Assignment.nl |
"Fill in the rules" exercise versions of the corresponding examples |
The *Test.nl files under src/main/resources/org/modelingvalue/nelumbo/tests/ are executable specifications — useful to skim for corner cases:
| File | What it specifies |
|---|---|
logicTest.nl |
The three-valued logic truth tables |
integersTest.nl, rationalsTest.nl, stringsTest.nl, collectionsTest.nl |
Per-stdlib-module behaviour for each data type |
datetimeTest.nl |
Every datetime operator and the parse-time edge cases |
langTest.nl |
Smoke test that imports nelumbo.lang on its own |
..is the incompleteness marker — it means "this side of the result may have more bindings than are listed." It is never called a wildcard because it doesn't match values.- Facts (left bracket) and falsehoods (right bracket) are the two sides of every query result.
- In-language extensions (rules, transformations, modules) are distinguished from host-language extensions (Java natives bound with
@). The docs use these terms consistently. - Cross-references in every page point to other pages when a topic is covered in more depth elsewhere. If you follow the links, you end up with a coherent tour of the language.
The documentation is new and will have errors. Corrections and suggestions are welcome via the GitHub issue tracker. The source files for the docs are under docs/ in the repository.