Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion INTEGRATION_PATCH.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Add a row for the JS WAM catalogue (see

| Target | Bindings | Notes |
|---|---|---|
| `wam_javascript` | 41 (`javascript_wam_builtin/3`) | Interpreter-tier Node WAM. findall/functor/arg/=../copy_term/\+/call/aggregate_all/bagof/setof implemented (ISO witness grouping + standard-order setof). |
| `wam_javascript` | catalogue in `javascript_wam_bindings.pl` | Interpreter-tier Node WAM. findall/functor/arg/=../copy_term/\+/call/aggregate_all/bagof/setof + ISO/library breadth + native Pratt `parse_term`. |

## 3. `tests/test_advanced.pl`

Expand Down Expand Up @@ -165,3 +165,37 @@ green. The dedicated runner that does **not** need this patch:
```bash
swipl -q -g run_tests -t halt tests/test_wam_javascript_builtins.pl
```

## 7. `src/unifyweaver/targets/wam_runtime_parser_capability.pl`

The JS WAM ships a hand-written recursive-descent / Pratt reader in
`templates/targets/javascript_wam/runtime.js.mustache`
(`Runtime.parse_term`). That is the same kind of in-runtime host parser
as C++/R (`native(parse_term)`), **not** the bundled portable
`compiled(prolog_term_parser)`. Do **not** also claim `compiled(...)`
until the portable parser is actually prepended.

Add next to the other `target_runtime_parser_default/2` clauses:

```prolog
% JavaScript WAM: hand-written Pratt reader in the Node runtime
% (Runtime.parse_term). Powers CLI argv, read_term_from_atom/2,3,
% atom_to_term/3, and term_to_atom/2 reverse mode. ISO default
% operator table is included; user op/3 is not. Same default as
% C++/R because the parser always ships with the generated runtime.
target_runtime_parser_default(wam_javascript, native(parse_term)).
```

Add next to the other `target_runtime_parser_mode_/2` clauses:

```prolog
target_runtime_parser_mode_(wam_javascript, native(parse_term)).
```

Add next to the other `normalize_runtime_parser_target/2` clauses
(before the catch-all `normalize_runtime_parser_target(Target, Target)`):

```prolog
normalize_runtime_parser_target(javascript, wam_javascript) :- !.
normalize_runtime_parser_target(wam_javascript, wam_javascript) :- !.
```
41 changes: 37 additions & 4 deletions docs/WAM_JAVASCRIPT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ Assoc (`library(assoc)` shape, list-of-pairs not AVL): **`empty_assoc/1`**,
**`list_to_assoc/2`**, **`get_assoc/3`**, **`put_assoc/4`**,
**`assoc_to_list/2`**, **`assoc_to_keys/2`**.

Term: **`functor/3`**, **`arg/3`**, **`=../2`**, **`copy_term/2`**.
Term: **`functor/3`**, **`arg/3`**, **`=../2`**, **`copy_term/2`**,
**`read_term_from_atom/2` `/3`**, **`atom_to_term/3`**, **`term_to_atom/2`**.

Metacall: **`\+/1`**, **`call/1`** (re-enter the same instruction loop /
builtin dispatch).
Expand All @@ -86,6 +87,36 @@ for `count` / `sum(X)` / `bag(X)` / `set(X)`.
Types: `atom/1`, `integer/1`, `float/1`, `number/1`, `compound/1`, `var/1`,
`nonvar/1`, `is_list/1`, `ground/1`.

## Runtime term parser (G-W2)

The Node runtime ships a **hand-written recursive-descent / Pratt reader**
(`Runtime.parse_term` / `tokenize_term` in `runtime.js.mustache`). CLI argv
goes through `parse_cli_atom_or_int`, which now calls the same reader
(unreadable text still interned as an atom).

**Full:** integers (including a leading `-` after start/`(`/`[`/`,`/`|`),
floats (`3.14`, `-1.5`, `1.0e2`), bare atoms, quoted atoms (`'hi there'`
with `\'` / `\\` escapes), variables (`X`, `_`, shared names), `[]`,
proper lists `[a,b,c]`, partial lists `[H|T]`, compounds
`foo(a, bar(b), 3)`, and parentheses. Cons intern as `[|]/2` + the `[]`
atom (same functor as `put_list`).

**Partial:** ISO default operator table (`+ - * / //`, comparisons, `,`,
`\+`, prefix `+/-`, …) so `1+2` reads as `+(1,2)`. User `op/3` and
postfix operators are not implemented. Fall back rather than invent a
term when the token stream is leftover or illegal.

Capability (coordinator applies `INTEGRATION_PATCH.md` §7; the shared
capability file is not edited here):

```prolog
target_runtime_parser_default(wam_javascript, native(parse_term)).
target_runtime_parser_mode_(wam_javascript, native(parse_term)).
```

This matches C++/R (`native(parse_term)`): an in-runtime host-language
parser, not the bundled portable `compiled(prolog_term_parser)`.

## Remaining / partial

| Builtin | Status |
Expand All @@ -100,6 +131,7 @@ Types: `atom/1`, `integer/1`, `float/1`, `number/1`, `compound/1`, `var/1`,
| First-arg indexing | **Implemented.** `switch_on_constant` / `_fallthrough` / `_a2`, `switch_on_structure` / `_a2`, and `switch_on_term` / `_a2` jump to the matching clause group. Ground first-arg with a unique clause leaves no choice point (`deterministic/0`). Unbound first arg falls through to the try/retry/trust chain (no lost solutions). Exclusive miss fails; fallthrough variants keep the chain for variable-headed clauses. Dedicated `try`/`retry`/`trust` dispatch chains are emitted for multi-clause groups. |
| Second-arg / deep indexing | A2 switches are implemented; deep (argument >2) indexing is not. |
| Lowered / functions emit mode | **Implemented.** `javascript_wam_resolve_emit_mode/2` accepts `interpreter` (default), `functions` (lower every eligible predicate), and `mixed([P/A, ...])` (lower only the named ones). Eligible shapes: single-clause deterministic bodies; T4 all-clauses-inline; T5 first-arg constant dispatch; T6 hash dispatch (≥8 atom keys); structured ITE / negation / once. Unsupported ops (`begin_aggregate`, bagof/setof, cuts/jumps the planner rejects) fall back to the interpreter rather than emitting wrong code. Interpreter-mode bytecode and wrappers are unchanged. |
| CLI / runtime term parser | **Implemented.** Pratt reader: int/float/atom (incl. quoted)/var/list/`[H\|T]`/compound. CLI argv + `read_term_from_atom` / `atom_to_term` / `term_to_atom`. Capability `native(parse_term)` via `INTEGRATION_PATCH.md` §7. |
| Conformance harness adapter | See `INTEGRATION_PATCH.md` (coordinator applies `conformance_target(javascript)`). |

## How to run
Expand Down Expand Up @@ -129,6 +161,7 @@ positioning; assoc is a list-of-pairs, not SWI's AVL tree.
## Document status

Initial JS WAM bring-up + builtin port from Lua, ISO bagof/3 and setof/3,
first-argument indexing, the Tier-2 lowered emitter, then ISO/library
builtin breadth (sort, lists, atom/string, format, assoc). Source-verified
against SWI-Prolog as the oracle (2026-08-30).
first-argument indexing, the Tier-2 lowered emitter, ISO/library builtin
breadth (sort, lists, atom/string, format, assoc), then the G-W2 runtime
term parser (floats, lists, compounds; `native(parse_term)`).
Source-verified against SWI-Prolog as the oracle (2026-08-30).
8 changes: 7 additions & 1 deletion src/unifyweaver/bindings/javascript_wam_bindings.pl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
% dispatches these names from BuiltinCall (and as a Call/Execute fallback
% when no user label exists). Status:
% implemented - full for the conformance + probe suite, including
% ISO bagof/3 / setof/3 witness grouping and ^/2
% ISO bagof/3 / setof/3 witness grouping and ^/2,
% plus the native Pratt parse_term reader
% (read_term_from_atom, atom_to_term, term_to_atom)

:- module(javascript_wam_bindings, [
javascript_wam_builtin/3, % Name, Arity, Status
Expand Down Expand Up @@ -104,6 +106,10 @@
javascript_wam_builtin(put_assoc, 4, implemented).
javascript_wam_builtin(assoc_to_list, 2, implemented).
javascript_wam_builtin(assoc_to_keys, 2, implemented).
javascript_wam_builtin(read_term_from_atom, 2, implemented).
javascript_wam_builtin(read_term_from_atom, 3, implemented).
javascript_wam_builtin(atom_to_term, 3, implemented).
javascript_wam_builtin(term_to_atom, 2, implemented).

javascript_wam_builtins(List) :-
findall(Name/Arity, javascript_wam_builtin(Name, Arity, _), List).
10 changes: 5 additions & 5 deletions templates/targets/javascript_wam/program.js.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ if (is_main()) {
}
const state = Runtime.new_state();
for (let i = 0; i < parsed.length; i++) Runtime.put_reg(state, i + 1, parsed[i]);
const slash = String(predArity).lastIndexOf("/");
const arity = slash >= 0 ? Number(predArity.slice(slash + 1)) : parsed.length;
for (let i = parsed.length; i < arity; i++) {
Runtime.put_reg(state, i + 1, Runtime.new_var(state));
}
state.program = shared_program;
let ok;
if (typeof loweredFn === "function") {
const slash = String(predArity).lastIndexOf("/");
const arity = slash >= 0 ? Number(predArity.slice(slash + 1)) : parsed.length;
for (let i = parsed.length; i < arity; i++) {
Runtime.put_reg(state, i + 1, Runtime.new_var(state));
}
ok = loweredFn(shared_program, state) === true;
} else {
state.pc = startPc;
Expand Down
Loading
Loading