move executables to scripts

This commit is contained in:
Joeri Exelmans 2025-03-24 17:29:33 +01:00
parent 145835ad5d
commit d236eca5e5
2 changed files with 66 additions and 6 deletions

326
scripts/main.js Normal file
View file

@ -0,0 +1,326 @@
import { select } from '@inquirer/prompts';
import { ModulePoint } from "../lib/point.js";
import { DefaultMap, pretty, prettyT } from '../util.js';
import { symbolFunction } from '../structures/types.js';
import { ModuleStd } from '../stdlib.js';
import { Type } from "../primitives/types.js";
import { assign, makeGeneric, unify } from '../generics/generics.js';
class Context {
constructor(mod) {
this.mod = mod;
this.types = new DefaultMap(() => new Set()); // instance to type
this.instances = new DefaultMap(() => new Set()); // type to instance
for (const {i, t} of mod.l) {
this.types.getdefault(i, true).add(t);
this.instances.getdefault(t, true).add(i);
}
this.functionsFrom = new DefaultMap(() => new Set()); // type to outgoing function
this.functionsTo = new DefaultMap(() => new Set()); // type to incoming function
for (const t of this.instances.m.keys()) {
if (t.symbol === symbolFunction) {
// 't' is a function signature
for (const fn of this.instances.getdefault(t)) {
this.functionsFrom.getdefault(t.params[0], true).add(fn);
this.functionsTo .getdefault(t.params[1], true).add(fn);
}
}
}
// this.typeVarAssigns = new Map();
// for (const t of this.instances.m.keys()) {
// if (t.typeVars) {
// for (const t2 of this.instances.m.keys()) {
// const genericT2 = (t2.typeVars === undefined)
// ? makeGeneric(() => t2)
// : t2;
// try {
// const unification = unify(t, t2);
// console.log(unification);
// } catch (e) {
// // skip
// }
// }
// }
// }
}
addToCtx({i, t}) {
return new Context({l:[
...this.mod.l,
{i, t},
]})
}
}
let ctx = new Context({l:[
...ModuleStd.l,
...ModulePoint.l,
]});
const prettyIT = ({i, t}) => ({
strI: isType(i) ? prettyT(i) : pretty(i),
strT: prettyT(t),
})
const toChoices = ([i, types]) => {
return [...types].map(t => {
const {strI, strT} = prettyIT({i, t});
return {
value: {i, t},
name: strI,
description: ` :: ${strT}`,
short: `${strI} :: ${strT}`,
};
});
}
const isType = i => ctx.types.getdefault(i).has(Type);
async function topPrompt() {
const action = await select({
message: "What do you want to do?",
choices: [
"list all types",
"list all functions",
"list all",
],
});
if (action === "list all types") {
await listInstances(Type);
// await listAllTypes();
}
if (action === "list all functions") {
await listAllFunctions();
}
if (action === "list all") {
await listAllInstances();
}
return topPrompt();
}
// async function listAllTypes() {
// const choice = await select({
// message: "select type:",
// choices: [
// "(go back)",
// ...[...ctx.instances.m.keys()].map(t => ({
// value: t,
// name: prettyT(t),
// })),
// ]
// });
// if (choice === "(go back)") {
// return;
// }
// await typeOptions(choice);
// return listAllTypes();
// }
async function listAllFunctions() {
const choice = await select({
message: "select function:",
choices: [
"(go back)",
...[...ctx.types.m.entries()]
.filter(([i, types]) => {
for (const type of types) {
if (type.symbol === symbolFunction)
return true;
}
return false;
})
.flatMap(toChoices),
],
});
if (choice === "(go back)") {
return;
}
const {i, t} = choice;
await functionOptions(i, t);
return listAllFunctions();
}
async function typeOptions(t) {
const choice = await select({
message: `actions for type ${prettyT(t)} :: Type`,
choices: [
"(go back)",
"list instances",
// "list outgoing functions",
// "list incoming functions",
"print raw",
"treat as instance",
],
});
if (choice === "(go back)") {
return;
}
else if (choice === "list instances") {
await listInstances(t);
}
else if (choice === "print raw") {
console.log(pretty(t));
}
else if (choice === "treat as instance") {
await instanceOptions(t, Type)
}
else {
console.log("unimplemented:", choice);
}
return typeOptions(t);
}
async function listAllInstances() {
const choice = await select({
message: `all instances:`,
choices: [
"(go back)",
... [...ctx.types.m.keys()].flatMap(i => toChoices([i, ctx.types.getdefault(i)])),
],
})
if (choice === "(go back)") {
return;
}
return instanceOrTypeOrFnOptions(choice);
}
async function instanceOrTypeOrFnOptions({i, t}) {
if (t.symbol === symbolFunction) {
return functionOptions(i, t);
}
if (isType(i)) {
return typeOptions(i);
}
return instanceOptions(i,t);
}
async function listInstances(t) {
const choice = await select({
message: `instances of ${prettyT(t)}:`,
choices: [
"(go back)",
... [...ctx.instances.getdefault(t)].flatMap(i => toChoices([i, [t]])),
],
});
if (choice === "(go back)") {
return;
}
return instanceOrTypeOrFnOptions(choice);
}
async function listTypes(i) {
const {strI} = prettyIT({i,t:Type});
const choice = await select({
message: `type(s) of ${strI}:`,
choices: [
"(go back)",
... [...ctx.types.getdefault(i)].flatMap(t => toChoices([t, ctx.types.getdefault(t)])),
],
});
if (choice === "(go back)") {
return;
}
const {i: chosenType} = choice;
await typeOptions(chosenType);
return listTypes(i);
}
async function functionOptions(fn, fnT) {
const {strI, strT} = prettyIT({i: fn, t: fnT});
const choice = await select({
message: `actions for function ${strI} :: ${strT}`,
choices: [
"(go back)",
"call",
"treat as instance",
],
});
if (choice === "(go back)") {
return;
}
if (choice === "call") {
await callFunction(fn, fnT);
}
if (choice === "treat as instance") {
await instanceOptions(fn, fnT);
}
return functionOptions(fn, fnT);
}
async function callFunction(fn, fnT) {
const {strI, strT} = prettyIT({i: fn, t: fnT});
const inType = fnT.params[0];
const choice = await select({
message: `select parameter for function ${strI} :: ${strT}`,
choices: [
"(go back)",
... [...ctx.instances.getdefault(inType)].flatMap(i => toChoices([i, ctx.types.getdefault(i)])),
],
});
if (choice === "(go back)") {
return;
}
const {i, t} = choice;
await apply(i, fn, fnT);
return callFunction(fn, fnT);
}
async function instanceOptions(i,t) {
const {strI, strT} = prettyIT({i,t});
const choice = await select({
message: `actions for instance ${strI} :: ${strT}`,
choices: [
"(go back)",
"transform",
"list type(s)",
]
})
if (choice === "(go back)") {
return;
}
if (choice === "transform") {
await transform(i, t)
}
if (choice === "list type(s)") {
await listTypes(i);
}
return await instanceOptions(i,t);
}
async function transform(i, t) {
const {strI, strT} = prettyIT({i, t});
console.log(ctx.functionsFrom.getdefault(t));
const choice = await select({
message: `choose transformation to perform on ${strI} :: ${strT}`,
choices: [
"(go back)",
... [...ctx.functionsFrom.getdefault(t)].flatMap(fn => toChoices([fn, ctx.types.getdefault(fn)])),
],
});
if (choice === "(go back)") {
return;
}
const {i:fn,t:fnT} = choice;
await apply(i, fn, fnT);
return transform(i, t);
}
async function apply(i, fn, fnT) {
const result = fn(i);
const resultType = fnT.params[1];
// update context with newly produced value
ctx = ctx.addToCtx({i: result, t: resultType});
const {strI: strResult, strT: strResultType} = prettyIT({i: result, t: resultType});
console.log(`result = ${strResult} :: ${strResultType}`);
return instanceOrTypeOrFnOptions({i: result, t: resultType});
}
topPrompt();