import { fnType } from "../function_registry.js"; import {Type, Function} from "../metacircular.js"; import {Int} from "../primitives/symbols.js"; // 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; } } export const makeListModule = elementType => { // List type depends on elementType // generating it another time, will give the same type (structurally equivalent): const ListOfElement = getListType(elementType); const emptyList = {l:[]}; const get = ls => i => ls.l[i]; const getBoundType = fnType({in: Int, out: elementType}); const getType = fnType({in: ListOfElement, out: getBoundType}); const push = ls => elem => ({l:ls.l.concat([elem])}); const pushBoundType = fnType({in: elementType, out: ListOfElement}); const pushType = fnType({in: ListOfElement, out: pushBoundType}); return [ {i: ListOfElement, t: Type}, {i: emptyList , t: ListOfElement}, {i: get , t: getType}, {i: getType , t: Function}, {i: getBoundType , t: Function}, {i: push , t: pushType}, {i: pushType , t: Function}, {i: pushBoundType, t: Function}, ]; };