Skip to content

Commit

Permalink
Create first API docs, modify README, bump to 0.0.4.
Browse files Browse the repository at this point in the history
  • Loading branch information
robsimmons committed Nov 24, 2023
1 parent a75f6ff commit a51d516
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Dusa Language

Dusa is a logic programming language that has features of both Datalog and answer
set programming.

[![Build status](https://builds.sr.ht/~robsimmons/dusa.svg)](https://builds.sr.ht/~robsimmons/dusa?)
[![Coverage Status](https://coveralls.io/repos/github/robsimmons/dusa/badge.svg?branch=main)](https://coveralls.io/github/robsimmons/dusa?branch=main)
[![NPM Module](https://img.shields.io/npm/v/dusa.svg)](https://www.npmjs.com/package/dusa)
Expand Down
8 changes: 8 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export default defineConfig({
{ label: 'Syntax specification', link: '/docs/language/syntax/' },
],
},
{
label: 'JavaScript API',
items: [
{ label: 'class Dusa', link: '/docs/api/dusa/' },
{ label: 'class DusaSolution', link: '/docs/api/dusasolution/' },
{ label: 'Terms', link: '/docs/api/terms/' },
],
},
],
}),
],
Expand Down
123 changes: 123 additions & 0 deletions docs/src/content/docs/docs/api/dusa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
---
title: class Dusa
---

The main entrypoint to the Dusa JavaScript API is the Dusa class. (The
[dusa NPM package](https://www.npmjs.com/package/dusa) also includes Typescript
definitions.)

## Creating a Dusa instance

### `Dusa()` constructor

A Dusa instance is created by passing a Dusa program to the constructor.

```javascript
const dusa = new Dusa(`
edge a b.
edge b c.
edge c d.
path X Y :- edge X Y.
path X Z :- edge X Y, path Y Z.`);
```

If the program has errors, an error in the `DusaError` class will be thrown.

```javascript
// raises DusaError, X is conclusion but not premise.
const dusa = new Dusa(`edge a X.`);
```

## Solving a Dusa instance

Dusa programs can't be directly queried: they must first be solved. There are several
different ways to direct Dusa to generate solutions, all of which provide access to
[`DusaSolution` objects](/docs/api/dusasolution/).

### `solution` getter

If a Dusa program has at most one solution, that solution can be accessed with the
`solution` getter. The first time this method is accessed it will cause some
computation to happen (and it could even fail to terminate if there aren't finite
solutions). The result is cached, so subsequent calls will not trigger additional
computation.

```javascript
const dusa = new Dusa(`
edge "a" "b".
edge "b" "c".
edge "c" "d".
path X Y :- edge X Y.
path X Z :- edge X Y, path Y Z.`);
dusa.solution; // Object of type DusaSolution
[...dusa.solution.lookup('path', 'a')]; // [ "b", "c", "d" ]
[...dusa.solution.lookup('path', 'd')]; // []
```

If no solutions exist, the `solution` getter will return `null`.

```javascript
const dusa = new Dusa(`
name is "one".
name is "two".`);
dusa.solution; // null
```

This getter can only be used if a single solution exists. Dusa will check for
additional solutions when the `solution` getter is accessed, and will throw an
exception if there are other solutions.

```javascript
const dusa = new Dusa(`name is { "one", "two" }.`);
dusa.solution; // raises DusaError
```

For programs with multiple solutions, use the `sample()` method or the `solutions`
getter, which returns an iterator.

### `sample()` method

The `sample()` method will return an arbitrary solution to the Dusa program, or
`null` if no solution exists.

Each call to `sample()` re-computes the program, so even if there are only a finite
(but nonzero) number of solutions, `sample()` can be called as many times as desired.

```javascript
const dusa = new Dusa(`name is { "one", "two" }.`);

for (let i = 0; i < 1000; i++) {
for (const { args } of dusa.sample().lookup('name')) {
console.log(args[0]);
}
}
```

The current Dusa interpreter does not have a well-defined probabilistic semantics for
complex programs, but the simple program above will print `"one"` about 500 times and
will print `"two"` about 500 times.

### solutions getter

The `solutions` getter iterates through all the possible distinct solutions of a Dusa
program. The iterator works in an arbitrary order: this program will either print
`"one"` and then `"two"` or else it will print `"two"` and then `"one"`.

```javascript
const dusa = new Dusa(`name is { "one", "two" }.`);

for (const solution of dusa.solutions) {
console.log([...solution.lookup('name')].args[0]);
}
```

Each time the `dusa.solutions` getter is accessed, an iterator is returned that
re-runs solution search, potentially returning solutions in a different order.

## Modifying a Dusa instance

TODO

### assert() method

TODO
5 changes: 5 additions & 0 deletions docs/src/content/docs/docs/api/dusasolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: class DusaSolution
---

TODO
5 changes: 5 additions & 0 deletions docs/src/content/docs/docs/api/terms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Terms
---

TODO
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
{
"name": "dusa",
"version": "0.0.3",
"version": "0.0.4",
"type": "module",
"main": "lib/client.js",
"types": "lib/client.d.ts",
"homepage": "https://dusa.rocks/",
"homepage": "https://dusa.rocks",
"repository": {
"type": "git",
"url": "https://git.sr.ht/~robsimmons/dusa"
},
"bugs": {
"url": "https://todo.sr.ht/~robsimmons/Dusa"
},
"keywords": [
"asp",
"data",
"database",
"datalog",
"immutable",
"logic programming",
"persistent"
],
"license": "GPL-3.0-only",
"scripts": {
"build": "tsc && vite build",
Expand Down
7 changes: 6 additions & 1 deletion src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import { Issue } from './parsing/parser';
export type { Issue, Stats };
export type { SourcePosition, SourceLocation } from './parsing/source-location';

export type Term = null | bigint | string | { name: string; args?: [Term, ...Term[]] };
export type Term =
| null // Trivial type ()
| bigint // Natural numbers and integers
| string // Strings
| { name: string } // Constants
| { name: string; args: [Term, ...Term[]] };
export interface Fact {
name: string;
args: Term[];
Expand Down

0 comments on commit a51d516

Please sign in to comment.