eyeling

A Notation3 (N3) reasoner in JavaScript.

eyeling is:

Playground

Try it here:

Quick start

Requirements

Install

npm i eyeling

CLI

Run on a file:

npx eyeling examples/socrates.n3

(Or install globally: npm i -g eyeling and run eyeling ....)

JavaScript API

const { reason } = require("eyeling");

const input = `
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix : <http://example.org/socrates#>.

:Socrates a :Human.
:Human rdfs:subClassOf :Mortal.

{ ?S a ?A. ?A rdfs:subClassOf ?B } => { ?S a ?B }.
`;

const output = reason({ proofComments: false }, input);
console.log(output);

ESM:

import eyeling from "eyeling";
const output = eyeling.reason({ proofComments: false }, input);
console.log(output);

Streaming (browser/worker, direct eyeling.js):

const { closureN3 } = eyeling.reasonStream(input, {
  proof: false,
  onDerived: ({ triple }) => console.log(triple),
});

Note: the API currently shells out to the bundled eyeling.js CLI under the hood (simple + robust).

Testing

From a repo checkout:

npm test

Or run individual suites:

npm run test:api
npm run test:examples
npm run test:package
npm run test:packlist

Usage

Usage: eyeling [options] <file.n3>

Options:
  -a, --ast               Print parsed AST as JSON and exit.
  -e, --enforce-https     Rewrite http:// IRIs to https:// for log dereferencing builtins.
  -h, --help              Show this help and exit.
  -p, --proof-comments    Enable proof explanations.
  -r, --strings           Print log:outputString strings (ordered by key) instead of N3 output.
  -s, --super-restricted  Disable all builtins except => and <=.
  -t, --stream            Stream derived triples as soon as they are derived.
  -v, --version           Print version and exit.

By default, eyeling:

  1. parses the input (facts + rules)
  2. runs forward chaining to a fixpoint
  3. prints only newly derived forward facts (not the original input facts)
  4. prints a compact per-triple explanation as # comments (can be disabled)

What output do I get?

For each newly derived triple, eyeling prints:

  1. a proof-style comment block explaining why the triple holds, and then
  2. the triple itself in N3/Turtle syntax.

The proof comments are compact “local justifications” per derived triple (not a single exported global proof tree).

Reasoning model

Forward + backward chaining

Forward rule premises are proved using:

The CLI prints only newly derived forward facts.

Performance notes

eyeling includes a few key performance mechanisms:

Blank nodes and quantification

eyeling follows the usual N3 intuition:

  1. blank nodes in facts are normal RDF blanks (_:b1, _:b2, … within a run)
  2. blank nodes in rule premises behave like rule-scoped universals (similar to variables)
  3. blank nodes only in rule conclusions behave like existentials: each rule firing generates fresh Skolem blanks (_:sk_0, _:sk_1, …)

Equal facts up to renaming of Skolem IDs are treated as duplicates and are not re-added.

Rule-producing rules aka meta-rules

eyeling understands the log:implies / log:impliedBy idiom.

Top level:

During reasoning:

Inference fuse

Rules whose conclusion is false are treated as hard failures:

:stone :color :black .
:stone :color :white .

{ ?X :color :black . ?X :color :white . } => false.

As soon as the premise is provable, eyeling exits with status code 2.

Syntax

eyeling’s parser targets (nearly) the full Notation3 Language grammar from the W3C N3 Community Group spec.

In practice this means: it’s a Turtle superset that also accepts quoted formulas, rules, paths, and the N3 “syntax shorthand” operators (=, =>, <=) described in the spec.

Commonly used N3/Turtle features:

Builtins

eyeling implements the builtins described in eyeling-builtins.

License

MIT (see LICENSE).