From fe978c5b417d9a7e2897c603a29f181c5fb75bea Mon Sep 17 00:00:00 2001 From: Joeri Exelmans Date: Sat, 10 May 2025 10:00:31 +0200 Subject: [PATCH] environment includes mapping name -> instance --- examples/prompt/prompt.js | 60 ++++++++++++++++++++++++++------------- lib/environment/env.js | 51 ++++++++++++++++++++++----------- 2 files changed, 75 insertions(+), 36 deletions(-) diff --git a/examples/prompt/prompt.js b/examples/prompt/prompt.js index 938b8ad..201359c 100644 --- a/examples/prompt/prompt.js +++ b/examples/prompt/prompt.js @@ -1,12 +1,12 @@ // The functions in this module prompt the user for actions to perform on types, instances, etc. -import { number, select } from "@inquirer/prompts"; +import { input, number, select } from "@inquirer/prompts"; -import { getCompatibleInputTypes, getEnabledFunctions, getInstances, growEnv } from "../../lib/environment/env.js"; +import { contains, getCompatibleInputTypes, getEnabledFunctions, getInstances, growEnv } from "../../lib/environment/env.js"; import { getInst, getType, newDynamic } from "../../lib/primitives/dynamic.js"; -import { Bool, Double, Int, SymbolDynamic, Type, UUID } from "../../lib/primitives/primitive_types.js"; +import { Bool, Double, Int, symbolDynamic, Type, UUID } from "../../lib/primitives/primitive_types.js"; import { eqType, getSymbol } from "../../lib/primitives/type.js"; -import { fold as foldSet } from "../../lib/structures/set.js"; +import { add, fold as foldSet } from "../../lib/structures/set.js"; import { symbolFunction } from "../../lib/structures/type_constructors.js"; import { pretty, prettyT } from "../../lib/util/pretty.js"; import { genUUID } from "../../lib/util/random.js"; @@ -15,19 +15,32 @@ const defaultSelectOptions = { pageSize: 13, }; +export const addToEnv = async (env, dynamic) => { + if (contains(env)(dynamic)) { + return env; + } + const name = await input({ + message: `enter name for ${pretty(dynamic)} (or leave empty to skip this):`, + }); + if (name === '') { + return env; + } + const newEnv = growEnv(env)(name)(dynamic); + return newEnv; +} + export const proxyDynamic = async (env, dynamic) => { - const newEnv = growEnv(env)(dynamic); const type = getType(dynamic) if (eqType(type)(Type)) { - return listTypeOptions(newEnv, getInst(dynamic)); + return listTypeOptions(env, getInst(dynamic)); } if (getSymbol(type) === symbolFunction) { - return listFunctionOptions(newEnv, dynamic); + return listFunctionOptions(env, dynamic); } - if (getSymbol(type) === SymbolDynamic) { - return proxyDynamic(newEnv, getInst(dynamic)); + if (getSymbol(type) === symbolDynamic) { + return proxyDynamic(env, getInst(dynamic)); } - return listInstanceOptions(newEnv, dynamic); + return listInstanceOptions(env, dynamic); }; export const selectInstance = async (env, type, msg) => { @@ -37,7 +50,10 @@ export const selectInstance = async (env, type, msg) => { value: instance, name: pretty(instance), }]; - })(["(go back)", "(new)"])(instances); + })([ + "(go back)", + "(new)", + ])(instances); const choice = await select({ message: `${msg} ${pretty(type)}:`, choices, @@ -53,11 +69,13 @@ export const selectInstance = async (env, type, msg) => { }; export const listInstances = async (env, type) => { - const choice = await selectInstance(env, type, "instances of"); - if (choice === undefined) { + const instance = await selectInstance(env, type, "instances of"); + if (instance === undefined) { return; } - await proxyDynamic(env, newDynamic(choice)(type)); + const dynamic = newDynamic(instance)(type); + const newEnv = await addToEnv(env, dynamic); + await proxyDynamic(newEnv, dynamic); return await listInstances(env, type); }; @@ -79,14 +97,15 @@ export const listTypeOptions = async (env, type) => { const i = await createInstance(type); if (i !== undefined) { const dynamic = newDynamic(i)(type); - await proxyDynamic(env, dynamic); + const newEnv = await addToEnv(env, dynamic); + await proxyDynamic(newEnv, dynamic); } } if (choice === "list instances") { await listInstances(env, type); } if (choice === "treat as instance") { - await listInstanceOptions(newDynamic(type)(Type)); + await listInstanceOptions(env, newDynamic(type)(Type)); } return await listTypeOptions(env, type); }; @@ -213,8 +232,11 @@ export const call = async (env, funDynamic) => { if (inValue === undefined) { return; } - const envWithInput = growEnv(env)(newDynamic(inValue)(choice.inType)); + const inDynamic = newDynamic(inValue)(choice.inType); + const envWithInput = await addToEnv(env, inDynamic); const outValue = getInst(funDynamic)(inValue); - await proxyDynamic(envWithInput, newDynamic(outValue)(choice.outType)); - return call(env, funDynamic); + const outDynamic = newDynamic(outValue)(choice.outType) + const envWithOutput = await addToEnv(envWithInput, outDynamic); + await proxyDynamic(envWithOutput, outDynamic); + return call(envWithOutput, funDynamic); }; diff --git a/lib/environment/env.js b/lib/environment/env.js index c1d5d4f..d8cc6f2 100644 --- a/lib/environment/env.js +++ b/lib/environment/env.js @@ -4,43 +4,60 @@ import { assignFn, UnifyError } from "../generics/generics.js"; import { getInst, getType, newDynamic } from "../primitives/dynamic.js"; import { Dynamic, Type } from "../primitives/primitive_types.js"; import { getSymbol } from "../primitives/type.js"; -import { emptyDict, get, get as getDict, set as setDict } from "../structures/dict.js"; +import { emptyDict, get, set } from "../structures/dict.js"; import { fold as foldList } from "../structures/list.js"; -import { add, emptySet, fold as foldSet } from "../structures/set.js"; +import { add, emptySet, fold as foldSet, has } from "../structures/set.js"; import { symbolFunction } from "../structures/type_constructors.js"; +import { emptyTrie, insert } from "../util/trie.js"; -const addEntry = env => i => t => { - const setOfInstances = getInstances(env)(t); - return setDict(env)(t)(add(setOfInstances)(i)); +const addEntry = typeDict => i => t => { + const setOfInstances = _getInstances(typeDict)(t); + return set(typeDict)(t)(add(setOfInstances)(i)); }; -export const growEnv = env => dynamic => { +export const emptyEnv = { + typeDict: emptyDict(compareTypes), + name2dyn: emptyTrie, +}; + +export const growEnv = ({typeDict, name2dyn}) => name => dynamic => { const t = getType(dynamic); - const typeDictWithEntry = addEntry(env )(getInst(dynamic))(t ); + const typeDictWithEntry = addEntry(typeDict )(getInst(dynamic))(t ); const typeDictWithType = addEntry(typeDictWithEntry)(t )(Type ); const typeDictWithDynamic = addEntry(typeDictWithType )(dynamic )(Dynamic); - return typeDictWithDynamic + return { + typeDict: typeDictWithDynamic, + name2dyn: insert(name2dyn)(name)(dynamic), + }; }; export const module2Env = module => { - return foldList(typeDict => dynamic => { + return foldList(env => ([name, dynamic]) => { try { - return growEnv(typeDict)(dynamic); + return growEnv(env)(name)(dynamic); } catch (e) { console.log('skip:', e.message); - return typeDict; + return env; } - })(emptyDict(compareTypes))(module); + })(emptyEnv)(module); }; -export const getInstances = env => type => { - return getDict(env)(type) || emptySet(makeCompareFn(type)); +const _getInstances = typeDict => type => { + return get(typeDict)(type) || emptySet(makeCompareFn(type)); }; +export const getInstances = env => type => _getInstances(env.typeDict)(type); + export const getTypes = env => { - return getDict(env)(Type) || emptySet(compareTypes); + return get(env.typeDict)(Type) || emptySet(compareTypes); }; +export const contains = env => dynamic => { + return has + (getInstances(env)(getType(dynamic))) + (getInst(dynamic)); +} + export const getFunctions = env => { const types = getTypes(env); return foldSet(types => type => { @@ -53,7 +70,7 @@ export const getFunctions = env => { newDynamic(fn)(type), ]) ([]) - (getInstances(env)(type)), + (_getInstances(env.typeDict)(type)), ]; } return types; @@ -91,4 +108,4 @@ export const getCompatibleInputTypes = env => funType => { } })([])(allTypes); return inTypes; -} \ No newline at end of file +};