diff --git a/examples/environment.js b/examples/environment.js index 469d33e..7837f09 100644 --- a/examples/environment.js +++ b/examples/environment.js @@ -1,3 +1,4 @@ +// Little demo that demonstrates interactive exploration of types, instances and transformations. import { module2Env } from "../lib/environment/env.js"; import { newDynamic } from "../lib/primitives/dynamic.js"; @@ -12,7 +13,7 @@ const env = module2Env(ModuleStd); await listInstances(env, Dynamic); -await transform( - env, - newDynamic(emptyList)(lsType(_ => TYPE_VARS[0])), -); +// await transform( +// env, +// newDynamic(emptyList)(lsType(_ => TYPE_VARS[0])), +// ); diff --git a/examples/prompt/prompt.js b/examples/prompt/prompt.js index fbc76fb..938b8ad 100644 --- a/examples/prompt/prompt.js +++ b/examples/prompt/prompt.js @@ -1,3 +1,5 @@ +// The functions in this module prompt the user for actions to perform on types, instances, etc. + import { number, select } from "@inquirer/prompts"; import { getCompatibleInputTypes, getEnabledFunctions, getInstances, growEnv } from "../../lib/environment/env.js"; @@ -11,9 +13,9 @@ import { genUUID } from "../../lib/util/random.js"; const defaultSelectOptions = { pageSize: 13, -} +}; -const proxyDynamic = async (env, dynamic) => { +export const proxyDynamic = async (env, dynamic) => { const newEnv = growEnv(env)(dynamic); const type = getType(dynamic) if (eqType(type)(Type)) { @@ -26,9 +28,9 @@ const proxyDynamic = async (env, dynamic) => { return proxyDynamic(newEnv, getInst(dynamic)); } return listInstanceOptions(newEnv, dynamic); -} +}; -const selectInstance = async (env, type, msg) => { +export const selectInstance = async (env, type, msg) => { const instances = getInstances(env)(type); const choices = foldSet(acc => instance => { return [...acc, { @@ -48,7 +50,7 @@ const selectInstance = async (env, type, msg) => { return createInstance(type); } return choice; -} +}; export const listInstances = async (env, type) => { const choice = await selectInstance(env, type, "instances of"); @@ -57,9 +59,9 @@ export const listInstances = async (env, type) => { } await proxyDynamic(env, newDynamic(choice)(type)); return await listInstances(env, type); -} +}; -const listTypeOptions = async (env, type) => { +export const listTypeOptions = async (env, type) => { const choice = await select({ message: `type ${pretty(type)}:`, choices: [ @@ -87,9 +89,9 @@ const listTypeOptions = async (env, type) => { await listInstanceOptions(newDynamic(type)(Type)); } return await listTypeOptions(env, type); -} +}; -const listInstanceOptions = async (env, dynamic) => { +export const listInstanceOptions = async (env, dynamic) => { const choice = await select({ message: `instance ${pretty(dynamic)}:`, choices: [ @@ -109,9 +111,9 @@ const listInstanceOptions = async (env, dynamic) => { await listTypeOptions(env, getType(dynamic)); } return await listInstanceOptions(env, dynamic); -} +}; -const listFunctionOptions = async (env, dynamic) => { +export const listFunctionOptions = async (env, dynamic) => { const choice = await select({ message: `function ${pretty(dynamic)}:`, choices: [ @@ -126,9 +128,9 @@ const listFunctionOptions = async (env, dynamic) => { if (choice === "call") { await call(env, dynamic); } -} +}; -const createInstance = async (type) => { +export const createInstance = async (type) => { if (eqType(type)(Int)) { const n = await number({ message: `enter an integer (leave empty to go back):`, @@ -185,9 +187,9 @@ export const transform = async (env, dynamic) => { const outValue = getInst(fun)(getInst(dynamic)); await proxyDynamic(env, newDynamic(outValue)(outType)); return transform(env, dynamic); -} +}; -const call = async (env, funDynamic) => { +export const call = async (env, funDynamic) => { const funType = getType(funDynamic); const inTypes = getCompatibleInputTypes(env)(funType); const choice = inTypes.length === 1 @@ -215,4 +217,4 @@ const call = async (env, funDynamic) => { const outValue = getInst(funDynamic)(inValue); await proxyDynamic(envWithInput, newDynamic(outValue)(choice.outType)); return call(env, funDynamic); -} +}; diff --git a/examples/rbtree.js b/examples/rbtree.js index 1ad2369..6b8168f 100644 --- a/examples/rbtree.js +++ b/examples/rbtree.js @@ -9,5 +9,5 @@ console.log( createRBTree() .insert(1) .insert(1) - .insert(2) + .insert(2).begin ); diff --git a/lib/compare/dynamic.js b/lib/compare/dynamic.js index d186487..56bb993 100644 --- a/lib/compare/dynamic.js +++ b/lib/compare/dynamic.js @@ -1,10 +1,12 @@ import { getInst, getType } from "../primitives/dynamic.js"; import { SymbolBool, SymbolBottom, SymbolByte, SymbolChar, SymbolDouble, SymbolDynamic, SymbolInt, SymbolUUID, SymbolType, SymbolUnit, SymbolOrdering } from "../primitives/primitive_types.js"; import { UNBOUND_SYMBOLS } from "../primitives/typevars.js"; +import { symbolDictIterator } from "../structures/dict.types.js"; +import { symbolSetIterator } from "../structures/set.types.js"; import { symbolDict, symbolFunction, symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/type_constructors.js"; import { prettyT } from "../util/pretty.js"; import { compareBools, compareDoubles, compareOrderings, compareStrings, compareSymbols, compareUnits } from "./primitives.js"; -import { compareDicts, compareFunctions, compareLists, compareProducts, compareSets, compareSums } from "./structures.js"; +import { compareDictIterators, compareDicts, compareFunctions, compareLists, compareProducts, compareSetIterators, compareSets, compareSums } from "./structures.js"; import { compareTypes } from "./type.js"; export const compareDynamic = x => y => @@ -28,12 +30,14 @@ const typeSymbolToCmp = new Map([ [SymbolOrdering, compareOrderings], // these functions take extra comparison callbacks: - [symbolFunction, compareFunctions], - [symbolSum , compareSums ], - [symbolProduct , compareProducts ], - [symbolList , compareLists ], - [symbolSet , compareSets ], - [symbolDict , compareDicts ], + [symbolFunction , compareFunctions ], + [symbolSum , compareSums ], + [symbolProduct , compareProducts ], + [symbolList , compareLists ], + [symbolSet , compareSets ], + [symbolDict , compareDicts ], + [symbolSetIterator , compareSetIterators ], + [symbolDictIterator, compareDictIterators], // even though we cannot compare typevar instances, // we still need to give a function or shit will break diff --git a/lib/compare/structures.js b/lib/compare/structures.js index 8e20fcc..31e68ae 100644 --- a/lib/compare/structures.js +++ b/lib/compare/structures.js @@ -1,6 +1,6 @@ // Total ordering of composed types -import { compareDoubles, compareStrings } from "./primitives.js" +import { compareBools, compareDoubles, compareStrings } from "./primitives.js" import { get, length as lengthLs } from "../structures/list.js"; import { read as readSet, length as lengthSet, first as firstSet } from "../structures/set.js"; import { read as readDict, length as lengthDict, first as firstDict } from "../structures/dict.js"; @@ -93,3 +93,40 @@ export const compareDicts = compareKeys => compareValues => x => y => { return iterate(firstDict(x))(firstDict(y)); })(); }; + +export const compareSetIterators = compareElems => x => y => { + // first compare the sets the iterators belong to, + // if the iterators belong to different sets, then they surely are not equal: + const ord = compareSets(compareElems)(x.tree)(y.tree); + if (ord !== 0) { + return ord; // sets differ + } + // sets are equal... + const xIsValid = x !== undefined && x.valid; + const yIsValid = y !== undefined && y.valid; + const ord2 = compareBools(xIsValid)(yIsValid); + if (ord2 !== 0) { + return ord2; // one is valid, the other is not + } + // both iterators are valid... + return compareElems(x.key)(y.key); +}; + +export const compareDictIterators = compareKeys => compareValues => x => y => { + // first compare the sets the iterators belong to, + // if the iterators belong to different sets, then they surely are not equal: + const ord = compareDicts(compareKeys)(compareValues)(x.tree)(y.tree); + if (ord !== 0) { + return ord; // sets differ + } + // sets are equal... + const xIsValid = x !== undefined && x.valid; + const yIsValid = y !== undefined && y.valid; + const ord2 = compareBools(xIsValid)(yIsValid); + if (ord2 !== 0) { + return ord2; // one is valid, the other is not + } + // both iterators are valid... + return compareKeys (x.key )(y.key ) + || compareValues(x.value)(y.value) +};