Nelumbo

July 12, 2026 · View on GitHub

Nelumbo

Nelumbo aims to be a powerful and extensible declarative logic programming language, designed for defining and executing custom syntax and semantics. As a meta-language, Nelumbo will be easily extensible, making it suitable for a wide range of applications. The goal is to integrate it with any IDE using the Language Server Protocol, allowing Nelumbo to serve as a language development platform. The language is currently developed in Java for seamless integration and performance. Please note that Nelumbo is in a very early stage of development, and incompatible changes are likely to occur.


Table of Contents


Features

  • Define and parse syntaxes
  • Define and execute semantics
  • Purely declarative semantics
  • Define and run tests
  • Easily extensible
  • Easily integrable
  • IDE integration via LSP, including auto-formatting
  • Written in Java

Documentation

Detailed documentation.

Building

Requires Java 21 or later.

Build everything (core library, LSP server, and all IDE plugins):

./gradlew build

Build individual components:

./gradlew jar                          # core library
./gradlew :lsp:server:serverJar        # LSP server (shaded jar)
./gradlew :lsp:plugins:eclipse:jar     # Eclipse plugin (includes LSP server)
./gradlew :lsp:plugins:intellij:build  # IntelliJ plugin
./gradlew cliJar                       # command-line runner (shaded jar)

Run tests:

./gradlew test

IDE Plugins

Nelumbo has LSP-based editor plugins for multiple IDEs:

IDEPathDetails
Eclipselsp/plugins/eclipseDropins-based plugin with semantic highlighting
IntelliJlsp/plugins/intellijIntelliJ platform plugin
VS Codelsp/plugins/vscodeVS Code extension
Neovimlsp/plugins/neovimNeovim LSP configuration

See the README in each plugin directory for installation instructions.

Command-Line Interface

NelumboCli parses and evaluates one or more .nl files from the terminal, printing each query together with its inferred result. Queries that declare expected results are compared and mismatches are reported as errors. Build the shaded jar with ./gradlew cliJar (output in build/libs/nelumbo-<version>-cli.jar) and run it with java:

java -jar build/libs/nelumbo-<version>-cli.jar [options] <file>...

Pass - in place of a filename to read from stdin. Use -q / --quiet to suppress query output (errors are still reported) and -h / --help for the full option list. The process exits with 0 on success, 1 on parse/evaluation/comparison errors, and 2 on usage errors — suitable for scripting and CI.

MCP Server

The mcp module is a Model Context Protocol stdio server that lets LLM agents author and verify self-contained .nl decision models. It exposes four tools:

ToolPurpose
eval_nlParse and evaluate a .nl model; returns structured diagnostics and per-query results, including whether embedded expected results matched
search_docsKeyword search over the bundled language documentation
get_exampleList or fetch the bundled working .nl examples
new_modelReturn a commented, self-verifying skeleton model to start from

Build the shaded jar:

./gradlew :mcp:mcpJar

Register it with an MCP client, for example Claude Code:

claude mcp add nelumbo -- java -jar $(pwd)/mcp/build/libs/nelumbo-mcp-server-<version>.jar

The server communicates over stdio (stdout is the JSON-RPC channel, logging goes to stderr). The query evaluation deadline defaults to 10 seconds and can be changed with --eval-deadline-ms <ms>.

The intended agent workflow: start from new_model, look up syntax with search_docs and get_example, then iterate with eval_nl until it reports ok=true with all expected query results matched. The bundled example clubFees.nl was authored end-to-end this way.

Examples

Family Relations Example

Person    :: Object
Male      :: Person
Female    :: Person

FactType  ::= pc(<Person>,<Person>)   // parent-child

Person    ::= p(<Person>),   // parent
              c(<Person>),   // child
              a(<Person>),   // ancestor
              d(<Person>),   // descendant
              m(<Person>),   // mother
              f(<Person>)    // father

Person a, b, c
Male   y
Female x
           
c(a)=b  <=>  pc(a,b)
p(a)=b  <=>  pc(b,a)
m(a)=b  <=>  E[x](c(x)=a & b=x)
f(a)=b  <=>  E[y](c(y)=a & b=y)

a(a)=b  <=>  d(b)=a
d(a)=c  <=>  c(a)=c |
             E[b](d(a)=b & c(b)=c)

Male   ::= Hendrik, Bernhard, Claus, Willem
Female ::= Wilhelmina, Juliana, Beatrix, Maxima, Amalia

pc(Hendrik, Juliana)
pc(Wilhelmina, Juliana)
pc(Juliana, Beatrix)
pc(Bernhard, Beatrix)
pc(Beatrix, Willem)
pc(Claus, Willem)
pc(Willem, Amalia)
pc(Maxima, Amalia)

a(Amalia)=a         ? [(a=Beatrix),(a=Maxima),(a=Hendrik),(a=Bernhard),(a=Juliana),(a=Claus),(a=Willem),(a=Wilhelmina)][..]    
m(Amalia)=Maxima    ? [()][]
m(Amalia)=Willem    ? [][()]
m(Amalia)=a         ? [(a=Maxima)][..]
f(Amalia)=a         ? [(a=Willem)][..]
f(m(f(Amalia)))=a   ? [(a=Bernhard)][..]

Fibonacci Example

Integer ::= fib(<Integer>)

Integer n, f

fib(n)=f <=> f=n                 if n<=1,
             f=fib(n-1)+fib(n-2) if n>1  

fib(0)=f       ? [(f=0)][..]
fib(1)=f       ? [(f=1)][..]
fib(5)=f       ? [(f=5)][..]
fib(100)=f     ? [(f=36#22r8fozas3n8w3)][..]
fib(1000)=f    ? [(f=36#18nrvsuayughau0blk8aylvbyaqwiaqba77rdsgscn5hzwgbgaws8i8svp4xdmoo82plxiyogd5iaj1cspez8zfeio92a76t9n1frssxklr92wyyxm8r903o1ofgncikuggcwnf)][..]

    

Releasing

Releases are created automatically by CI. The process works as follows:

  1. You edit RELEASE_NOTES.md in the repository root with the release notes for the upcoming version. You can use ${version} and ${version-num} for the version tag and version number respectively.
  2. You merge your changes to master, that's it!
  3. The build workflow runs. On success, the Gradle mvgTagger plugin creates and pushes a version tag (e.g. v1.2.3).
  4. The tag push triggers the release workflow, which downloads the build artifacts and creates a GitHub release with the contents of RELEASE_NOTES.md.

The release includes the following artifacts:

  • Editor — standalone Swing-based editor (nelumbo-${version-num}-editor.jar)
  • Eclipse plugin — dropins-based plugin (eclipse-nelumbo-plugin-${version-num}.jar)
  • IntelliJ plugin — LSP4IJ-based plugin (intellij-nelumbo-plugin-${version-num}.zip)
  • Slides — presentation slides (nelumbo-slides.zip)

If RELEASE_NOTES.md is absent, GitHub will auto-generate release notes from the commit log.

Contributing

Contributions and feedback are welcome! Please open issues or pull requests on GitHub.

License

This project is licensed under the terms of the LICENSE file provided in the repository.

Support

For questions or support, please use the GitHub Issues page.