add interactive prompt

This commit is contained in:
Joeri Exelmans 2025-03-20 09:54:11 +01:00
parent ce192b49f2
commit 94efde3e65
22 changed files with 599 additions and 138 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
node_modules/

View file

@ -1,6 +1,5 @@
import { Bool, Int } from "../primitives/symbols.js";
import { fnType, lsType } from "../type_registry.js";
import { deepEqual } from "../util.js";
import { deepEqual, pretty } from "../util.js";
export const makeGeneric = callback => {
// type variables to make available:
@ -32,12 +31,11 @@ const occurring = (type, typeVars) => {
return new Set();
}
// merge_int(1, 2) => conflict(1,2)
// merge_list_of_int([1], [2]) => [conflict(1,2)]
import { inspect } from 'node:util';
// merge {i: [1], t: List_of_Int} ->
function pretty(obj) {
return inspect(obj, {colors: true});
}
export const matchGeneric = (
{typeVars: formalTypeVars, type: formalType},

View file

@ -9,8 +9,8 @@ const ListOfByte = lsType(Byte);
const serializeFnType = fnType({in: Serializable, out: ListOfByte});
const deserializeFnType = fnType({in: ListOfByte, out: Serializable});
export const ModuleSerializable = [
export const ModuleSerializable = {l:[
{i: Serializable , t: Type},
{i: serializeFnType , t: Function},
{i: deserializeFnType, t: Function},
];
]};

View file

@ -32,8 +32,8 @@ import {Function} from "../metacircular.js";
export const makeIdFn = typ => {
const Typ_to_Typ = fnType({in: typ, out: typ});
const id = x => x;
return [
return {l:[
{i: id , t: Typ_to_Typ},
{i: Typ_to_Typ, t: Function},
];
]};
};

View file

@ -36,15 +36,15 @@ export const makeSquare = ({i: mul, t: mulFunction}) => {
}
const square = x => mul(x)(x);
const squareFunction = fnType({in: numType, out: numType});
return [
return {l:[
{i: square , t: squareFunction},
{i: squareFunction, t: Function},
];
]};
};
const makeSquareType = fnType({in: Typed, out: Module});
export const ModuleSquare = [
export const ModuleSquare = {l:[
{i: makeSquare , t: makeSquareType},
{i: makeSquareType, t: Function},
];
]};

View file

@ -1,39 +0,0 @@
import {Int, Bool, Double, Byte} from "../primitives/symbols.js";
import { makeListModule } from "../structures/list_common.js";
import { makeProductType } from "../structures/product.js";
import { makeSumType } from "../structures/sum.js";
import { lsType, prodType, sumType } from "../type_registry.js";
const ListOfDouble = lsType(Double);
const ListOfDoubleModule = makeListModule(Double);
const ListOfListOfDouble = lsType(ListOfDouble);
const ListOfListOfDoubleModule = makeListModule(ListOfDouble);
const ListOfByte = lsType(Byte);
const ListOfByteModule = makeListModule(Byte);
export const ModuleValues = [
{i: 0n, t: Int},
{i: 42n, t: Int},
{i: false, t: Bool},
{i: 3.14159265359, t: Double},
{i: {l:[4.2, 7.6]} , t: ListOfDouble},
{i: {l:[{l:[4.2, 7.6]}, {l:[4.3]}]}, t: ListOfListOfDouble},
{i: new Uint8Array([1,2,3]), t: ListOfByte},
// i'm lazy
...ListOfDoubleModule,
...ListOfListOfDoubleModule,
...ListOfByteModule,
...makeProductType(Int, Bool),
...makeSumType(Int, Bool),
{i: {left: 42n, right: true}, t: prodType(Int, Bool)},
{i: {variant: "L", value: 100n}, t: sumType(Int, Bool)},
];

197
main.js
View file

@ -3,92 +3,169 @@ import {ModuleTyped} from "./typed.js";
import {ModuleBool} from "./primitives/bool.js";
import { Double_to_Double_to_Double, ModuleDouble, mulDouble } from "./primitives/double.js";
import {Int_to_Int_to_Int, ModuleInt, mulInt} from "./primitives/int.js";
import {Int} from "./primitives/symbols.js";
import { makeSquare } from "./lib/square.js";
import {makeIdFn} from "./lib/id.js";
import {ModuleValues} from "./lib/values.js";
import {DefaultMap} from "./util.js";
import {DefaultMap, pretty} from "./util.js";
import { ModuleModule } from "./structures/module.js";
import { ModuleList } from "./structures/list.js";
import {Int, Bool, Double, Byte} from "./primitives/symbols.js";
import { makeListModule } from "./structures/list_common.js";
import { makeProductType } from "./structures/product.js";
import { makeSumType } from "./structures/sum.js";
import { lsType, prodType, sumType } from "./type_registry.js";
class Context {
constructor(mod) {
// input type -> Function-signature
this.functionsFrom = new DefaultMap(() => []);
this.functionsTo = new DefaultMap(() => []);
this.types = new DefaultMap(() => []);
this.instances = new DefaultMap(() => []);
for (const {i, t} of mod) {
this.addInstance({i, t});
for (const {i, t} of mod.l) {
this.types.getdefault(i, true).push(t);
this.instances.getdefault(t, true).push(i);
}
const callFunctionOnEveryValue = (fn, fnType, indent=1) => {
const inType = getIn(fnType);
const outType = getOut(fnType);
console.log();
if (fn.name !== "") {
console.log("--".repeat(indent), fn, ':', fnType);
}
for (const i of this.instances.getdefault(inType)) {
try {
const result = fn(i);
console.log("--".repeat(indent+1), i, '->', result);
if (this.types.getdefault(outType).includes(Function)) {
if (indent < 5) {
callFunctionOnEveryValue(result, outType, indent+2);
}
}
} catch (e) {
console.log("--".repeat(indent+1), i, `-> (exception: ${e})`);
}
}
}
for (const fntypes of this.functionsFrom.m.values()) {
for (const fntype of fntypes) {
for (const fn of this.instances.getdefault(fntype)) {
callFunctionOnEveryValue(fn, fntype);
for (const fnType of this.instances.getdefault(Function)) {
for (const fn of this.instances.getdefault(fnType)) {
this.functionsFrom.getdefault(getIn(fnType), true).push(fn);
this.functionsTo.getdefault(getOut(fnType), true).push(fn);
}
}
}
// const callFunctionOnEveryValue = (fn, fnType, indent=1) => {
// const inType = getIn(fnType);
// const outType = getOut(fnType);
// console.log();
// if (fn.name !== "") {
// console.log("--".repeat(indent), fn, ':', fnType);
// }
// for (const i of this.instances.getdefault(inType)) {
// try {
// const result = fn(i);
// console.log("--".repeat(indent+1), i, '->', result);
// if (this.types.getdefault(outType).includes(Function)) {
// if (indent < 5) {
// callFunctionOnEveryValue(result, outType, indent+2);
// }
// }
// } catch (e) {
// console.log("--".repeat(indent+1), i, `-> (exception: ${e})`);
// }
// }
// }
// for (const fntypes of this.functionsFrom.m.values()) {
// for (const fntype of fntypes) {
// for (const fn of this.instances.getdefault(fntype)) {
// callFunctionOnEveryValue(fn, fntype);
// }
// }
// }
// }
}
addInstance({i, t}) {
const arr = this.types.getdefault(i, true);
arr.push(t);
const arrI = this.instances.getdefault(t, true);
arrI.push(i);
if (t === Function) {
const arr = this.functionsFrom.getdefault(getIn(i), true);
arr.push(i);
const arrTo = this.functionsTo.getdefault(getOut(i), true);
arrTo.push(i);
}
else {
}
}
}
const ListOfDouble = lsType(Double);
const ListOfDoubleModule = makeListModule(Double);
const ListOfListOfDouble = lsType(ListOfDouble);
const ListOfListOfDoubleModule = makeListModule(ListOfDouble);
const ListOfByte = lsType(Byte);
const ListOfByteModule = makeListModule(Byte);
const ModuleValues = {l:[
{i: 0n, t: Int},
{i: 42n, t: Int},
{i: false, t: Bool},
{i: 3.14159265359, t: Double},
{i: {l:[4.2, 7.6]} , t: ListOfDouble},
{i: {l:[{l:[4.2, 7.6]}, {l:[4.3]}]}, t: ListOfListOfDouble},
{i: new Uint8Array([1,2,3]), t: ListOfByte},
// i'm lazy
...ListOfDoubleModule.l,
...ListOfListOfDoubleModule.l,
...ListOfByteModule.l,
const ctx = new Context([
...ModuleMetaCircular,
...ModuleTyped,
...makeProductType(Int, Bool).l,
...makeSumType(Int, Bool).l,
{i: {left: 42n, right: true}, t: prodType(Int, Bool)},
{i: {variant: "L", value: 100n}, t: sumType(Int, Bool)},
]};
const ctx = new Context({l:[
...ModuleMetaCircular.l,
...ModuleTyped.l,
// ...ModuleConformable,
// ...ModuleConformanceCheckConforms,
// ...ModuleNum,
// ...ModuleEq,
...ModuleBool,
...ModuleInt,
...ModuleDouble,
...ModuleBool.l,
...ModuleInt.l,
...ModuleDouble.l,
// ...ModuleSquare,
// ...ModuleList,
...makeIdFn(Int),
...makeSquare({i: mulInt, t: Int_to_Int_to_Int}),
...makeSquare({i: mulDouble, t: Double_to_Double_to_Double}),
...ModuleList,
...ModuleValues,
...ModuleModule,
]);
...makeIdFn(Int).l,
...makeSquare({i: mulInt, t: Int_to_Int_to_Int}).l,
...makeSquare({i: mulDouble, t: Double_to_Double_to_Double}).l,
...ModuleList.l,
...ModuleValues.l,
...ModuleModule.l,
]});
import { input, select } from '@inquirer/prompts';
const makeChoice = ([i, t]) => {
return {
value: {i, t: t[0]},
name: pretty(i),
description: `${pretty(i)} :: ${pretty(t[0])}`,
short: `${pretty(i)} :: ${pretty(t[0])}`,
};
}
let {i,t} = await select({
message: "Choose value:",
choices: [...ctx.types.entries()].map(makeChoice),
});
while (true) {
let fn, fnType;
if (ctx.types.getdefault(t).includes(Function)) {
fn = i;
fnType = t;
const s = await select({
message: "Select input for function:",
choices: ctx.instances.getdefault(getIn(t))
.map(i => [i, ctx.types.getdefault(i)])
.map(makeChoice),
});
i = s.i;
t = s.t;
}
else{
fn = await select({
message: "Choose function:",
choices: [...ctx.functionsFrom.getdefault(t).map(fn => ({
value: fn,
name: pretty(fn),
description: `${pretty(fn)} :: ${pretty(ctx.types.getdefault(fn)[0])}`,
short: `${pretty(fn)} :: ${pretty(ctx.types.getdefault(fn)[0])}`,
})
)],
});
fnType = ctx.types.getdefault(fn)[0];
}
const result = fn(i);
t = getOut(fnType);
console.log("result =", result, "::", t);
i = result;
}

View file

@ -10,7 +10,7 @@ export const getOut = fn => fn.out;
// a module is just a set of typed objects
// each 'typed object' is implicitly an instance of TypeLink (defined below)
export const ModuleMetaCircular = [
export const ModuleMetaCircular = {l:[
// TODO? maybe follow Lean so
// Type.{0} : Type.{1}
// Type.{1} : Type.{2}
@ -28,4 +28,4 @@ export const ModuleMetaCircular = [
{i: getIn , t: fnType({in: Function, out: Type})},
{i: getOut, t: fnType({in: Function, out: Type})},
];
]};

5
package.json Normal file
View file

@ -0,0 +1,5 @@
{
"dependencies": {
"@inquirer/prompts": "^7.4.0"
}
}

374
pnpm-lock.yaml generated Normal file
View file

@ -0,0 +1,374 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@inquirer/prompts':
specifier: ^7.4.0
version: 7.4.0
packages:
'@inquirer/checkbox@4.1.4':
resolution: {integrity: sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/confirm@5.1.8':
resolution: {integrity: sha512-dNLWCYZvXDjO3rnQfk2iuJNL4Ivwz/T2+C3+WnNfJKsNGSuOs3wAo2F6e0p946gtSAk31nZMfW+MRmYaplPKsg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/core@10.1.9':
resolution: {integrity: sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/editor@4.2.9':
resolution: {integrity: sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/expand@4.0.11':
resolution: {integrity: sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/figures@1.0.11':
resolution: {integrity: sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==}
engines: {node: '>=18'}
'@inquirer/input@4.1.8':
resolution: {integrity: sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/number@3.0.11':
resolution: {integrity: sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/password@4.0.11':
resolution: {integrity: sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/prompts@7.4.0':
resolution: {integrity: sha512-EZiJidQOT4O5PYtqnu1JbF0clv36oW2CviR66c7ma4LsupmmQlUwmdReGKRp456OWPWMz3PdrPiYg3aCk3op2w==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/rawlist@4.0.11':
resolution: {integrity: sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/search@3.0.11':
resolution: {integrity: sha512-9CWQT0ikYcg6Ls3TOa7jljsD7PgjcsYEM0bYE+Gkz+uoW9u8eaJCRHJKkucpRE5+xKtaaDbrND+nPDoxzjYyew==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/select@4.1.0':
resolution: {integrity: sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
'@inquirer/type@3.0.5':
resolution: {integrity: sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==}
engines: {node: '>=18'}
peerDependencies:
'@types/node': '>=18'
peerDependenciesMeta:
'@types/node':
optional: true
ansi-escapes@4.3.2:
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
engines: {node: '>=8'}
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
chardet@0.7.0:
resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
cli-width@4.1.0:
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
engines: {node: '>= 12'}
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
external-editor@3.1.0:
resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==}
engines: {node: '>=4'}
iconv-lite@0.4.24:
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
engines: {node: '>=0.10.0'}
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
mute-stream@2.0.0:
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
engines: {node: ^18.17.0 || >=20.5.0}
os-tmpdir@1.0.2:
resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==}
engines: {node: '>=0.10.0'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
tmp@0.0.33:
resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==}
engines: {node: '>=0.6.0'}
type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
yoctocolors-cjs@2.1.2:
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
engines: {node: '>=18'}
snapshots:
'@inquirer/checkbox@4.1.4':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/figures': 1.0.11
'@inquirer/type': 3.0.5
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
'@inquirer/confirm@5.1.8':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
'@inquirer/core@10.1.9':
dependencies:
'@inquirer/figures': 1.0.11
'@inquirer/type': 3.0.5
ansi-escapes: 4.3.2
cli-width: 4.1.0
mute-stream: 2.0.0
signal-exit: 4.1.0
wrap-ansi: 6.2.0
yoctocolors-cjs: 2.1.2
'@inquirer/editor@4.2.9':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
external-editor: 3.1.0
'@inquirer/expand@4.0.11':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
yoctocolors-cjs: 2.1.2
'@inquirer/figures@1.0.11': {}
'@inquirer/input@4.1.8':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
'@inquirer/number@3.0.11':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
'@inquirer/password@4.0.11':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
ansi-escapes: 4.3.2
'@inquirer/prompts@7.4.0':
dependencies:
'@inquirer/checkbox': 4.1.4
'@inquirer/confirm': 5.1.8
'@inquirer/editor': 4.2.9
'@inquirer/expand': 4.0.11
'@inquirer/input': 4.1.8
'@inquirer/number': 3.0.11
'@inquirer/password': 4.0.11
'@inquirer/rawlist': 4.0.11
'@inquirer/search': 3.0.11
'@inquirer/select': 4.1.0
'@inquirer/rawlist@4.0.11':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/type': 3.0.5
yoctocolors-cjs: 2.1.2
'@inquirer/search@3.0.11':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/figures': 1.0.11
'@inquirer/type': 3.0.5
yoctocolors-cjs: 2.1.2
'@inquirer/select@4.1.0':
dependencies:
'@inquirer/core': 10.1.9
'@inquirer/figures': 1.0.11
'@inquirer/type': 3.0.5
ansi-escapes: 4.3.2
yoctocolors-cjs: 2.1.2
'@inquirer/type@3.0.5': {}
ansi-escapes@4.3.2:
dependencies:
type-fest: 0.21.3
ansi-regex@5.0.1: {}
ansi-styles@4.3.0:
dependencies:
color-convert: 2.0.1
chardet@0.7.0: {}
cli-width@4.1.0: {}
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
color-name@1.1.4: {}
emoji-regex@8.0.0: {}
external-editor@3.1.0:
dependencies:
chardet: 0.7.0
iconv-lite: 0.4.24
tmp: 0.0.33
iconv-lite@0.4.24:
dependencies:
safer-buffer: 2.1.2
is-fullwidth-code-point@3.0.0: {}
mute-stream@2.0.0: {}
os-tmpdir@1.0.2: {}
safer-buffer@2.1.2: {}
signal-exit@4.1.0: {}
string-width@4.2.3:
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
tmp@0.0.33:
dependencies:
os-tmpdir: 1.0.2
type-fest@0.21.3: {}
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
yoctocolors-cjs@2.1.2: {}

View file

@ -7,9 +7,9 @@ const eqBool = x => y => x === y;
const Bool_to_Bool = fnType({in: Bool, out: Bool});
const Bool_to_Bool_to_Bool = fnType({in: Bool, out: Bool_to_Bool});
export const ModuleBool = [
export const ModuleBool = {l:[
{i: Bool , t: Type },
{i: Bool_to_Bool , t: Function },
{i: Bool_to_Bool_to_Bool , t: Function },
{i: eqBool , t: Bool_to_Bool_to_Bool },
];
]};

View file

@ -7,9 +7,9 @@ const eqByte = x => y => x === y;
const Byte_to_Bool = fnType({in: Byte, out: Bool});
const Byte_to_Byte_to_Bool = fnType({in: Byte, out: Byte_to_Bool});
export const ModuleByte = [
export const ModuleByte = {l:[
{i: Byte , t: Type },
{i: Byte_to_Bool , t: Function },
{i: Byte_to_Byte_to_Bool , t: Function },
{i: eqByte , t: Byte_to_Byte_to_Bool },
];
]};

View file

@ -13,7 +13,7 @@ export const Double_to_Double_to_Double = fnType({in: Double, out: Double_to_Dou
export const Double_to_Double_to_Bool = fnType({in: Double, out: Double_to_Bool});
export const ModuleDouble = [
export const ModuleDouble = {l:[
{i: Double , t: Type },
{i: Double_to_Double_to_Double, t: Function },
@ -24,4 +24,4 @@ export const ModuleDouble = [
{i: addDouble , t: Double_to_Double_to_Double },
{i: mulDouble , t: Double_to_Double_to_Double },
{i: eqDouble , t: Double_to_Double_to_Bool },
];
]};

View file

@ -12,8 +12,11 @@ const Int_to_Bool = fnType({in: Int, out: Bool});
export const Int_to_Int_to_Int = fnType({in: Int, out: Int_to_Int});
export const Int_to_Int_to_Bool = fnType({in: Int, out: Int_to_Bool});
const serialize = x => x.toString();
const deserialize = str => BigInt(str);
export const ModuleInt = [
export const ModuleInt = {l:[
{i: Int , t: Type },
{i: Int_to_Int_to_Int , t: Function },
@ -24,4 +27,4 @@ export const ModuleInt = [
{i: addInt , t: Int_to_Int_to_Int },
{i: mulInt , t: Int_to_Int_to_Int },
{i: eqInt , t: Int_to_Int_to_Bool },
];
]};

17
progress.txt Normal file
View file

@ -0,0 +1,17 @@
status:
- everything is properly typed, up to the meta-circular level
- primitives
- structures: list, product, sum
can compose structures, e.g., create list of list of product of sum of ...
list type is specialized for ListOfByte to use Uint8Array
- generics currently implemented in two ways:
1) similar to "templates" (as in C++):
a generic function or type is a function that takes a Type, and produces a specific variant
2) experimental implementation of polymorphic types and type inferencing
values currently treated as white-box, hardcoded generic types (e.g., list, function) in type inferencing algorithm
todo:
- interfaces via typeclasses?
- type inferencing can be reduced to finding a graph isomorphism?

View file

@ -6,10 +6,10 @@ import { Module } from "./module.js";
const Type_to_Type = fnType({in: Type, out: Type});
const Type_to_Module = fnType({in: Type, out: Module});
export const ModuleList = [
export const ModuleList = {l:[
{i: lsType , t: Type_to_Type},
{i: Type_to_Type , t: Function},
{i: makeListModule, t: Type_to_Module},
{i: Type_to_Module, t: Function},
];
]};

View file

@ -50,20 +50,20 @@ export const makeListModule = elementType => {
if (elementType === Byte) {
// specialization: use Uint8Array instead of JS array
return [
return {l:[
...common,
{i: byteListImpl.emptyList , t: ListOfElement},
{i: byteListImpl.get , t: getFnType},
{i: byteListImpl.put , t: putFnType},
];
]};
}
else {
return [
return {l:[
...common,
{i: emptyList , t: ListOfElement},
{i: get , t: getFnType},
{i: put , t: putFnType},
// {i: push , t: pushFnType},
];
]};
}
};

View file

@ -16,7 +16,7 @@ export const makeProductType = (leftType, rightType) => {
const constructorBoundType = fnType({in: rightType, out: pType});
const constructorType = fnType({in: leftType , out: constructorBoundType});
return [
return {l:[
{i: pType, t: Type},
{i: getLeft , t: leftFnType},
@ -27,5 +27,5 @@ export const makeProductType = (leftType, rightType) => {
{i: constructor , t: constructorType},
{i: constructorType , t: Function},
{i: constructorBoundType, t: Function},
];
]};
};

View file

@ -5,6 +5,8 @@ import { Module } from "./module.js";
const constructorLeft = left => ({variant: "L", value: left });
const constructorRight = right => ({variant: "R", value: right});
// (<uuid>, product(double, double)): product(int, type)
// signature:
// sum-type -> (leftType -> resultType, rightType -> resultType) -> resultType
const match = sum => handlers => sum.variant === "L"
@ -26,13 +28,13 @@ export const makeSumType = (leftType, rightType) => {
fnType({in: rightType, out: returnType}), // handler function for right variant
);
const matchFnType = fnType({in: sType, out: fnType({in: handlersType, out: returnType})});
return [
return {l:[
{i: match , t: matchFnType},
{i: matchFnType, t: Function},
];
]};
};
return [
return {l:[
{i: sType , t: Type},
{i: constructorLeft , t: constructorLeftType},
{i: constructorRight , t: constructorRightType},
@ -40,5 +42,5 @@ export const makeSumType = (leftType, rightType) => {
{i: constructorRightType, t: Function},
{i: makeMatchFn, t: fnType({in: Type, out: Module})},
];
]};
};

View file

@ -62,3 +62,19 @@ export const sumType = (leftType, rightType) => {
return st;
}
}
// const genericTypes = new Map();
// export const genericType = (underlyingType) => {
// if (genericTypes.has(underlyingType)) {
// // only generate each list type once
// // this would not be necessary if we could define our own equality and hash functions on objects in JavaScript.
// return genericTypes.get(underlyingType);
// }
// else {
// const type = {
// generic: underlyingType,
// };
// genericTypes.set(underlyingType, type);
// return type;
// }
// }

View file

@ -8,11 +8,11 @@ const getType = lnk => lnk.t;
const Typed_to_Type = fnType({in: Typed, out: Type});
export const ModuleTyped = [
export const ModuleTyped = {l:[
{i: Typed, t: Type},
{i: Typed_to_Type, t: Function},
{i: getInst, t: Typed_to_Type},
{i: getType, t: Typed_to_Type},
];
]};

View file

@ -40,3 +40,10 @@ export class DefaultMap {
return this.m.entries();
}
}
import { inspect } from 'node:util';
export function pretty(obj) {
return inspect(obj, {colors: true});
}