feat: Template types (#45)

Includes a full implementation of a type-homogeneous Tuple type, using the template types
  feature, as a demonstration/check of its operation.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #45
This commit is contained in:
Glen Whitney 2022-08-05 12:48:57 +00:00
parent fd32ee1f10
commit 845a2354c9
28 changed files with 920 additions and 129 deletions

View file

@ -8,6 +8,7 @@ import * as complex from '../src/complex/all.mjs'
import * as complexAdd from '../src/complex/add.mjs'
import * as complexNegate from '../src/complex/negate.mjs'
import * as complexComplex from '../src/complex/complex.mjs'
import * as bigintAdd from '../src/bigint/add.mjs'
import * as concreteSubtract from '../src/generic/subtract.concrete.mjs'
import * as genericSubtract from '../src/generic/subtract.mjs'
import extendToComplex from '../src/complex/extendToComplex.mjs'
@ -17,9 +18,10 @@ describe('A custom instance', () => {
it("works when partially assembled", () => {
bw.install(complex)
// Not much we can call without any number types:
const i3 = {re: 0, im: 3}
assert.deepStrictEqual(bw.complex(0, 3), i3)
assert.deepStrictEqual(bw.chain(0).complex(3).value, i3)
assert.deepStrictEqual(bw.complex(undefined, undefined), undefined)
assert.deepStrictEqual(
bw.chain(undefined).complex(undefined).value,
undefined)
// Don't have a way to negate things, for example:
assert.throws(() => bw.negate(2), TypeError)
})
@ -33,7 +35,7 @@ describe('A custom instance', () => {
assert.deepStrictEqual(
bw.subtract(16, bw.add(3, bw.complex(0,4), 2)),
math.complex(11, -4)) // note both instances coexist
assert.deepStrictEqual(bw.negate(math.complex(3, '8')).im, -8)
assert.deepStrictEqual(bw.negate(bw.complex(3, '8')).im, -8)
})
it("can be assembled piecemeal", () => {
@ -112,4 +114,30 @@ describe('A custom instance', () => {
math.complex(1n, -3n))
})
it("instantiates templates correctly", () => {
const inst = new PocomathInstance('InstantiateTemplates')
inst.install(numberAdd)
inst.install({typeMerge: {'T,T': ({T}) => (t,u) => 'Merge to ' + T }})
assert.strictEqual(inst.typeMerge(7,6.28), 'Merge to number')
assert.strictEqual(inst.typeMerge(7,6), 'Merge to NumInt')
assert.strictEqual(inst.typeMerge(7.35,6), 'Merge to number')
inst.install(complexAdd)
inst.install(complexComplex)
inst.install(bigintAdd)
assert.strictEqual(
inst.typeMerge(6n, inst.complex(3n, 2n)),
'Merge to GaussianInteger')
assert.strictEqual(
inst.typeMerge(3, inst.complex(4.5,2.1)),
'Merge to Complex')
// The following is the current behavior, since 3 converts to 3+0i
// which is technically the same Complex type as 3n+0ni.
// This should clear up when Complex is templatized
assert.strictEqual(inst.typeMerge(3, inst.complex(3n)), 'Merge to Complex')
// But types that truly cannot be merged should throw a TypeError
// Should add a variation of this with a more usual type once there is
// one not interconvertible with others...
inst.install(genericSubtract)
assert.throws(() => inst.typeMerge(3, undefined), TypeError)
})
})