dope2/lib/environment/env.js

94 lines
No EOL
2.8 KiB
JavaScript

import { makeCompareFn } from "../compare/dynamic.js";
import { compareTypes } from "../compare/type.js";
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 { fold as foldList } from "../structures/list.js";
import { add, emptySet, fold as foldSet } from "../structures/set.js";
import { symbolFunction } from "../structures/type_constructors.js";
const addEntry = env => i => t => {
const setOfInstances = getInstances(env)(t);
return setDict(env)(t)(add(setOfInstances)(i));
};
export const growEnv = env => dynamic => {
const t = getType(dynamic);
const typeDictWithEntry = addEntry(env )(getInst(dynamic))(t );
const typeDictWithType = addEntry(typeDictWithEntry)(t )(Type );
const typeDictWithDynamic = addEntry(typeDictWithType )(dynamic )(Dynamic);
return typeDictWithDynamic
};
export const module2Env = module => {
return foldList(typeDict => dynamic => {
try {
return growEnv(typeDict)(dynamic);
} catch (e) {
console.log('skip:', e.message);
return typeDict;
}
})(emptyDict(compareTypes))(module);
};
export const getInstances = env => type => {
return getDict(env)(type) || emptySet(makeCompareFn(type));
};
export const getTypes = env => {
return getDict(env)(Type) || emptySet(compareTypes);
};
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)(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;
}