-
Notifications
You must be signed in to change notification settings - Fork 0
/
repl.mjs
executable file
·190 lines (178 loc) · 5.88 KB
/
repl.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/usr/bin/env node
import readline from "node:readline";
import fs from "node:fs";
import k from "./index.mjs";
import {run, closeVector } from "./run.mjs";
import { prettyCode, prettyRel, patterns2filters } from "./pretty.mjs";
import { find } from "./codes.mjs";
const splice = [].splice;
console.log("Very! experimental repl shell for 'k-language'...");
const help = function () {
// console.log(" --debug loads codes and relations as value");
console.log(" --c print aliased codes");
console.log(" --C code print 'code' definition");
console.log(" --r print relations");
console.log(" --R rel print 'rel' definition with type patterns");
console.log(" --p (--pp) pretty-print last value");
console.log(" --s (--g) reg store (get) the current value in (from) register 'reg'");
console.log(" --regs print register names");
console.log(" --l file.k load 'file.k'");
};
help();
const re__l = /^[ \n\t]*(?:--l[ ]+)(.+)[ ]*?$/;
const re__s = /^[ \n\t]*(?:--s[ ]+)(.+)[ ]*?$/;
const re__g = /^[ \n\t]*(?:--g[ ]+)(.+)[ ]*?$/;
const re__R = /^[ \n\t]*(?:--R[ ]+)(.+)[ ]*?$/;
const re__C = /^[ \n\t]*(?:--C[ ]+)(.+)[ ]*?$/;
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: '> '
});
rl.prompt();
rl.on('line', (line) => {
evaluate(line);
rl.prompt();
}).on('close', () => {
console.log('REPL closed');
process.exit(0);
});
let old_val = {};
let val = {};
const printVal = function (v = val) {
if (v === undefined)
console.log("...",v);
else
console.log(`--> ${JSON.stringify(v)}`);
rl.setPrompt('> ');
}
const registers = {};
const buffer = [];
function evaluate(line) {
if (line.trim().endsWith('\\')) {
buffer.push(line.slice(0, -1));
rl.setPrompt(' ');
return;
}
line = [...buffer, line].join('\n');
buffer.length = 0;
try {
if (val === undefined)
val = old_val;
else
old_val = val;
if (line.match(/^[ \n\t]*(?:--h)?$/)) {
// --h
help();
} else if (line.match(/^[ \n\t]*\^$/)) {
val = closeVector(val);
printVal();
} else if (line.match(re__l)) {
// --l
const file = line.match(re__l)[1];
console.log(` ... loading file: ${file} ...`);
const kScript = fs.readFileSync(file).toString();
console.log(` Done!`);
// console.log(kScript);
val = k.compile("+++\n" + kScript + "\n()")(val);
printVal();
} else if (line.match(/^[ \n\t]*--debug$/)) {
// --debug
val = run.defs;
console.log(val);
// --r
} else if (line.match(/^[ \n\t]*(?:--r)?$/)) {
console.log(
(function (defs, result) {
if (defs == null) {
return result;
}
return (function (prettyRel) {
for (const relName in defs.rels) {
if (relName != "__main__")
result[relName] = prettyRel(defs.rels[relName].def);
}
return result;
})(
prettyRel.bind(
null,
prettyCode.bind(null, defs.representatives)
)
);
})(run.defs, {}));
// --c
} else if (line.match(/^[ \n\t]*(?:--c)?$/)) {
console.log(
(function (defs, result) {
for (const codeName of Object.keys(defs.representatives || {})) {
const codeExp = find(defs.representatives[codeName] || codeName);
result[codeName] = prettyCode(
defs.representatives,
codeExp
);
}
return result;
})(run.defs || {}, {})
);
// --C
} else if (line.match(re__C)) {
let codeName = line.match(re__C)[1];
if (codeName.startsWith("?"))
codeName = codeName.slice(1);
if (codeName.startsWith("$"))
codeName = codeName.slice(1);
const canonicalName = run.defs.representatives[codeName] || codeName;
const codeExp = find( canonicalName );
console.log(` $ ${canonicalName} = ${prettyCode(run.defs.representatives, codeExp)}; -- ${codeExp.def}`);
// --pp
} else if (line.match(/^[ \n\t]*(?:--pp)?$/)) {
console.log(val);
// --p
} else if (line.match(/^[ \n\t]*(?:--p)?$/)) {
console.log(JSON.stringify(val, null, 2));
// --regs
} else if (line.match(/^[ \n\t]*(?:--regs)?$/)) {
console.log(` -- registers: ${Object.keys(registers).join(", ")}`);
// --s
} else if (line.match(re__s)) {
let reg = line.match(re__s)[1];
registers[reg] = val;
console.log(` -- current value stored in register: '${reg}'`);
// --g
} else if (line.match(re__g)) {
console.log(" -- getting value from register...");
let reg = line.match(re__g)[1];
val = registers[reg];
console.log(val);
// --R rel
} else if (line.match(re__R)) {
const relName = line.match(re__R)[1];
const rel = run.defs?.rels[relName];
if (!rel) {
console.log(` -- relation '${relName}' not found`);
return;
}
const filters = patterns2filters(rel.typePatternGraph, ...rel.def.patterns);
// console.log(filters);
// console.log(" variables:", JSON.stringify(variables));
// console.log(JSON.stringify({filters, variables}, null, 2));
// for (const filter of filters) {
const pcodef= prettyCode.bind(null, run.defs.representatives);
const filtersStr = filters.map( x => prettyRel(pcodef, {op: "filter", filter: x}));
console.log(` ${relName} : ${filtersStr[0]} --> ${filtersStr[1]}`);
console.log(` ${relName} = ${prettyRel(pcodef,rel.def)};`);
// }
// ------ k code
} else if (!line.match(/^[ \n\t]*(?:#.*)?$/)) {
try {
val = k.run(`+++\n${line}\n()`, val);
printVal();
} catch (error) {
console.error(error.message);
}
}
} catch (e) {
console.error(e.message);
console.error(e);
}
}