diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 6ea05af..d244386 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -13,7 +13,7 @@ jobs:
strategy:
matrix:
- node-version: [18.x, latest]
+ node-version: [24.x, latest]
fail-fast: false
steps:
diff --git a/.github/workflows/ovsxstore.yaml b/.github/workflows/ovsxstore.yaml
index 0adbe41..39d7574 100644
--- a/.github/workflows/ovsxstore.yaml
+++ b/.github/workflows/ovsxstore.yaml
@@ -22,7 +22,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
- node-version: 18.x
+ node-version: 24.x
- run: npm install -g vsce
- run: npm install
diff --git a/.github/workflows/vcstore.yaml b/.github/workflows/vcstore.yaml
index e897ae8..98ab4ce 100644
--- a/.github/workflows/vcstore.yaml
+++ b/.github/workflows/vcstore.yaml
@@ -22,7 +22,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
- node-version: 18.x
+ node-version: 24.x
- run: npm install -g vsce
- run: npm install
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8600f85..8bc1f1f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+
+### 0.3.2
+
+- No more shiki
+- Support multiple trace versions
+
### 0.3.1
- Syntax for Elpi 3.0
diff --git a/media/main.js b/media/main.js
index fd9379d..4bd02c8 100644
--- a/media/main.js
+++ b/media/main.js
@@ -22,7 +22,7 @@
break;
case 'trace':
clear();
- trace(message.trace, message.enable_highlighting);
+ trace(message.trace);
$("#trace-information").val(message.file + ' on ' + new Date().toISOString());
break;
case 'clear':
@@ -44,7 +44,7 @@
function elide(i, str) {
- if (str.length < i)
+ if (str.length < 2*i)
return str;
return str.replace(str.slice(i,-i),' ... ');
@@ -656,12 +656,6 @@ ${step.value.findall_solution_text}
`;
- if(window.enable_highlighting)
- vscode.postMessage({
- command: 'highlight_inline',
- id: rule_id,
- value: step.value.suspend_sibling.goal_text
- });
contents += format_stack(step.value.suspend_stack, r_id, s_id);
@@ -706,15 +700,9 @@ ${step.value.findall_solution_text}
${step.value[i].goal_text}
`;
-
- if(window.enable_highlighting) vscode.postMessage({
- command: 'highlight_inline',
- id: rule_id,
- value: step.value[i].goal_text
- });
}
- contents += `
+ contents += `
@@ -985,19 +973,29 @@ ${step.value.findall_solution_text}
function format_rule(element, r_id, s_id, g_id)
{
- // console.log('Formatting rule', JSON.stringify(element));
+
+ //return('${rule_text}
+ ${rule_text_full}
${element[i].value}
`;
- if(window.enable_highlighting) vscode.postMessage({
- command: 'highlight_inline',
- id: rule_id,
- value: element[i].value
- });
}
return fmt;
@@ -1171,11 +1158,6 @@ class="has-tooltip-arrow has-tooltip-bottom" data-tooltip="${rule_loc_file} (${r
`;
}
- if(window.enable_highlighting) vscode.postMessage({
- command: 'highlight_inline',
- id: rule_id,
- value: element[i].goal_text
- });
}
return fmt;
@@ -1217,12 +1199,6 @@ class="has-tooltip-arrow has-tooltip-bottom" data-tooltip="${attempt_loc_file} (
${attempt_text}
' + window.inbox[i].goal_text + '';
-
- if(window.enable_highlighting)
- vscode.postMessage({
- command: 'highlight_elided',
- index: i,
- value: window.inbox[i].goal_text_elided
- });
- else
- window.inbox[i].goal_text_highlighted_elided = '' + window.inbox[i].goal_text_elided + '';
+ window.inbox[i].goal_text_highlighted = '' + window.inbox[i].goal_text + '';
+
+ window.inbox[i].goal_text_highlighted_elided = '' + window.inbox[i].goal_text_elided + '';
// /////////////////////////////////////////////////////////////////////////////
}
diff --git a/package-lock.json b/package-lock.json
index 4be694c..06b37f2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "elpi-lang",
- "version": "0.2.8",
+ "version": "0.3.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "elpi-lang",
- "version": "0.2.8",
+ "version": "0.3.2",
"license": "MIT",
"dependencies": {
"@creativebulma/bulma-collapsible": "^1.0.4",
@@ -19,7 +19,6 @@
"chokidar": "^3.5.3",
"fuzzball": "^2.1.2",
"jquery": "^3.6.1",
- "shiki": "^0.10.1",
"vue": "^2.7.0"
},
"devDependencies": {
@@ -245,6 +244,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.0.tgz",
"integrity": "sha512-joNO6zMGUZg+C73vwrKXCd8usnsmOYmgW/w5ZW0pG0RGvqeznjtGDk61EqqTpNrFLUYBW2RSBFrxdAZMqA4OZA==",
"dev": true,
+ "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.46.0",
"@typescript-eslint/types": "5.46.0",
@@ -458,6 +458,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
"dev": true,
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -1045,6 +1046,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz",
"integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@eslint/eslintrc": "^1.3.3",
"@humanwhocodes/config-array": "^0.11.6",
@@ -1836,7 +1838,8 @@
"node_modules/jsonc-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
- "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
+ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
+ "dev": true
},
"node_modules/keytar": {
"version": "7.9.0",
@@ -2630,16 +2633,6 @@
"node": ">=8"
}
},
- "node_modules/shiki": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz",
- "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==",
- "dependencies": {
- "jsonc-parser": "^3.0.0",
- "vscode-oniguruma": "^1.6.1",
- "vscode-textmate": "5.2.0"
- }
- },
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -2924,6 +2917,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
"dev": true,
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -2966,16 +2960,6 @@
"dev": true,
"optional": true
},
- "node_modules/vscode-oniguruma": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
- "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
- },
- "node_modules/vscode-textmate": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
- "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ=="
- },
"node_modules/vue": {
"version": "2.7.16",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
@@ -3229,6 +3213,7 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.46.0.tgz",
"integrity": "sha512-joNO6zMGUZg+C73vwrKXCd8usnsmOYmgW/w5ZW0pG0RGvqeznjtGDk61EqqTpNrFLUYBW2RSBFrxdAZMqA4OZA==",
"dev": true,
+ "peer": true,
"requires": {
"@typescript-eslint/scope-manager": "5.46.0",
"@typescript-eslint/types": "5.46.0",
@@ -3357,7 +3342,8 @@
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
"integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
- "dev": true
+ "dev": true,
+ "peer": true
},
"acorn-jsx": {
"version": "5.3.2",
@@ -3787,6 +3773,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.29.0.tgz",
"integrity": "sha512-isQ4EEiyUjZFbEKvEGJKKGBwXtvXX+zJbkVKCgTuB9t/+jUBcy8avhkEwWJecI15BkRkOYmvIM5ynbhRjEkoeg==",
"dev": true,
+ "peer": true,
"requires": {
"@eslint/eslintrc": "^1.3.3",
"@humanwhocodes/config-array": "^0.11.6",
@@ -4377,7 +4364,8 @@
"jsonc-parser": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
- "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w=="
+ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
+ "dev": true
},
"keytar": {
"version": "7.9.0",
@@ -4927,16 +4915,6 @@
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
- "shiki": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz",
- "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==",
- "requires": {
- "jsonc-parser": "^3.0.0",
- "vscode-oniguruma": "^1.6.1",
- "vscode-textmate": "5.2.0"
- }
- },
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -5138,7 +5116,8 @@
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
"integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
- "dev": true
+ "dev": true,
+ "peer": true
},
"uc.micro": {
"version": "1.0.6",
@@ -5174,16 +5153,6 @@
"dev": true,
"optional": true
},
- "vscode-oniguruma": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz",
- "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA=="
- },
- "vscode-textmate": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz",
- "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ=="
- },
"vue": {
"version": "2.7.16",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
diff --git a/package.json b/package.json
index 32a5650..cd47d1f 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"displayName": "Elpi lang",
"publisher": "gares",
"description": "Elpi programming language support",
- "version": "0.3.1",
+ "version": "0.3.2",
"homepage": "https://github.com/LPCIC/elpi-lang",
"repository": {
"type": "git",
@@ -88,11 +88,6 @@
"type": "string",
"default": "elpi-trace-elaborator",
"markdownDescription": "Path to `elpi-trace-elaborator` (or elpi from `$PATH`)"
- },
- "elpi.elpi_trace_view.syntax_highlighting": {
- "type": "boolean",
- "default": "false",
- "markdownDescription": "Highlight elpi code statements"
}
}
},
@@ -176,7 +171,7 @@
},
"scripts": {
"build": "mustache elpiLexicalConventions.js syntaxes/elpi.tmLanguage.mustache > syntaxes/elpi.tmLanguage.json",
- "vscode:prepublish": "npm run compile && rm -rf node_modules/shiki/languages/*",
+ "vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"lint": "eslint . --ext .ts,.tsx",
"watch": "tsc -w -p ./",
@@ -204,7 +199,6 @@
"chokidar": "^3.5.3",
"fuzzball": "^2.1.2",
"jquery": "^3.6.1",
- "shiki": "^0.10.1",
"vue": "^2.7.0"
}
}
diff --git a/src/provider.ts b/src/provider.ts
index 5b894d0..cb1b6f8 100644
--- a/src/provider.ts
+++ b/src/provider.ts
@@ -1,15 +1,37 @@
import * as vscode from 'vscode';
-import * as parser from './trace';
+import * as parser_v1 from './trace_v1';
+import * as parser_v2 from './trace_v2';
import * as path from 'path';
import os = require('node:os');
import cp = require('child_process');
import fs = require('fs');
-// import tmp = require('tmp');
-import shiki = require('shiki');
import chokidar = require('chokidar');
+type TraceParser = {
+ readTrace: (x: any, context?: any) => any;
+};
+
+const traceParsers: TraceParser[] = [parser_v2, parser_v1];
+
+function any_parser_readTrace(x: any) {
+ let lastError: unknown;
+
+ for (const parser of traceParsers) {
+ try {
+ return parser.readTrace(x);
+ } catch (error) {
+ lastError = error;
+ }
+ }
+
+ if (lastError instanceof Error)
+ throw lastError;
+
+ throw new Error('Failed to parse trace with all available parser versions.');
+}
+
export class TraceProvider implements vscode.WebviewViewProvider {
public static readonly viewType = 'elpi.tracer';
@@ -17,7 +39,6 @@ export class TraceProvider implements vscode.WebviewViewProvider {
private _cat: string;
private _elpi: string;
private _elpi_trace_elaborator: string;
- private _highlighter: shiki.Highlighter | undefined;
private _options: string;
private _options_default: string;
private _view?: vscode.WebviewView;
@@ -70,11 +91,6 @@ export class TraceProvider implements vscode.WebviewViewProvider {
this._watcher_target = this._target_dir + "traced.tmp.json";
this._watcher_target_elaborated = this._target_dir + "traced.json";
- shiki.getHighlighter({theme: 'css-variables'}).then(highlighter => {
- this._highlighter = highlighter;
- this._highlighter.loadLanguage(elpi_lang);
- });
-
if (os.platform().toString().toLowerCase() == "win32")
this._cat = "type";
else
@@ -107,9 +123,6 @@ export class TraceProvider implements vscode.WebviewViewProvider {
const indx = message.index;
let html = undefined;
- if (this._highlighter)
- html = this._highlighter.codeToHtml(code, { lang: 'elpi' });
-
if (this._view)
this._view.webview.postMessage({
type: 'highlight',
@@ -124,10 +137,7 @@ export class TraceProvider implements vscode.WebviewViewProvider {
const code = message.value;
const indx = message.index;
let html = undefined;
-
- if (this._highlighter)
- html = this._highlighter.codeToHtml(code, { lang: 'elpi' });
-
+
if (this._view)
this._view.webview.postMessage({
type: 'highlight_elided',
@@ -142,10 +152,7 @@ export class TraceProvider implements vscode.WebviewViewProvider {
const code = message.value;
const id = message.id;
let html = undefined;
-
- if (this._highlighter)
- html = this._highlighter.codeToHtml(code, { lang: 'elpi' });
-
+
if (this._view)
this._view.webview.postMessage({
type: 'highlight_inline',
@@ -284,14 +291,12 @@ export class TraceProvider implements vscode.WebviewViewProvider {
this.exec(this._cat + " " + fileUri[0].fsPath + " | " + this._elpi_trace_elaborator + " > " + this._target);
- const trace = parser.readTrace(JSON.parse(fs.readFileSync(this._target, 'utf8')));
+ const trace = any_parser_readTrace(JSON.parse(fs.readFileSync(this._target, 'utf8')));
this._source = fileUri[0].fsPath;
- let enable_highlighting = configuration.elpi_trace_view.syntax_highlighting;
-
if (this._view)
- this._view.webview.postMessage({ type: 'trace', trace: trace, file: fileUri[0].fsPath, enable_highlighting: enable_highlighting });
+ this._view.webview.postMessage({ type: 'trace', trace: trace, file: fileUri[0].fsPath });
if (this._view)
this._view.webview.postMessage({ type: 'progress', state: 'off' });
@@ -358,8 +363,6 @@ export class TraceProvider implements vscode.WebviewViewProvider {
return;
}
- let enable_highlighting = configuration.elpi_trace_view.syntax_highlighting;
-
message = `File ${path} has been changed`;
vscode.window.showInformationMessage(message);
@@ -368,12 +371,12 @@ export class TraceProvider implements vscode.WebviewViewProvider {
this.exec("eval $(opam env) && cat " + this._watcher_target + " | " + this._elpi_trace_elaborator + " > " + this._watcher_target_elaborated);
- const trace = parser.readTrace(JSON.parse(fs.readFileSync(this._watcher_target_elaborated, 'utf8')));
+ const trace = any_parser_readTrace(JSON.parse(fs.readFileSync(this._watcher_target_elaborated, 'utf8')));
this._source = this._watcher_target;
if (this._view)
- this._view.webview.postMessage({ type: 'trace', trace: trace, file: 'Watched', enable_highlighting: enable_highlighting });
+ this._view.webview.postMessage({ type: 'trace', trace: trace, file: 'Watched' });
});
message = "Me watch has started. Try me by touching " + this._watcher_target;
@@ -432,8 +435,6 @@ export class TraceProvider implements vscode.WebviewViewProvider {
this._options_default = configuration.elpi.options;
- let enable_highlighting = configuration.elpi_trace_view.syntax_highlighting;
-
if(vscode.window.activeTextEditor == undefined)
return;
@@ -470,12 +471,12 @@ export class TraceProvider implements vscode.WebviewViewProvider {
// --
- const trace = parser.readTrace(JSON.parse(fs.readFileSync(this._target, 'utf8')))
+ const trace = any_parser_readTrace(JSON.parse(fs.readFileSync(this._target, 'utf8')))
// --- Send message to the view backend
if (this._view)
- this._view.webview.postMessage({ type: 'trace', trace: trace, file: current_file, enable_highlighting: enable_highlighting });
+ this._view.webview.postMessage({ type: 'trace', trace: trace, file: current_file });
}
private _getHtmlForWebview(webview: vscode.Webview) {
diff --git a/src/trace.atd b/src/trace_v1.atd
similarity index 100%
rename from src/trace.atd
rename to src/trace_v1.atd
diff --git a/src/trace.ts b/src/trace_v1.ts
similarity index 100%
rename from src/trace.ts
rename to src/trace_v1.ts
diff --git a/src/trace_v2.atd b/src/trace_v2.atd
new file mode 100644
index 0000000..79302a3
--- /dev/null
+++ b/src/trace_v2.atd
@@ -0,0 +1,143 @@
+(* This file describes the format of the trace generated by elpi
+ and the format of the elaborate trace generated by elpi-trace-elaborator
+
+ home: https://github.com/ahrefs/atd
+ doc: https://atd.readthedocs.io/en/latest/index.html
+
+
+*)
+
+(* input: raw events *)
+
+type item = {
+ kind : kind list;
+ goal_id : int;
+ runtime_id : int;
+ step : int;
+ name : string;
+ payload : string list;
+}
+type kind = [ Start | Info | Stop of stop ]
+type stop = { cause : string; time : float }
+type raw_trace = item list
+
+(* **** output: cards to be displayed ************************************** *)
+
+type trace = card list
+
+(* Note: step_id + runtime_id form a unique identified for the card *)
+type card = {
+ step_id : step_id; (* sequential, but local to the runtime *)
+ runtime_id : runtime_id; (* each runtime has an id, 0 for the main one *)
+ step : step; (* the computation step *)
+ color : color;
+}
+
+type color = [ Red | Green | Grey | YellowGreen | YellowRed ]
+
+type step =
+ [ Inference of inference (* The goal is solved by a rule, most common case *)
+ | Findall of findall (* A sub runtime computes all solutions to a goal *)
+ | Cut of cut (* Some alternatives are dropped *)
+ | Suspend of suspend (* A new constraint is generated *)
+ | Resume of resume (* A constraint is resumed *)
+ | CHR of chr (* Some constraint handling rules fires *)
+ | Init of goal (* The initial goal is set *)
+ ]
+
+(* Inference step operates on a goal with a bunch of rules: first a bunch of
+ rules which fail, and then some which succeed. If no rule succeeds, then
+ the inference fails. If a rule succeeds, but some sibling fails, then
+ there may be more rules to be attempted later *)
+type inference = {
+ current_goal_id : goal_id;
+ current_goal_text : goal_text;
+ current_goal_predicate : string; (* string to search/filter steps *)
+ failed_attempts : attempt list;
+ successful_attempts : successful_attempt list;
+ more_successful_attempts : step_id list;
+ ~more_failing_attempts : step_id list; (* optional, for backward compatibility *)
+ stack : stack;
+}
+
+type attempt = {
+ rule : rule;
+ events : event list;
+}
+type rule = [ BuiltinRule of builtin_rule | UserRule of user_rule ]
+type user_rule = { rule_text : rule_text; rule_loc : location }
+type builtin_kind = [ Logic | FFI ]
+type builtin_rule = { name : string; kind : builtin_kind; payload : string list }
+type location = [ File of file_location | Context of step_id ]
+type file_location = { filename : string; line : int; column : int; character : int }
+type event = [ Assign of string | Fail of string | ResumeGoal of goal_id list]
+type rule_text = string (* Todo: use a formattable data, e.g. box language *)
+
+type successful_attempt = {
+ attempt : attempt;
+ siblings : goal list;
+ siblings_aggregated_outcome : outcome;
+}
+type goal = { goal_text : string; goal_id : goal_id }
+type outcome = [ Fail | Success ]
+
+type stack = frame list
+type frame = { rule : rule; step_id : step_id; runtime_id : runtime_id }
+
+type goal_id = int
+type step_id = int
+type runtime_id = int
+type goal_text = string (* Todo: use a formattable data, e.g. box language *)
+
+
+(* Findall step *)
+type findall = {
+ findall_goal_id : goal_id;
+ findall_goal_text : goal_text;
+ findall_cards : trace; (* The sub trace computing all solutions to the goal *)
+ findall_solution_text : solution_text;
+ findall_stack : stack;
+}
+type solution_text = string list (* Todo: use a formattable data, e.g. box language *)
+
+(* This goal generates a suspended sibling *)
+type suspend = {
+ suspend_goal_id : goal_id;
+ suspend_goal_text : goal_text;
+ suspend_sibling : goal;
+ suspend_stack : stack;
+}
+
+(* The ! operator eliminates some rules (for some goal) *)
+type cut = {
+ cut_goal_id : goal_id;
+ cut_victims : cutted list;
+}
+type cutted = {
+ cut_branch_for_goal : goal;
+ cut_branch : user_rule
+}
+
+(* Resumption activaes suspended goals *)
+type resume = goal list
+
+(* A CHR step is like an inference step, it is made of some failed and some
+ successful attempts. It acts on the store. *)
+type chr = {
+ chr_failed_attempts : chr_attempt list;
+ chr_successful_attempts : successful_chr_attempt list;
+ chr_store_before : goal list;
+ chr_store_after : goal list;
+}
+type chr_attempt = {
+ chr_text : chr_text; (* the rule text *)
+ chr_loc : file_location; (* the rule loc *)
+ chr_condition_cards : trace; (* the rule has a condition, which is an elpi
+ program running in a dedicated runtime *)
+}
+type successful_chr_attempt = {
+ chr_attempt : chr_attempt;
+ chr_removed_goals : goal_id list;
+ chr_new_goals : goal list;
+}
+type chr_text = string (* Todo: use a formattable data, e.g. box language *)
diff --git a/src/trace_v2.ts b/src/trace_v2.ts
new file mode 100644
index 0000000..e0bde14
--- /dev/null
+++ b/src/trace_v2.ts
@@ -0,0 +1,1178 @@
+/*
+ Generated by atdts from type definitions in 'trace.atd'.
+
+ Type-safe translations from/to JSON
+
+ For each type 'Foo', there is a pair of functions:
+ - 'writeFoo': convert a 'Foo' value into a JSON-compatible value.
+ - 'readFoo': convert a JSON-compatible value into a TypeScript value
+ of type 'Foo'.
+*/
+
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-nocheck
+/* tslint:disable */
+/* eslint-disable */
+
+export type Item = {
+ kind: Kind[];
+ goal_id: number /*int*/;
+ runtime_id: number /*int*/;
+ step: number /*int*/;
+ name: string;
+ payload: string[];
+}
+
+export type Kind =
+| { kind: 'Start' }
+| { kind: 'Info' }
+| { kind: 'Stop'; value: Stop }
+
+export type Stop = {
+ cause: string;
+ time: number;
+}
+
+export type RawTrace = Item[]
+
+export type Trace = Card[]
+
+export type Card = {
+ step_id: StepId;
+ runtime_id: RuntimeId;
+ step: Step;
+ color: Color;
+}
+
+export type Color =
+| { kind: 'Red' }
+| { kind: 'Green' }
+| { kind: 'Grey' }
+| { kind: 'YellowGreen' }
+| { kind: 'YellowRed' }
+
+export type Step =
+| { kind: 'Inference'; value: Inference }
+| { kind: 'Findall'; value: Findall }
+| { kind: 'Cut'; value: Cut }
+| { kind: 'Suspend'; value: Suspend }
+| { kind: 'Resume'; value: Resume }
+| { kind: 'CHR'; value: Chr }
+| { kind: 'Init'; value: Goal }
+
+export type Inference = {
+ current_goal_id: GoalId;
+ current_goal_text: GoalText;
+ current_goal_predicate: string;
+ failed_attempts: Attempt[];
+ successful_attempts: SuccessfulAttempt[];
+ more_successful_attempts: StepId[];
+ more_failing_attempts: StepId[];
+ stack: Stack;
+}
+
+export type Attempt = {
+ rule: Rule;
+ events: Event[];
+}
+
+export type Rule =
+| { kind: 'BuiltinRule'; value: BuiltinRule }
+| { kind: 'UserRule'; value: UserRule }
+
+export type UserRule = {
+ rule_text: RuleText;
+ rule_loc: Location;
+}
+
+export type BuiltinKind =
+| { kind: 'Logic' }
+| { kind: 'FFI' }
+
+export type BuiltinRule = {
+ name: string;
+ kind: BuiltinKind;
+ payload: string[];
+}
+
+export type Location =
+| { kind: 'File'; value: FileLocation }
+| { kind: 'Context'; value: StepId }
+
+export type FileLocation = {
+ filename: string;
+ line: number /*int*/;
+ column: number /*int*/;
+ character: number /*int*/;
+}
+
+export type Event =
+| { kind: 'Assign'; value: string }
+| { kind: 'Fail'; value: string }
+| { kind: 'ResumeGoal'; value: GoalId[] }
+
+export type RuleText = string
+
+export type SuccessfulAttempt = {
+ attempt: Attempt;
+ siblings: Goal[];
+ siblings_aggregated_outcome: Outcome;
+}
+
+export type Goal = {
+ goal_text: string;
+ goal_id: GoalId;
+}
+
+export type Outcome =
+| { kind: 'Fail' }
+| { kind: 'Success' }
+
+export type Stack = Frame[]
+
+export type Frame = {
+ rule: Rule;
+ step_id: StepId;
+ runtime_id: RuntimeId;
+}
+
+export type GoalId = number /*int*/
+
+export type StepId = number /*int*/
+
+export type RuntimeId = number /*int*/
+
+export type GoalText = string
+
+export type Findall = {
+ findall_goal_id: GoalId;
+ findall_goal_text: GoalText;
+ findall_cards: Trace;
+ findall_solution_text: SolutionText;
+ findall_stack: Stack;
+}
+
+export type SolutionText = string[]
+
+export type Suspend = {
+ suspend_goal_id: GoalId;
+ suspend_goal_text: GoalText;
+ suspend_sibling: Goal;
+ suspend_stack: Stack;
+}
+
+export type Cut = {
+ cut_goal_id: GoalId;
+ cut_victims: Cutted[];
+}
+
+export type Cutted = {
+ cut_branch_for_goal: Goal;
+ cut_branch: UserRule;
+}
+
+export type Resume = Goal[]
+
+export type Chr = {
+ chr_failed_attempts: ChrAttempt[];
+ chr_successful_attempts: SuccessfulChrAttempt[];
+ chr_store_before: Goal[];
+ chr_store_after: Goal[];
+}
+
+export type ChrAttempt = {
+ chr_text: ChrText;
+ chr_loc: FileLocation;
+ chr_condition_cards: Trace;
+}
+
+export type SuccessfulChrAttempt = {
+ chr_attempt: ChrAttempt;
+ chr_removed_goals: GoalId[];
+ chr_new_goals: Goal[];
+}
+
+export type ChrText = string
+
+export function writeItem(x: Item, context: any = x): any {
+ return {
+ 'kind': _atd_write_required_field('Item', 'kind', _atd_write_array(writeKind), x.kind, x),
+ 'goal_id': _atd_write_required_field('Item', 'goal_id', _atd_write_int, x.goal_id, x),
+ 'runtime_id': _atd_write_required_field('Item', 'runtime_id', _atd_write_int, x.runtime_id, x),
+ 'step': _atd_write_required_field('Item', 'step', _atd_write_int, x.step, x),
+ 'name': _atd_write_required_field('Item', 'name', _atd_write_string, x.name, x),
+ 'payload': _atd_write_required_field('Item', 'payload', _atd_write_array(_atd_write_string), x.payload, x),
+ };
+}
+
+export function readItem(x: any, context: any = x): Item {
+ return {
+ kind: _atd_read_required_field('Item', 'kind', _atd_read_array(readKind), x['kind'], x),
+ goal_id: _atd_read_required_field('Item', 'goal_id', _atd_read_int, x['goal_id'], x),
+ runtime_id: _atd_read_required_field('Item', 'runtime_id', _atd_read_int, x['runtime_id'], x),
+ step: _atd_read_required_field('Item', 'step', _atd_read_int, x['step'], x),
+ name: _atd_read_required_field('Item', 'name', _atd_read_string, x['name'], x),
+ payload: _atd_read_required_field('Item', 'payload', _atd_read_array(_atd_read_string), x['payload'], x),
+ };
+}
+
+export function writeKind(x: Kind, context: any = x): any {
+ switch (x.kind) {
+ case 'Start':
+ return 'Start'
+ case 'Info':
+ return 'Info'
+ case 'Stop':
+ return ['Stop', writeStop(x.value, x)]
+ }
+}
+
+export function readKind(x: any, context: any = x): Kind {
+ if (typeof x === 'string') {
+ switch (x) {
+ case 'Start':
+ return { kind: 'Start' }
+ case 'Info':
+ return { kind: 'Info' }
+ default:
+ _atd_bad_json('Kind', x, context)
+ throw new Error('impossible')
+ }
+ }
+ else {
+ _atd_check_json_tuple(2, x, context)
+ switch (x[0]) {
+ case 'Stop':
+ return { kind: 'Stop', value: readStop(x[1], x) }
+ default:
+ _atd_bad_json('Kind', x, context)
+ throw new Error('impossible')
+ }
+ }
+}
+
+export function writeStop(x: Stop, context: any = x): any {
+ return {
+ 'cause': _atd_write_required_field('Stop', 'cause', _atd_write_string, x.cause, x),
+ 'time': _atd_write_required_field('Stop', 'time', _atd_write_float, x.time, x),
+ };
+}
+
+export function readStop(x: any, context: any = x): Stop {
+ return {
+ cause: _atd_read_required_field('Stop', 'cause', _atd_read_string, x['cause'], x),
+ time: _atd_read_required_field('Stop', 'time', _atd_read_float, x['time'], x),
+ };
+}
+
+export function writeRawTrace(x: RawTrace, context: any = x): any {
+ return _atd_write_array(writeItem)(x, context);
+}
+
+export function readRawTrace(x: any, context: any = x): RawTrace {
+ return _atd_read_array(readItem)(x, context);
+}
+
+export function writeTrace(x: Trace, context: any = x): any {
+ return _atd_write_array(writeCard)(x, context);
+}
+
+export function readTrace(x: any, context: any = x): Trace {
+ return _atd_read_array(readCard)(x, context);
+}
+
+export function writeCard(x: Card, context: any = x): any {
+ return {
+ 'step_id': _atd_write_required_field('Card', 'step_id', writeStepId, x.step_id, x),
+ 'runtime_id': _atd_write_required_field('Card', 'runtime_id', writeRuntimeId, x.runtime_id, x),
+ 'step': _atd_write_required_field('Card', 'step', writeStep, x.step, x),
+ 'color': _atd_write_required_field('Card', 'color', writeColor, x.color, x),
+ };
+}
+
+export function readCard(x: any, context: any = x): Card {
+ return {
+ step_id: _atd_read_required_field('Card', 'step_id', readStepId, x['step_id'], x),
+ runtime_id: _atd_read_required_field('Card', 'runtime_id', readRuntimeId, x['runtime_id'], x),
+ step: _atd_read_required_field('Card', 'step', readStep, x['step'], x),
+ color: _atd_read_required_field('Card', 'color', readColor, x['color'], x),
+ };
+}
+
+export function writeColor(x: Color, context: any = x): any {
+ switch (x.kind) {
+ case 'Red':
+ return 'Red'
+ case 'Green':
+ return 'Green'
+ case 'Grey':
+ return 'Grey'
+ case 'YellowGreen':
+ return 'YellowGreen'
+ case 'YellowRed':
+ return 'YellowRed'
+ }
+}
+
+export function readColor(x: any, context: any = x): Color {
+ switch (x) {
+ case 'Red':
+ return { kind: 'Red' }
+ case 'Green':
+ return { kind: 'Green' }
+ case 'Grey':
+ return { kind: 'Grey' }
+ case 'YellowGreen':
+ return { kind: 'YellowGreen' }
+ case 'YellowRed':
+ return { kind: 'YellowRed' }
+ default:
+ _atd_bad_json('Color', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeStep(x: Step, context: any = x): any {
+ switch (x.kind) {
+ case 'Inference':
+ return ['Inference', writeInference(x.value, x)]
+ case 'Findall':
+ return ['Findall', writeFindall(x.value, x)]
+ case 'Cut':
+ return ['Cut', writeCut(x.value, x)]
+ case 'Suspend':
+ return ['Suspend', writeSuspend(x.value, x)]
+ case 'Resume':
+ return ['Resume', writeResume(x.value, x)]
+ case 'CHR':
+ return ['CHR', writeChr(x.value, x)]
+ case 'Init':
+ return ['Init', writeGoal(x.value, x)]
+ }
+}
+
+export function readStep(x: any, context: any = x): Step {
+ _atd_check_json_tuple(2, x, context)
+ switch (x[0]) {
+ case 'Inference':
+ return { kind: 'Inference', value: readInference(x[1], x) }
+ case 'Findall':
+ return { kind: 'Findall', value: readFindall(x[1], x) }
+ case 'Cut':
+ return { kind: 'Cut', value: readCut(x[1], x) }
+ case 'Suspend':
+ return { kind: 'Suspend', value: readSuspend(x[1], x) }
+ case 'Resume':
+ return { kind: 'Resume', value: readResume(x[1], x) }
+ case 'CHR':
+ return { kind: 'CHR', value: readChr(x[1], x) }
+ case 'Init':
+ return { kind: 'Init', value: readGoal(x[1], x) }
+ default:
+ _atd_bad_json('Step', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeInference(x: Inference, context: any = x): any {
+ return {
+ 'current_goal_id': _atd_write_required_field('Inference', 'current_goal_id', writeGoalId, x.current_goal_id, x),
+ 'current_goal_text': _atd_write_required_field('Inference', 'current_goal_text', writeGoalText, x.current_goal_text, x),
+ 'current_goal_predicate': _atd_write_required_field('Inference', 'current_goal_predicate', _atd_write_string, x.current_goal_predicate, x),
+ 'failed_attempts': _atd_write_required_field('Inference', 'failed_attempts', _atd_write_array(writeAttempt), x.failed_attempts, x),
+ 'successful_attempts': _atd_write_required_field('Inference', 'successful_attempts', _atd_write_array(writeSuccessfulAttempt), x.successful_attempts, x),
+ 'more_successful_attempts': _atd_write_required_field('Inference', 'more_successful_attempts', _atd_write_array(writeStepId), x.more_successful_attempts, x),
+ 'more_failing_attempts': _atd_write_field_with_default(_atd_write_array(writeStepId), [], x.more_failing_attempts, x),
+ 'stack': _atd_write_required_field('Inference', 'stack', writeStack, x.stack, x),
+ };
+}
+
+export function readInference(x: any, context: any = x): Inference {
+ return {
+ current_goal_id: _atd_read_required_field('Inference', 'current_goal_id', readGoalId, x['current_goal_id'], x),
+ current_goal_text: _atd_read_required_field('Inference', 'current_goal_text', readGoalText, x['current_goal_text'], x),
+ current_goal_predicate: _atd_read_required_field('Inference', 'current_goal_predicate', _atd_read_string, x['current_goal_predicate'], x),
+ failed_attempts: _atd_read_required_field('Inference', 'failed_attempts', _atd_read_array(readAttempt), x['failed_attempts'], x),
+ successful_attempts: _atd_read_required_field('Inference', 'successful_attempts', _atd_read_array(readSuccessfulAttempt), x['successful_attempts'], x),
+ more_successful_attempts: _atd_read_required_field('Inference', 'more_successful_attempts', _atd_read_array(readStepId), x['more_successful_attempts'], x),
+ more_failing_attempts: _atd_read_field_with_default(_atd_read_array(readStepId), [], x['more_failing_attempts'], x),
+ stack: _atd_read_required_field('Inference', 'stack', readStack, x['stack'], x),
+ };
+}
+
+export function writeAttempt(x: Attempt, context: any = x): any {
+ return {
+ 'rule': _atd_write_required_field('Attempt', 'rule', writeRule, x.rule, x),
+ 'events': _atd_write_required_field('Attempt', 'events', _atd_write_array(writeEvent), x.events, x),
+ };
+}
+
+export function readAttempt(x: any, context: any = x): Attempt {
+ return {
+ rule: _atd_read_required_field('Attempt', 'rule', readRule, x['rule'], x),
+ events: _atd_read_required_field('Attempt', 'events', _atd_read_array(readEvent), x['events'], x),
+ };
+}
+
+export function writeRule(x: Rule, context: any = x): any {
+ switch (x.kind) {
+ case 'BuiltinRule':
+ return ['BuiltinRule', writeBuiltinRule(x.value, x)]
+ case 'UserRule':
+ return ['UserRule', writeUserRule(x.value, x)]
+ }
+}
+
+export function readRule(x: any, context: any = x): Rule {
+ _atd_check_json_tuple(2, x, context)
+ switch (x[0]) {
+ case 'BuiltinRule':
+ return { kind: 'BuiltinRule', value: readBuiltinRule(x[1], x) }
+ case 'UserRule':
+ return { kind: 'UserRule', value: readUserRule(x[1], x) }
+ default:
+ _atd_bad_json('Rule', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeUserRule(x: UserRule, context: any = x): any {
+ return {
+ 'rule_text': _atd_write_required_field('UserRule', 'rule_text', writeRuleText, x.rule_text, x),
+ 'rule_loc': _atd_write_required_field('UserRule', 'rule_loc', writeLocation, x.rule_loc, x),
+ };
+}
+
+export function readUserRule(x: any, context: any = x): UserRule {
+ return {
+ rule_text: _atd_read_required_field('UserRule', 'rule_text', readRuleText, x['rule_text'], x),
+ rule_loc: _atd_read_required_field('UserRule', 'rule_loc', readLocation, x['rule_loc'], x),
+ };
+}
+
+export function writeBuiltinKind(x: BuiltinKind, context: any = x): any {
+ switch (x.kind) {
+ case 'Logic':
+ return 'Logic'
+ case 'FFI':
+ return 'FFI'
+ }
+}
+
+export function readBuiltinKind(x: any, context: any = x): BuiltinKind {
+ switch (x) {
+ case 'Logic':
+ return { kind: 'Logic' }
+ case 'FFI':
+ return { kind: 'FFI' }
+ default:
+ _atd_bad_json('BuiltinKind', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeBuiltinRule(x: BuiltinRule, context: any = x): any {
+ return {
+ 'name': _atd_write_required_field('BuiltinRule', 'name', _atd_write_string, x.name, x),
+ 'kind': _atd_write_required_field('BuiltinRule', 'kind', writeBuiltinKind, x.kind, x),
+ 'payload': _atd_write_required_field('BuiltinRule', 'payload', _atd_write_array(_atd_write_string), x.payload, x),
+ };
+}
+
+export function readBuiltinRule(x: any, context: any = x): BuiltinRule {
+ return {
+ name: _atd_read_required_field('BuiltinRule', 'name', _atd_read_string, x['name'], x),
+ kind: _atd_read_required_field('BuiltinRule', 'kind', readBuiltinKind, x['kind'], x),
+ payload: _atd_read_required_field('BuiltinRule', 'payload', _atd_read_array(_atd_read_string), x['payload'], x),
+ };
+}
+
+export function writeLocation(x: Location, context: any = x): any {
+ switch (x.kind) {
+ case 'File':
+ return ['File', writeFileLocation(x.value, x)]
+ case 'Context':
+ return ['Context', writeStepId(x.value, x)]
+ }
+}
+
+export function readLocation(x: any, context: any = x): Location {
+ _atd_check_json_tuple(2, x, context)
+ switch (x[0]) {
+ case 'File':
+ return { kind: 'File', value: readFileLocation(x[1], x) }
+ case 'Context':
+ return { kind: 'Context', value: readStepId(x[1], x) }
+ default:
+ _atd_bad_json('Location', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeFileLocation(x: FileLocation, context: any = x): any {
+ return {
+ 'filename': _atd_write_required_field('FileLocation', 'filename', _atd_write_string, x.filename, x),
+ 'line': _atd_write_required_field('FileLocation', 'line', _atd_write_int, x.line, x),
+ 'column': _atd_write_required_field('FileLocation', 'column', _atd_write_int, x.column, x),
+ 'character': _atd_write_required_field('FileLocation', 'character', _atd_write_int, x.character, x),
+ };
+}
+
+export function readFileLocation(x: any, context: any = x): FileLocation {
+ return {
+ filename: _atd_read_required_field('FileLocation', 'filename', _atd_read_string, x['filename'], x),
+ line: _atd_read_required_field('FileLocation', 'line', _atd_read_int, x['line'], x),
+ column: _atd_read_required_field('FileLocation', 'column', _atd_read_int, x['column'], x),
+ character: _atd_read_required_field('FileLocation', 'character', _atd_read_int, x['character'], x),
+ };
+}
+
+export function writeEvent(x: Event, context: any = x): any {
+ switch (x.kind) {
+ case 'Assign':
+ return ['Assign', _atd_write_string(x.value, x)]
+ case 'Fail':
+ return ['Fail', _atd_write_string(x.value, x)]
+ case 'ResumeGoal':
+ return ['ResumeGoal', _atd_write_array(writeGoalId)(x.value, x)]
+ }
+}
+
+export function readEvent(x: any, context: any = x): Event {
+ _atd_check_json_tuple(2, x, context)
+ switch (x[0]) {
+ case 'Assign':
+ return { kind: 'Assign', value: _atd_read_string(x[1], x) }
+ case 'Fail':
+ return { kind: 'Fail', value: _atd_read_string(x[1], x) }
+ case 'ResumeGoal':
+ return { kind: 'ResumeGoal', value: _atd_read_array(readGoalId)(x[1], x) }
+ default:
+ _atd_bad_json('Event', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeRuleText(x: RuleText, context: any = x): any {
+ return _atd_write_string(x, context);
+}
+
+export function readRuleText(x: any, context: any = x): RuleText {
+ return _atd_read_string(x, context);
+}
+
+export function writeSuccessfulAttempt(x: SuccessfulAttempt, context: any = x): any {
+ return {
+ 'attempt': _atd_write_required_field('SuccessfulAttempt', 'attempt', writeAttempt, x.attempt, x),
+ 'siblings': _atd_write_required_field('SuccessfulAttempt', 'siblings', _atd_write_array(writeGoal), x.siblings, x),
+ 'siblings_aggregated_outcome': _atd_write_required_field('SuccessfulAttempt', 'siblings_aggregated_outcome', writeOutcome, x.siblings_aggregated_outcome, x),
+ };
+}
+
+export function readSuccessfulAttempt(x: any, context: any = x): SuccessfulAttempt {
+ return {
+ attempt: _atd_read_required_field('SuccessfulAttempt', 'attempt', readAttempt, x['attempt'], x),
+ siblings: _atd_read_required_field('SuccessfulAttempt', 'siblings', _atd_read_array(readGoal), x['siblings'], x),
+ siblings_aggregated_outcome: _atd_read_required_field('SuccessfulAttempt', 'siblings_aggregated_outcome', readOutcome, x['siblings_aggregated_outcome'], x),
+ };
+}
+
+export function writeGoal(x: Goal, context: any = x): any {
+ return {
+ 'goal_text': _atd_write_required_field('Goal', 'goal_text', _atd_write_string, x.goal_text, x),
+ 'goal_id': _atd_write_required_field('Goal', 'goal_id', writeGoalId, x.goal_id, x),
+ };
+}
+
+export function readGoal(x: any, context: any = x): Goal {
+ return {
+ goal_text: _atd_read_required_field('Goal', 'goal_text', _atd_read_string, x['goal_text'], x),
+ goal_id: _atd_read_required_field('Goal', 'goal_id', readGoalId, x['goal_id'], x),
+ };
+}
+
+export function writeOutcome(x: Outcome, context: any = x): any {
+ switch (x.kind) {
+ case 'Fail':
+ return 'Fail'
+ case 'Success':
+ return 'Success'
+ }
+}
+
+export function readOutcome(x: any, context: any = x): Outcome {
+ switch (x) {
+ case 'Fail':
+ return { kind: 'Fail' }
+ case 'Success':
+ return { kind: 'Success' }
+ default:
+ _atd_bad_json('Outcome', x, context)
+ throw new Error('impossible')
+ }
+}
+
+export function writeStack(x: Stack, context: any = x): any {
+ return _atd_write_array(writeFrame)(x, context);
+}
+
+export function readStack(x: any, context: any = x): Stack {
+ return _atd_read_array(readFrame)(x, context);
+}
+
+export function writeFrame(x: Frame, context: any = x): any {
+ return {
+ 'rule': _atd_write_required_field('Frame', 'rule', writeRule, x.rule, x),
+ 'step_id': _atd_write_required_field('Frame', 'step_id', writeStepId, x.step_id, x),
+ 'runtime_id': _atd_write_required_field('Frame', 'runtime_id', writeRuntimeId, x.runtime_id, x),
+ };
+}
+
+export function readFrame(x: any, context: any = x): Frame {
+ return {
+ rule: _atd_read_required_field('Frame', 'rule', readRule, x['rule'], x),
+ step_id: _atd_read_required_field('Frame', 'step_id', readStepId, x['step_id'], x),
+ runtime_id: _atd_read_required_field('Frame', 'runtime_id', readRuntimeId, x['runtime_id'], x),
+ };
+}
+
+export function writeGoalId(x: GoalId, context: any = x): any {
+ return _atd_write_int(x, context);
+}
+
+export function readGoalId(x: any, context: any = x): GoalId {
+ return _atd_read_int(x, context);
+}
+
+export function writeStepId(x: StepId, context: any = x): any {
+ return _atd_write_int(x, context);
+}
+
+export function readStepId(x: any, context: any = x): StepId {
+ return _atd_read_int(x, context);
+}
+
+export function writeRuntimeId(x: RuntimeId, context: any = x): any {
+ return _atd_write_int(x, context);
+}
+
+export function readRuntimeId(x: any, context: any = x): RuntimeId {
+ return _atd_read_int(x, context);
+}
+
+export function writeGoalText(x: GoalText, context: any = x): any {
+ return _atd_write_string(x, context);
+}
+
+export function readGoalText(x: any, context: any = x): GoalText {
+ return _atd_read_string(x, context);
+}
+
+export function writeFindall(x: Findall, context: any = x): any {
+ return {
+ 'findall_goal_id': _atd_write_required_field('Findall', 'findall_goal_id', writeGoalId, x.findall_goal_id, x),
+ 'findall_goal_text': _atd_write_required_field('Findall', 'findall_goal_text', writeGoalText, x.findall_goal_text, x),
+ 'findall_cards': _atd_write_required_field('Findall', 'findall_cards', writeTrace, x.findall_cards, x),
+ 'findall_solution_text': _atd_write_required_field('Findall', 'findall_solution_text', writeSolutionText, x.findall_solution_text, x),
+ 'findall_stack': _atd_write_required_field('Findall', 'findall_stack', writeStack, x.findall_stack, x),
+ };
+}
+
+export function readFindall(x: any, context: any = x): Findall {
+ return {
+ findall_goal_id: _atd_read_required_field('Findall', 'findall_goal_id', readGoalId, x['findall_goal_id'], x),
+ findall_goal_text: _atd_read_required_field('Findall', 'findall_goal_text', readGoalText, x['findall_goal_text'], x),
+ findall_cards: _atd_read_required_field('Findall', 'findall_cards', readTrace, x['findall_cards'], x),
+ findall_solution_text: _atd_read_required_field('Findall', 'findall_solution_text', readSolutionText, x['findall_solution_text'], x),
+ findall_stack: _atd_read_required_field('Findall', 'findall_stack', readStack, x['findall_stack'], x),
+ };
+}
+
+export function writeSolutionText(x: SolutionText, context: any = x): any {
+ return _atd_write_array(_atd_write_string)(x, context);
+}
+
+export function readSolutionText(x: any, context: any = x): SolutionText {
+ return _atd_read_array(_atd_read_string)(x, context);
+}
+
+export function writeSuspend(x: Suspend, context: any = x): any {
+ return {
+ 'suspend_goal_id': _atd_write_required_field('Suspend', 'suspend_goal_id', writeGoalId, x.suspend_goal_id, x),
+ 'suspend_goal_text': _atd_write_required_field('Suspend', 'suspend_goal_text', writeGoalText, x.suspend_goal_text, x),
+ 'suspend_sibling': _atd_write_required_field('Suspend', 'suspend_sibling', writeGoal, x.suspend_sibling, x),
+ 'suspend_stack': _atd_write_required_field('Suspend', 'suspend_stack', writeStack, x.suspend_stack, x),
+ };
+}
+
+export function readSuspend(x: any, context: any = x): Suspend {
+ return {
+ suspend_goal_id: _atd_read_required_field('Suspend', 'suspend_goal_id', readGoalId, x['suspend_goal_id'], x),
+ suspend_goal_text: _atd_read_required_field('Suspend', 'suspend_goal_text', readGoalText, x['suspend_goal_text'], x),
+ suspend_sibling: _atd_read_required_field('Suspend', 'suspend_sibling', readGoal, x['suspend_sibling'], x),
+ suspend_stack: _atd_read_required_field('Suspend', 'suspend_stack', readStack, x['suspend_stack'], x),
+ };
+}
+
+export function writeCut(x: Cut, context: any = x): any {
+ return {
+ 'cut_goal_id': _atd_write_required_field('Cut', 'cut_goal_id', writeGoalId, x.cut_goal_id, x),
+ 'cut_victims': _atd_write_required_field('Cut', 'cut_victims', _atd_write_array(writeCutted), x.cut_victims, x),
+ };
+}
+
+export function readCut(x: any, context: any = x): Cut {
+ return {
+ cut_goal_id: _atd_read_required_field('Cut', 'cut_goal_id', readGoalId, x['cut_goal_id'], x),
+ cut_victims: _atd_read_required_field('Cut', 'cut_victims', _atd_read_array(readCutted), x['cut_victims'], x),
+ };
+}
+
+export function writeCutted(x: Cutted, context: any = x): any {
+ return {
+ 'cut_branch_for_goal': _atd_write_required_field('Cutted', 'cut_branch_for_goal', writeGoal, x.cut_branch_for_goal, x),
+ 'cut_branch': _atd_write_required_field('Cutted', 'cut_branch', writeUserRule, x.cut_branch, x),
+ };
+}
+
+export function readCutted(x: any, context: any = x): Cutted {
+ return {
+ cut_branch_for_goal: _atd_read_required_field('Cutted', 'cut_branch_for_goal', readGoal, x['cut_branch_for_goal'], x),
+ cut_branch: _atd_read_required_field('Cutted', 'cut_branch', readUserRule, x['cut_branch'], x),
+ };
+}
+
+export function writeResume(x: Resume, context: any = x): any {
+ return _atd_write_array(writeGoal)(x, context);
+}
+
+export function readResume(x: any, context: any = x): Resume {
+ return _atd_read_array(readGoal)(x, context);
+}
+
+export function writeChr(x: Chr, context: any = x): any {
+ return {
+ 'chr_failed_attempts': _atd_write_required_field('Chr', 'chr_failed_attempts', _atd_write_array(writeChrAttempt), x.chr_failed_attempts, x),
+ 'chr_successful_attempts': _atd_write_required_field('Chr', 'chr_successful_attempts', _atd_write_array(writeSuccessfulChrAttempt), x.chr_successful_attempts, x),
+ 'chr_store_before': _atd_write_required_field('Chr', 'chr_store_before', _atd_write_array(writeGoal), x.chr_store_before, x),
+ 'chr_store_after': _atd_write_required_field('Chr', 'chr_store_after', _atd_write_array(writeGoal), x.chr_store_after, x),
+ };
+}
+
+export function readChr(x: any, context: any = x): Chr {
+ return {
+ chr_failed_attempts: _atd_read_required_field('Chr', 'chr_failed_attempts', _atd_read_array(readChrAttempt), x['chr_failed_attempts'], x),
+ chr_successful_attempts: _atd_read_required_field('Chr', 'chr_successful_attempts', _atd_read_array(readSuccessfulChrAttempt), x['chr_successful_attempts'], x),
+ chr_store_before: _atd_read_required_field('Chr', 'chr_store_before', _atd_read_array(readGoal), x['chr_store_before'], x),
+ chr_store_after: _atd_read_required_field('Chr', 'chr_store_after', _atd_read_array(readGoal), x['chr_store_after'], x),
+ };
+}
+
+export function writeChrAttempt(x: ChrAttempt, context: any = x): any {
+ return {
+ 'chr_text': _atd_write_required_field('ChrAttempt', 'chr_text', writeChrText, x.chr_text, x),
+ 'chr_loc': _atd_write_required_field('ChrAttempt', 'chr_loc', writeFileLocation, x.chr_loc, x),
+ 'chr_condition_cards': _atd_write_required_field('ChrAttempt', 'chr_condition_cards', writeTrace, x.chr_condition_cards, x),
+ };
+}
+
+export function readChrAttempt(x: any, context: any = x): ChrAttempt {
+ return {
+ chr_text: _atd_read_required_field('ChrAttempt', 'chr_text', readChrText, x['chr_text'], x),
+ chr_loc: _atd_read_required_field('ChrAttempt', 'chr_loc', readFileLocation, x['chr_loc'], x),
+ chr_condition_cards: _atd_read_required_field('ChrAttempt', 'chr_condition_cards', readTrace, x['chr_condition_cards'], x),
+ };
+}
+
+export function writeSuccessfulChrAttempt(x: SuccessfulChrAttempt, context: any = x): any {
+ return {
+ 'chr_attempt': _atd_write_required_field('SuccessfulChrAttempt', 'chr_attempt', writeChrAttempt, x.chr_attempt, x),
+ 'chr_removed_goals': _atd_write_required_field('SuccessfulChrAttempt', 'chr_removed_goals', _atd_write_array(writeGoalId), x.chr_removed_goals, x),
+ 'chr_new_goals': _atd_write_required_field('SuccessfulChrAttempt', 'chr_new_goals', _atd_write_array(writeGoal), x.chr_new_goals, x),
+ };
+}
+
+export function readSuccessfulChrAttempt(x: any, context: any = x): SuccessfulChrAttempt {
+ return {
+ chr_attempt: _atd_read_required_field('SuccessfulChrAttempt', 'chr_attempt', readChrAttempt, x['chr_attempt'], x),
+ chr_removed_goals: _atd_read_required_field('SuccessfulChrAttempt', 'chr_removed_goals', _atd_read_array(readGoalId), x['chr_removed_goals'], x),
+ chr_new_goals: _atd_read_required_field('SuccessfulChrAttempt', 'chr_new_goals', _atd_read_array(readGoal), x['chr_new_goals'], x),
+ };
+}
+
+export function writeChrText(x: ChrText, context: any = x): any {
+ return _atd_write_string(x, context);
+}
+
+export function readChrText(x: any, context: any = x): ChrText {
+ return _atd_read_string(x, context);
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// Runtime library
+/////////////////////////////////////////////////////////////////////
+
+export type Option