110 lines
3.2 KiB
JavaScript
110 lines
3.2 KiB
JavaScript
import { makeCompareFn } from "../compare/dynamic.js";
|
|
import { compareTypes } from "../compare/type.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, set } from "../structures/dict.js";
|
|
import { fold as foldList } from "../structures/list.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 = typeDict => i => t => {
|
|
const setOfInstances = _getInstances(typeDict)(t);
|
|
return set(typeDict)(t)(add(setOfInstances)(i));
|
|
};
|
|
|
|
export const emptyEnv = {
|
|
typeDict: emptyDict(compareTypes),
|
|
name2dyn: emptyTrie,
|
|
};
|
|
|
|
export const growEnv = ({typeDict, name2dyn}) => name => dynamic => {
|
|
const t = getType(dynamic);
|
|
const typeDictWithEntry = addEntry(typeDict )(getInst(dynamic))(t );
|
|
const typeDictWithType = addEntry(typeDictWithEntry)(t )(Type );
|
|
const typeDictWithDynamic = addEntry(typeDictWithType )(dynamic )(Dynamic);
|
|
return {
|
|
typeDict: typeDictWithDynamic,
|
|
name2dyn: insert(name2dyn)(name)(dynamic),
|
|
};
|
|
};
|
|
|
|
export const module2Env = module => {
|
|
return foldList(env => ([name, dynamic]) => {
|
|
try {
|
|
return growEnv(env)(name)(dynamic);
|
|
} catch (e) {
|
|
console.log('skip:', e.message);
|
|
return env;
|
|
}
|
|
})(emptyEnv)(module);
|
|
};
|
|
|
|
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 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 => {
|
|
if (getSymbol(type) === symbolFunction) {
|
|
return [
|
|
...types,
|
|
...foldSet
|
|
(functions => fn => [
|
|
...functions,
|
|
newDynamic(fn)(type),
|
|
])
|
|
([])
|
|
(_getInstances(env.typeDict)(type)),
|
|
];
|
|
}
|
|
return types;
|
|
})([])(types);
|
|
};
|
|
|
|
// // return list of functions that can be called on 'dynamic'
|
|
// export const getEnabledFunctions = env => dynamic => {
|
|
// const allFunctions = getFunctions(env);
|
|
// const enabled = foldList(enabled => fun => {
|
|
// try {
|
|
// const outType = assignFn(getType(fun), getType(dynamic));
|
|
// return [...enabled, {fun, outType}];
|
|
// } catch (e) {
|
|
// if (!(e instanceof UnifyError)) {
|
|
// throw e;
|
|
// }
|
|
// return enabled;
|
|
// }
|
|
// })([])(allFunctions);
|
|
// return enabled;
|
|
// };
|
|
|
|
export const getCompatibleInputTypes = env => funType => {
|
|
const allTypes = getTypes(env);
|
|
const inTypes = foldSet(types => inType => {
|
|
try {
|
|
const outType = assignFn(funType, inType); // may throw
|
|
return [...types, {inType, outType}];
|
|
} catch (e) {
|
|
if (!(e instanceof UnifyError)) {
|
|
throw e;
|
|
}
|
|
return types;
|
|
}
|
|
})([])(allTypes);
|
|
return inTypes;
|
|
};
|