move executables to scripts
This commit is contained in:
parent
145835ad5d
commit
d236eca5e5
2 changed files with 66 additions and 6 deletions
60
scripts/int_or_bool.js
Normal file
60
scripts/int_or_bool.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { assign, makeGeneric, unify } from "../generics/generics.js";
|
||||
import { Bool, Int } from "../primitives/types.js";
|
||||
import { constructorLeft, constructorRight, match } from "../structures/sum.js";
|
||||
import { fnType, sumType } from "../structures/types.js";
|
||||
import { pretty } from "../util.js";
|
||||
|
||||
const IntOrBool = sumType(Int)(Bool);
|
||||
|
||||
|
||||
// console.log(int5);
|
||||
|
||||
console.log(pretty(unify(
|
||||
makeGeneric(() => IntOrBool),
|
||||
makeGeneric(a => sumType(Int)(a)),
|
||||
)));
|
||||
|
||||
const cipFunction = (x) => {
|
||||
return match(x)({
|
||||
left: x_as_int => (x_as_int === 5),
|
||||
right: x_as_bool => false,
|
||||
});
|
||||
}
|
||||
|
||||
const cipFunctionType = fnType
|
||||
(IntOrBool) // in
|
||||
(Bool);
|
||||
|
||||
// console.log(cipFunctionType);
|
||||
// console.log(IntOrBool);
|
||||
|
||||
console.log(assign(
|
||||
makeGeneric(() => cipFunctionType),
|
||||
makeGeneric(() => IntOrBool),
|
||||
));
|
||||
|
||||
console.log("calling constructorLeft with Int:");
|
||||
const typeAtCallSite = assign(
|
||||
makeGeneric((a, b) =>
|
||||
fnType
|
||||
(a)
|
||||
(sumType(a)(b))
|
||||
),
|
||||
makeGeneric(() => Int));
|
||||
console.log(pretty(typeAtCallSite));
|
||||
|
||||
|
||||
console.log("calling cipFunction:");
|
||||
console.log(pretty(assign(
|
||||
makeGeneric(() => cipFunctionType),
|
||||
typeAtCallSite,
|
||||
)));
|
||||
|
||||
console.log("valid function calls:");
|
||||
console.log(cipFunction(constructorLeft(5)));
|
||||
console.log(cipFunction(constructorLeft(7)));
|
||||
console.log(cipFunction(constructorRight(true)));
|
||||
|
||||
console.log("invalid function calls:");
|
||||
console.log(cipFunction(5));
|
||||
console.log(cipFunction(constructorLeft("abc")));
|
||||
326
scripts/main.js
Normal file
326
scripts/main.js
Normal 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();
|
||||
Loading…
Add table
Add a link
Reference in a new issue