UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

425 lines (424 loc) 11.5 kB
import { abs, mask } from "../bigint/module.f.js"; import { asBase, asNominal } from "../nominal/module.f.js"; import { length, empty, uint, vec, lsb, msb, repeat, vec8 } from "./module.f.js"; const unsafeVec = (a) => asNominal(a); // 0x8 = 0b1000 = 0 + 8 // 0x9 = 0b1001 = 1 + 8 // 0xA = 0b1010 = 2 + 8 // 0xB = 0b1011 = 3 + 8 // 0xC = 0b1100 = 4 + 8 // 0xD = 0b1101 = 5 + 8 // 0xE = 0b1110 = 6 + 8 // 0xF = 0b1111 = 7 + 8 const assertEq = (a, b) => { if (a !== b) { throw [a, b]; } }; const assertEq2 = ([a0, a1], [b0, b1]) => { assertEq(a0, b0); assertEq(a1, b1); }; const frontTest = (e) => (r0) => (r1) => () => { const vector = vec(8n)(0xf5n); // 0xF5n if (vector !== unsafeVec(0xf5n)) { throw vector; } const result = e.front(4n)(vector); if (result !== r0) { throw result; } const result2 = e.front(16n)(vector); if (result2 !== r1) { throw result2; } }; const popFront = (e) => ([r00, r01]) => ([r10, r11]) => () => { const vector = vec(8n)(0xf5n); // 0xF5n const [result, rest] = e.popFront(4n)(vector); if (result !== r00) { throw result; } if (rest !== unsafeVec(r01)) { throw rest; } const [result2, rest2] = e.popFront(16n)(vector); if (result2 !== r10) { throw result2; } if (rest2 !== unsafeVec(r11)) { throw rest2; } }; const removeFront = (e) => (r0) => (r1) => () => { const v = vec(16n)(0x3456n); // -0xB456n if (v !== unsafeVec(-0xb456n)) { throw v; } const r = e.removeFront(4n)(v); if (r !== r0) { throw r; } const r2 = e.removeFront(24n)(v); if (r2 !== r1) { throw r2; } }; const concat = (e) => (r) => () => { const u8 = vec(8n); const a = u8(0x45n); // -0xC5n if (a !== unsafeVec(-0xc5n)) { throw a; } const b = u8(0x89n); // 0x89n if (b !== unsafeVec(0x89n)) { throw b; } const ab = e.concat(a)(b); // 0x8945n if (ab !== r) { throw ab; } }; export default { examples: { vec: () => { const vec4 = vec(4n); const v0 = vec4(5n); // 0b0101 => -0b1101 if (v0 !== unsafeVec(-0xdn)) { throw v0; } const v1 = vec4(0x5fen); // 0xEn if (v1 !== unsafeVec(0xen)) { throw v1; } }, uint: () => { const vector = vec(8n)(0x5n); // -0x85n if (vector !== unsafeVec(-0x85n)) { throw vector; } const result = uint(vector); // result is 0x5n if (result !== 0x5n) { throw result; } }, front: () => { const vector = vec(8n)(0xf5n); // 0xF5n assertEq(lsb.front(4n)(vector), 5n); assertEq(lsb.front(16n)(vector), 0xf5n); assertEq(msb.front(4n)(vector), 0xfn); assertEq(msb.front(16n)(vector), 0xf500n); }, removeFront: () => { const v = vec(16n)(0x3456n); // -0xB456n assertEq(lsb.removeFront(4n)(v), asNominal(-0xb45n)); assertEq(lsb.removeFront(24n)(v), empty); assertEq(msb.removeFront(4n)(v), asNominal(-0xc56n)); assertEq(msb.removeFront(24n)(v), empty); }, popFront: () => { const vector = vec(8n)(0xf5n); // 0xF5n assertEq2(lsb.popFront(4n)(vector), [5n, asNominal(0xfn)]); assertEq2(lsb.popFront(16n)(vector), [0xf5n, empty]); assertEq2(msb.popFront(4n)(vector), [0xfn, asNominal(-0xdn)]); assertEq2(msb.popFront(16n)(vector), [0xf500n, empty]); }, concat: () => { const u8 = vec(8n); const a = u8(0x45n); // -0xC5n const b = u8(0x89n); // 0x89n assertEq(lsb.concat(a)(b), asNominal(0x8945n)); assertEq(msb.concat(a)(b), asNominal(-0xc589n)); } }, front: { lsbf: frontTest(lsb)(5n)(0xf5n), msbf: frontTest(msb)(0xfn)(0xf500n), }, popFront: { lsbm: popFront(lsb)([5n, 0xfn])([0xf5n, 0n]), msbm: popFront(msb)([0xfn, -0xdn])([0xf500n, 0n]), }, removeFront: { lsbm: removeFront(lsb)(asNominal(-0xb45n))(empty), msbm: removeFront(msb)(asNominal(-0xc56n))(empty), }, concat: { lsbm: concat(lsb)(asNominal(0x8945n)), msbm: concat(msb)(asNominal(-0xc589n)), }, uintLsb: () => { const vector = asNominal(53n); const extract3Bits = lsb.front(3n); const result = extract3Bits(vector); // result is 0b101n (5n) if (result !== 5n) { throw result; } }, uintSmall: () => { const vector = asNominal(1n); const extract3Bits = lsb.front(3n)(vector); if (extract3Bits !== 1n) { throw extract3Bits; } }, vecExample: () => { const createVector = vec(4n); const vector = createVector(5n); // vector is -0b1101n if (vector !== unsafeVec(-13n)) { throw vector; } }, length: () => { const len = length(empty); if (len !== 0n) { throw len; } }, bitset: () => { const v = vec(8n)(0x5fen); if (v !== unsafeVec(0xfen)) { throw v; } if (length(v) !== 8n) { throw 'len'; } const u = lsb.front(8n)(v); if (u !== 0xfen) { throw v; } }, appendBack: () => { const vec8 = vec(8n); const a = vec8(0x345n); const b = vec8(0x789n); const ab = lsb.concat(a)(b); if (ab !== unsafeVec(0x8945n)) { throw ab; } const s = length(ab); if (s !== 16n) { throw `appendBack: ${s}`; } }, removeBack: () => { const v = vec(17n)(0x12345n); if (v !== unsafeVec(0x12345n)) { throw asBase(v).toString(16); } const r = lsb.removeFront(9n)(v); if (r !== unsafeVec(0x91n)) { throw asBase(r).toString(16); } }, uint: [ // 0 () => { const x = uint(asNominal(0n)); if (x !== 0n) { throw x; } }, // 1 () => { const v = asNominal(1n); const x = uint(v); if (x !== 1n) { throw x; } const len = length(v); if (len !== 1n) { throw len; } }, // 2 () => { const v = asNominal(2n); const x = uint(v); if (x !== 2n) { throw x; } const len = length(v); if (len !== 2n) { throw len; } }, // 3 () => { const v = asNominal(3n); const x = uint(v); if (x !== 3n) { throw x; } const len = length(v); if (len !== 2n) { throw len; } }, // 4 () => { const v = asNominal(-1n); const x = uint(v); if (x !== 0n) { throw x; } const len = length(v); if (len !== 1n) { throw len; } }, () => { const v = asNominal(-2n); const x = uint(v); if (x !== 0n) { throw x; } const len = length(v); if (len !== 2n) { throw len; } }, () => { const v = asNominal(-3n); const x = uint(v); if (x !== 1n) { throw x; } const len = length(v); if (len !== 2n) { throw len; } } ], vec: [ // 0 () => { const v = asBase(vec(0n)(0n)); if (v !== 0n) { throw v; } }, () => { const v = asBase(vec(0n)(1n)); if (v !== 0n) { throw v; } }, () => { const v = asBase(vec(0n)(-1n)); if (v !== 0n) { throw v; } }, // 1 () => { const v = asBase(vec(1n)(0n)); if (v !== -1n) { throw v; } }, () => { const v = asBase(vec(1n)(1n)); if (v !== 1n) { throw v; } }, () => { const v = asBase(vec(1n)(-1n)); if (v !== 1n) { throw v; } }, () => { const v = asBase(vec(1n)(2n)); if (v !== -1n) { throw v; } }, () => { const v = asBase(vec(1n)(3n)); if (v !== 1n) { throw v; } } ], both: () => { const c = (len) => (ui) => (raw) => { const v = vec(len)(ui); const x = asBase(v); if (x !== raw) { throw x; } const len2 = length(v); if (len2 !== len) { throw len2; } const u = uint(v); const mui = mask(len) & abs(ui); if (u !== mui) { throw u; } }; // 0n for (const i of [0n, 1n, -1n, 2n, -2n, 3n, -3n]) { c(0n)(i)(0n); } return [ // 1n () => c(1n)(0n)(-1n), () => c(1n)(1n)(1n), () => c(1n)(-11n)(1n), //< overflow // 2n () => c(2n)(0n)(-2n), () => c(2n)(1n)(-3n), () => c(2n)(2n)(2n), () => c(2n)(3n)(3n), () => c(2n)(-7n)(3n), //< overflow ]; }, concat2: () => { const c = (a) => (b) => (abx) => { const ab = msb.concat(a)(b); const abLen = length(ab); const abxLen = length(abx); if (abLen !== abxLen) { throw abLen; } const abU = uint(ab); const abxU = uint(abx); if (abU !== abxU) { throw abU; } }; c(vec(4n)(0xfn))(vec(8n)(0xa7n))(vec(12n)(0xfa7n)); c(vec(4n)(0xfn))(vec(8n)(0x57n))(vec(12n)(0xf57n)); c(vec(4n)(0x5n))(vec(8n)(0xa7n))(vec(12n)(0x5a7n)); c(vec(4n)(0x5n))(vec(8n)(0x79n))(vec(12n)(0x579n)); }, lsbXor: () => { const c = (a) => (b) => (e) => { const r = lsb.xor(a)(b); if (r !== e) { throw r; } }; c(vec(4n)(0x7n))(vec(8n)(0x12n))(vec(8n)(0x7n ^ 0x12n)); }, msbXor: () => { const c = (a) => (b) => (e) => { const r = msb.xor(a)(b); if (r !== e) { throw r; } }; c(vec(4n)(0x7n))(vec(8n)(0x12n))(vec(8n)(0x70n ^ 0x12n)); }, repeat: () => { if (repeat(4n)(vec8(0xa5n)) !== vec(32n)(0xa5a5a5a5n)) { throw 'repeat failed'; } if (repeat(7n)(vec(5n)(0x13n)) !== vec(35n)(21059194483n)) { throw 'repeat failed'; } } };