dope2/type_registry.js

62 lines
2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// This module ensures that we never accidentally create a Symbol for the same type twice.
// Maybe we shouldn't use Symbols for types, but we also cannot use primitive values for types because they may accidentally overlap with 'real' values (that are not types)
// We also cannot use objects for types because similar to Symbols, objects are only equal to themselves if we use them as Map keys.
import { DefaultMap } from "./util.js";
// Global store of function types:
const fnTypes = new DefaultMap(() => new Map());
export const fnType = ({in: inType, out: outType}) => {
const m2 = fnTypes.getdefault(inType, true);
if (m2.has(outType)) {
return m2.get(outType);
}
else {
const fnType = {in: inType, out: outType};
m2.set(outType, fnType);
return fnType;
}
};
// Global store of list types:
const listTypes = new Map();
export function getListType(elementType) {
if (listTypes.has(elementType)) {
// 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 listTypes.get(elementType);
}
else {
const type = Symbol('ListOf:' + elementType.toString());
listTypes.set(elementType, type);
return type;
}
}
// Global store of product types:
const productTypes = new DefaultMap(() => new Map());
export const prodType = (leftType, rightType) => {
const m2 = productTypes.getdefault(leftType, true);
if (m2.has(rightType)) {
return m2.get(rightType);
}
else {
const pt = Symbol(`${leftType.toString()} × ${rightType.toString()}`);
m2.set(rightType, pt);
return pt;
}
}
// Global store of sum types:
const sumTypes = new DefaultMap(() => new Map());
export const sumType = (leftType, rightType) => {
const m2 = sumTypes.getdefault(leftType, true);
if (m2.has(rightType)) {
return m2.get(rightType);
}
else {
const st = Symbol(`${leftType.toString()} + ${rightType.toString()}`);
m2.set(rightType, st);
return st;
}
}