import { fnType, getListType } from "../type_registry.js"; import {Type, Function} from "../metacircular.js"; import {Int, Byte} from "../primitives/symbols.js"; // 'normal' implementation const emptyList = {l:[]}; const get = ls => i => ls.l[i]; const put = ls => i => elem => ({l: ls.l.with(Number(i), elem)}); // const push = ls => elem => ({l:ls.l.concat([elem])}); const byteListImpl = { // specialization emptyList: new Uint8Array(), get: ls => i => ls[i], put: ls => i => elem => { res = new Uint8Array(ls); // creates copy res[i] = elem; return res; } } 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 getFnType1 = fnType({in: Int , out: elementType}); const getFnType = fnType({in: ListOfElement, out: getFnType1}); const putFnType2 = fnType({in: elementType , out: ListOfElement}); const putFnType1 = fnType({in: Int , out: putFnType2}); const putFnType = fnType({in: ListOfElement, out: putFnType1}); // const pushFnType1 = fnType({in: elementType , out: ListOfElement}); // const pushFnType = fnType({in: ListOfElement, out: pushFnType1}); const common = [ {i: ListOfElement, t: Type}, {i: getFnType , t: Function}, {i: getFnType1 , t: Function}, {i: putFnType , t: Function}, {i: putFnType1, t: Function}, {i: putFnType2, t: Function}, // {i: pushFnType , t: Function}, // {i: pushFnType1, t: Function}, ]; if (elementType === Byte) { // specialization: use Uint8Array instead of JS array return [ ...common, {i: byteListImpl.emptyList , t: ListOfElement}, {i: byteListImpl.get , t: getFnType}, {i: byteListImpl.put , t: putFnType}, ]; } else { return [ ...common, {i: emptyList , t: ListOfElement}, {i: get , t: getFnType}, {i: put , t: putFnType}, // {i: push , t: pushFnType}, ]; } };