Compare commits

..

8 Commits

Author SHA1 Message Date
Jos de Jong 6bfd06cafb feat: extract generic parameter from the reflectedType (see #18) 2023-10-18 15:22:21 +02:00
Jos de Jong 0cdc9aba78 chore: fix typo in type definition of `FunctionDef` 2023-10-18 15:11:54 +02:00
Glen Whitney 40146c2f48 feat: Runtime type reflection (#17)
Now each behavior specification "knows" its type information.
  Also bumps version number and sets up so that the scripts will run on Windows as well as Unix (thanks to Jos).
  Resolves #5.
  Resolves #16.

Co-authored-by: Jos de Jong <wjosdejong@gmail.com>
Reviewed-on: #17
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-committed-by: Glen Whitney <glen@studioinfinity.org>
2023-10-17 22:02:18 +00:00
Glen Whitney 180e772dab fix: Add types first and distinguish them semantically. (#15)
Rather than via some format on the name of the identifier, this commit
  changes the construction of Dispatcher to assume that functions are
  implementations and other objects are type specifiers.

  Also installs all types first, before any implementations.
  Resolves #3.
  Resolves #12.

Reviewed-on: #15
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-committed-by: Glen Whitney <glen@studioinfinity.org>
2023-08-26 02:15:59 +00:00
Glen Whitney 327a9385ed fix: Use intersection of matching types in AssociatedTypes<> lookup (#14)
Resolves #11.
Reviewed-on: #14
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-committed-by: Glen Whitney <glen@studioinfinity.org>
2023-08-23 16:52:16 +00:00
Glen Whitney 76e144bc2a feat: add build script (#13)
This commit adds pnpm scripts for compiling and running the
  typocomath package, and a convenience script `pnpm go` that does
  both in succession. It also configure pnpm to use a shell
  emulator so that it should work on Windows as well. Finally,
  it changes the directory for object files from obj to build.
  Resolves #9.

Reviewed-on: #13
Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-committed-by: Glen Whitney <glen@studioinfinity.org>
2023-08-23 03:20:10 +00:00
Glen Whitney f06943ba1a chore: Update to latest TypeScript and make sure instructions work 2023-08-18 10:36:11 -07:00
Glen Whitney cc1e66c054 Declare implementations and dependencies via standard interfaces for operations (#8)
Adds a new subdirectory `interfaces` where standard interfaces
  are defined. Additional interfaces for a given operation can
  be added with an `AliasOf` type operator. Provides type
  operators that give the return type, full function type, and
  the type of a dependency on, a given operator.

  Resolves #6.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Co-authored-by: Jos de Jong <wjosdejong@gmail.com>
Reviewed-on: #8
2023-01-22 01:34:57 +00:00
29 changed files with 1627 additions and 396 deletions

5
.gitignore vendored
View File

@ -2,7 +2,7 @@
*~
# Typescript
# emitted code
obj
build
# ---> Node
# Logs
@ -129,6 +129,9 @@ dist
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# Webstorm
.idea
# yarn v2
.yarn/cache
.yarn/unplugged

1
.npmrc Normal file
View File

@ -0,0 +1 @@
shell-emulator=true

View File

@ -1,3 +1,14 @@
# typocomath
A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state.
A final (?) prototype for a refactor of mathjs, culminating the picomath, pocomath, typomath series. Provides an extensible core with "fuzzy" types for its operations, that can at any time generate exact .d.ts file for its current state.
Convenience scripts:
* `pnpm build` -- compile the package
* `pnpm exec` -- run the compiled code produced by `pnpm build`
* `pnpm go` -- both of the above in sequence.
Important installation note:
after `pnpm install`, you must execute `npx ts-patch install` to activate the ts-macros compiler plugin.

1
etc/package.json Normal file
View File

@ -0,0 +1 @@
{"type": "module"}

View File

@ -1,11 +1,16 @@
{
name: 'typocomath',
version: '0.0.1',
version: '0.0.2',
description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept',
main: 'index.ts',
scripts: {
test: 'echo "Error: no test specified" && exit 1',
build: 'mkdirp build && cpy etc/package.json build --flat && tsc',
start: 'node build',
go: 'pnpm clean && pnpm build && pnpm start',
clean: 'del-cli build',
},
packageManager: 'pnpm',
keywords: [
'math',
'algebra',
@ -18,6 +23,13 @@
url: 'https://code.studioinfinity.org/glen/typocomath.git',
},
devDependencies: {
typescript: '^4.9.3',
'@types/node': '20.8.4',
'cpy-cli': '5.0.0',
'del-cli': '5.1.0',
mkdirp: '3.0.1',
'source-map': '0.7.4',
'ts-macros': '2.6.0',
'ts-patch': '3.0.2',
typescript: '5.1.6',
},
}

View File

@ -1,15 +1,920 @@
lockfileVersion: 5.4
lockfileVersion: '6.0'
specifiers:
typescript: ^4.9.3
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
devDependencies:
typescript: 4.9.3
'@types/node':
specifier: 20.8.4
version: 20.8.4
cpy-cli:
specifier: 5.0.0
version: 5.0.0
del-cli:
specifier: 5.1.0
version: 5.1.0
mkdirp:
specifier: 3.0.1
version: 3.0.1
source-map:
specifier: 0.7.4
version: 0.7.4
ts-macros:
specifier: 2.6.0
version: 2.6.0(typescript@5.1.6)
ts-patch:
specifier: 3.0.2
version: 3.0.2
typescript:
specifier: 5.1.6
version: 5.1.6
packages:
/typescript/4.9.3:
resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
engines: {node: '>=4.2.0'}
/@babel/code-frame@7.22.13:
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.22.20
chalk: 2.4.2
dev: true
/@babel/helper-validator-identifier@7.22.20:
resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/highlight@7.22.20:
resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.20
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.stat': 2.0.5
run-parallel: 1.2.0
dev: true
/@nodelib/fs.stat@2.0.5:
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
dev: true
/@nodelib/fs.walk@1.2.8:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.15.0
dev: true
/@types/minimist@1.2.2:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true
/@types/node@20.8.4:
resolution: {integrity: sha512-ZVPnqU58giiCjSxjVUESDtdPk4QR5WQhhINbc9UBrKLU68MX5BF6kbQzTrkwbolyr0X8ChBpXfavr5mZFKZQ5A==}
dependencies:
undici-types: 5.25.3
dev: true
/@types/normalize-package-data@2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
dev: true
/aggregate-error@4.0.1:
resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==}
engines: {node: '>=12'}
dependencies:
clean-stack: 4.2.0
indent-string: 5.0.0
dev: true
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
dev: true
/ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
dependencies:
color-convert: 1.9.3
dev: true
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
dev: true
/arrify@1.0.1:
resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
engines: {node: '>=0.10.0'}
dev: true
/arrify@3.0.0:
resolution: {integrity: sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==}
engines: {node: '>=12'}
dev: true
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: true
/brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
dev: true
/braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
dependencies:
fill-range: 7.0.1
dev: true
/camelcase-keys@7.0.2:
resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==}
engines: {node: '>=12'}
dependencies:
camelcase: 6.3.0
map-obj: 4.3.0
quick-lru: 5.1.1
type-fest: 1.4.0
dev: true
/camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
dev: true
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: true
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
dev: true
/clean-stack@4.2.0:
resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==}
engines: {node: '>=12'}
dependencies:
escape-string-regexp: 5.0.0
dev: true
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: true
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
dev: true
/color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
/concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: true
/cp-file@10.0.0:
resolution: {integrity: sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg==}
engines: {node: '>=14.16'}
dependencies:
graceful-fs: 4.2.11
nested-error-stacks: 2.1.1
p-event: 5.0.1
dev: true
/cpy-cli@5.0.0:
resolution: {integrity: sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ==}
engines: {node: '>=16'}
hasBin: true
dependencies:
cpy: 10.1.0
meow: 12.1.1
dev: true
/cpy@10.1.0:
resolution: {integrity: sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ==}
engines: {node: '>=16'}
dependencies:
arrify: 3.0.0
cp-file: 10.0.0
globby: 13.2.2
junk: 4.0.1
micromatch: 4.0.5
nested-error-stacks: 2.1.1
p-filter: 3.0.0
p-map: 6.0.0
dev: true
/decamelize-keys@1.1.1:
resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
engines: {node: '>=0.10.0'}
dependencies:
decamelize: 1.2.0
map-obj: 1.0.1
dev: true
/decamelize@1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
dev: true
/decamelize@5.0.1:
resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==}
engines: {node: '>=10'}
dev: true
/del-cli@5.1.0:
resolution: {integrity: sha512-xwMeh2acluWeccsfzE7VLsG3yTr7nWikbfw+xhMnpRrF15pGSkw+3/vJZWlGoE4I86UiLRNHicmKt4tkIX9Jtg==}
engines: {node: '>=14.16'}
hasBin: true
dependencies:
del: 7.1.0
meow: 10.1.5
dev: true
/del@7.1.0:
resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==}
engines: {node: '>=14.16'}
dependencies:
globby: 13.2.2
graceful-fs: 4.2.11
is-glob: 4.0.3
is-path-cwd: 3.0.0
is-path-inside: 4.0.0
p-map: 5.5.0
rimraf: 3.0.2
slash: 4.0.0
dev: true
/dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
dependencies:
path-type: 4.0.0
dev: true
/error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
is-arrayish: 0.2.1
dev: true
/escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
dev: true
/escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
dev: true
/fast-glob@3.3.1:
resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
engines: {node: '>=8.6.0'}
dependencies:
'@nodelib/fs.stat': 2.0.5
'@nodelib/fs.walk': 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
micromatch: 4.0.5
dev: true
/fastq@1.15.0:
resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==}
dependencies:
reusify: 1.0.4
dev: true
/fill-range@7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
dependencies:
to-regex-range: 5.0.1
dev: true
/find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
dependencies:
locate-path: 6.0.0
path-exists: 4.0.0
dev: true
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.3
dev: true
/glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: true
/global-prefix@3.0.0:
resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==}
engines: {node: '>=6'}
dependencies:
ini: 1.3.8
kind-of: 6.0.3
which: 1.3.1
dev: true
/globby@13.2.2:
resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
dir-glob: 3.0.1
fast-glob: 3.3.1
ignore: 5.2.4
merge2: 1.4.1
slash: 4.0.0
dev: true
/graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
dev: true
/hard-rejection@2.1.0:
resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
engines: {node: '>=6'}
dev: true
/has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
dev: true
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: true
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/hosted-git-info@4.1.0:
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
engines: {node: '>=10'}
dependencies:
lru-cache: 6.0.0
dev: true
/ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'}
dev: true
/indent-string@5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
dev: true
/inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: true
/inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
dev: true
/is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
dev: true
/is-core-module@2.13.0:
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
dependencies:
has: 1.0.3
dev: true
/is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
dev: true
/is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
dependencies:
is-extglob: 2.1.1
dev: true
/is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
dev: true
/is-path-cwd@3.0.0:
resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true
/is-path-inside@4.0.0:
resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==}
engines: {node: '>=12'}
dev: true
/is-plain-obj@1.1.0:
resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
engines: {node: '>=0.10.0'}
dev: true
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
/json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
/junk@4.0.1:
resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==}
engines: {node: '>=12.20'}
dev: true
/kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
dev: true
/lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true
/locate-path@6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
dependencies:
p-locate: 5.0.0
dev: true
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
dependencies:
yallist: 4.0.0
dev: true
/map-obj@1.0.1:
resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
engines: {node: '>=0.10.0'}
dev: true
/map-obj@4.3.0:
resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
engines: {node: '>=8'}
dev: true
/meow@10.1.5:
resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
'@types/minimist': 1.2.2
camelcase-keys: 7.0.2
decamelize: 5.0.1
decamelize-keys: 1.1.1
hard-rejection: 2.1.0
minimist-options: 4.1.0
normalize-package-data: 3.0.3
read-pkg-up: 8.0.0
redent: 4.0.0
trim-newlines: 4.1.1
type-fest: 1.4.0
yargs-parser: 20.2.9
dev: true
/meow@12.1.1:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
dev: true
/merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
dev: true
/micromatch@4.0.5:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
dependencies:
braces: 3.0.2
picomatch: 2.3.1
dev: true
/min-indent@1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
dev: true
/minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
brace-expansion: 1.1.11
dev: true
/minimist-options@4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'}
dependencies:
arrify: 1.0.1
is-plain-obj: 1.1.0
kind-of: 6.0.3
dev: true
/minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true
/mkdirp@3.0.1:
resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
engines: {node: '>=10'}
hasBin: true
dev: true
/nested-error-stacks@2.1.1:
resolution: {integrity: sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==}
dev: true
/normalize-package-data@3.0.3:
resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
engines: {node: '>=10'}
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.13.0
semver: 7.5.4
validate-npm-package-license: 3.0.4
dev: true
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
wrappy: 1.0.2
dev: true
/p-event@5.0.1:
resolution: {integrity: sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
p-timeout: 5.1.0
dev: true
/p-filter@3.0.0:
resolution: {integrity: sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
p-map: 5.5.0
dev: true
/p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
dependencies:
yocto-queue: 0.1.0
dev: true
/p-locate@5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
dependencies:
p-limit: 3.1.0
dev: true
/p-map@5.5.0:
resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
engines: {node: '>=12'}
dependencies:
aggregate-error: 4.0.1
dev: true
/p-map@6.0.0:
resolution: {integrity: sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==}
engines: {node: '>=16'}
dev: true
/p-timeout@5.1.0:
resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==}
engines: {node: '>=12'}
dev: true
/parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
'@babel/code-frame': 7.22.13
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
dev: true
/path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
dev: true
/path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
dev: true
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: true
/picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
dev: true
/queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
/quick-lru@5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
dev: true
/read-pkg-up@8.0.0:
resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==}
engines: {node: '>=12'}
dependencies:
find-up: 5.0.0
read-pkg: 6.0.0
type-fest: 1.4.0
dev: true
/read-pkg@6.0.0:
resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==}
engines: {node: '>=12'}
dependencies:
'@types/normalize-package-data': 2.4.1
normalize-package-data: 3.0.3
parse-json: 5.2.0
type-fest: 1.4.0
dev: true
/redent@4.0.0:
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
engines: {node: '>=12'}
dependencies:
indent-string: 5.0.0
strip-indent: 4.0.0
dev: true
/resolve@1.22.4:
resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==}
hasBin: true
dependencies:
is-core-module: 2.13.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
dev: true
/reusify@1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
/rimraf@3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
dependencies:
glob: 7.2.3
dev: true
/run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
queue-microtask: 1.2.3
dev: true
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
engines: {node: '>=10'}
hasBin: true
dependencies:
lru-cache: 6.0.0
dev: true
/slash@4.0.0:
resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
engines: {node: '>=12'}
dev: true
/source-map@0.7.4:
resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==}
engines: {node: '>= 8'}
dev: true
/spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
dependencies:
spdx-expression-parse: 3.0.1
spdx-license-ids: 3.0.15
dev: true
/spdx-exceptions@2.3.0:
resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
dev: true
/spdx-expression-parse@3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
dependencies:
spdx-exceptions: 2.3.0
spdx-license-ids: 3.0.15
dev: true
/spdx-license-ids@3.0.15:
resolution: {integrity: sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==}
dev: true
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
dev: true
/strip-indent@4.0.0:
resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==}
engines: {node: '>=12'}
dependencies:
min-indent: 1.0.1
dev: true
/supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
dependencies:
has-flag: 3.0.0
dev: true
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
dev: true
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
dev: true
/to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
dependencies:
is-number: 7.0.0
dev: true
/trim-newlines@4.1.1:
resolution: {integrity: sha512-jRKj0n0jXWo6kh62nA5TEh3+4igKDXLvzBJcPpiizP7oOolUrYIxmVBG9TOtHYFHoddUk6YvAkGeGoSVTXfQXQ==}
engines: {node: '>=12'}
dev: true
/ts-macros@2.6.0(typescript@5.1.6):
resolution: {integrity: sha512-X7c4rHPTpBYY+MJUkIDIQMbTPAcv1y1sylrnDMsTvcbImleT4Wlheg3wNbORwnX8Zvq2ldZnttNXcZ1a0VE2Kg==}
hasBin: true
peerDependencies:
typescript: 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x
dependencies:
typescript: 5.1.6
yargs-parser: 21.1.1
dev: true
/ts-patch@3.0.2:
resolution: {integrity: sha512-iTg8euqiNsNM1VDfOsVIsP0bM4kAVXU38n7TGQSkky7YQX/syh6sDPIRkvSS0HjT8ZOr0pq1h+5Le6jdB3hiJQ==}
hasBin: true
dependencies:
chalk: 4.1.2
global-prefix: 3.0.0
minimist: 1.2.8
resolve: 1.22.4
semver: 7.5.4
strip-ansi: 6.0.1
dev: true
/type-fest@1.4.0:
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
engines: {node: '>=10'}
dev: true
/typescript@5.1.6:
resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==}
engines: {node: '>=14.17'}
hasBin: true
dev: true
/undici-types@5.25.3:
resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==}
dev: true
/validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
dev: true
/which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
dependencies:
isexe: 2.0.0
dev: true
/wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: true
/yargs-parser@20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
dev: true
/yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
dev: true
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true

View File

@ -1,10 +1,6 @@
import {ForType} from '../core/Dispatcher.js'
import {ComplexImpTypes} from './type.js'
import * as Complex from './native.js'
import * as complex from './arithmetic.js'
export { complex }
export {Complex}
declare module "../core/Dispatcher" {
interface ImpTypes<T>
extends ForType<'Complex', ComplexImpTypes<T>> {}
}

View File

@ -1,110 +1,88 @@
import {Complex, UnderlyingReal, complex_binary} from './type.js'
import {Dependency, ImpType} from '../core/Dispatcher.js'
import {Complex} from './type.js'
import type {
Dependencies, Signature, Returns, RealType, AliasOf
} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
type ComplexUnary<T> =
T extends Complex<infer R> ? (a: Complex<R>) => Complex<R> : never
type ComplexBinary<T> =
T extends Complex<infer R>
? (a: Complex<R>, b: Complex<R>) => Complex<R>
: never
type ComplexReal<T> = T extends Complex<infer R>
? (a: Complex<R>, b: UnderlyingReal<R>) => Complex<R>
: never
declare module "./type" {
interface ComplexImpTypes<T> {
add: ComplexBinary<T>
add_real: ComplexReal<T>
unaryMinus: ComplexUnary<T>
conj: ComplexUnary<T>
subtract: ComplexBinary<T>
multiply: ComplexBinary<T>
absquare: T extends Complex<infer R> ? (a: T) => UnderlyingReal<R> : never
reciprocal: ComplexUnary<T>
divide: ComplexBinary<T>
divide_real: ComplexReal<T>
// square root that remains the same type
conservativeSqrt: ComplexUnary<T>
// Same as conservativeSqrt for complex numbers:
sqrt: ComplexUnary<T>
declare module "../interfaces/type" {
interface Signatures<T> {
addReal: AliasOf<'add', (a: T, b: RealType<T>) => T>
divideReal: AliasOf<'divide', (a: T, b: RealType<T>) => T>
}
}
export const add =
<T>(dep: Dependency<'add', [T,T]>):
ImpType<'add', [Complex<T>, Complex<T>]> =>
(w, z) => complex_binary(dep.add(w.re, z.re), dep.add(w.im, z.im))
<T>(dep: Dependencies<'add' | 'complex', T>): Signature<'add', Complex<T>> =>
(w, z) => dep.complex(dep.add(w.re, z.re), dep.add(w.im, z.im))
export const add_real =
<T>(dep: Dependency<'add_real', [T, UnderlyingReal<T>]>):
ImpType<'add_real', [Complex<T>, UnderlyingReal<T>]> =>
(z, r) => complex_binary(dep.add_real(z.re, r), z.im)
export const addReal =
<T>(dep: Dependencies<'addReal' | 'complex', T>):
Signature<'addReal', Complex<T>> =>
(z, r) => dep.complex(dep.addReal(z.re, r), z.im)
export const unaryMinus =
<T>(dep: Dependency<'unaryMinus', [T]>):
ImpType<'unaryMinus', [Complex<T>]> =>
z => complex_binary(dep.unaryMinus(z.re), dep.unaryMinus(z.im))
<T>(dep: Dependencies<'unaryMinus' | 'complex', T>):
Signature<'unaryMinus', Complex<T>> =>
z => dep.complex(dep.unaryMinus(z.re), dep.unaryMinus(z.im))
export const conj =
<T>(dep: Dependency<'unaryMinus'|'conj', [T]>):
ImpType<'conj', [Complex<T>]> =>
z => complex_binary(dep.conj(z.re), dep.unaryMinus(z.im))
<T>(dep: Dependencies<'unaryMinus' | 'conj' | 'complex', T>):
Signature<'conj', Complex<T>> =>
z => dep.complex(dep.conj(z.re), dep.unaryMinus(z.im))
export const subtract =
<T>(dep: Dependency<'subtract', [T,T]>):
ImpType<'subtract', [Complex<T>, Complex<T>]> =>
(w, z) => complex_binary(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im))
<T>(dep: Dependencies<'subtract' | 'complex', T>):
Signature<'subtract', Complex<T>> =>
(w, z) => dep.complex(dep.subtract(w.re, z.re), dep.subtract(w.im, z.im))
export const multiply =
<T>(dep: Dependency<'add', [T,T]>
& Dependency<'subtract', [T,T]>
& Dependency<'multiply', [T,T]>
& Dependency<'conj', [T]>):
ImpType<'multiply', [Complex<T>, Complex<T>]> =>
<T>(dep: Dependencies<
'add' | 'subtract' | 'multiply' | 'conj' | 'complex', T>):
Signature<'multiply', Complex<T>> =>
(w, z) => {
const mult = dep.multiply
const realpart = dep.subtract(
mult( w.re, z.re), mult(dep.conj(w.im), z.im))
const imagpart = dep.add(
mult(dep.conj(w.re), z.im), mult( w.im, z.re))
return complex_binary(realpart, imagpart)
return dep.complex(realpart, imagpart)
}
export const absquare =
<T>(dep: Dependency<'absquare', [T]>
& Dependency<'add', [UnderlyingReal<T>, UnderlyingReal<T>]>):
ImpType<'absquare', [Complex<T>]> =>
<T>(dep: Dependencies<'absquare', T>
& Dependencies<'add', Returns<'absquare', T>>):
Signature<'absquare', Complex<T>> =>
z => dep.add(dep.absquare(z.re), dep.absquare(z.im))
export const divide_real =
<T>(dep: Dependency<'divide_real', [T, UnderlyingReal<T>]>):
ImpType<'divide_real', [Complex<T>, UnderlyingReal<T>]> =>
(z, r) => complex_binary(
dep.divide_real(z.re, r), dep.divide_real(z.im, r))
export const divideReal =
<T>(dep: Dependencies<'divideReal' | 'complex', T>):
Signature<'divideReal', Complex<T>> =>
(z, r) => dep.complex(dep.divideReal(z.re, r), dep.divideReal(z.im, r))
export const reciprocal =
<T>(dep: Dependency<'conj', [Complex<T>]>
& Dependency<'absquare', [Complex<T>]>
& Dependency<'divide_real', [Complex<T>, UnderlyingReal<T>]>):
ImpType<'reciprocal', [Complex<T>]> =>
z => dep.divide_real(dep.conj(z), dep.absquare(z))
<T>(dep: Dependencies<'conj' | 'absquare' | 'divideReal', Complex<T>>):
Signature<'reciprocal', Complex<T>> =>
z => dep.divideReal(dep.conj(z), dep.absquare(z))
export const divide =
<T>(dep: Dependency<'multiply', [Complex<T>, Complex<T>]>
& Dependency<'reciprocal', [Complex<T>]>):
ImpType<'divide', [Complex<T>, Complex<T>]> =>
<T>(dep: Dependencies<'multiply' | 'reciprocal', Complex<T>>):
Signature<'divide', Complex<T>> =>
(w, z) => dep.multiply(w, dep.reciprocal(z))
// The dependencies are slightly tricky here, because there are three types
// involved: Complex<T>, T, and RealType<T>, all of which might be different,
// and we have to get it straight which operations we need on each type, and
// in fact, we need `addReal` on both T and Complex<T>, hence the dependency
// with a custom name, not generated via Dependencies<...>
export const sqrt =
<T>(dep: Dependency<'absquare' | 're', [Complex<T>]>
& Dependency<'conservativeSqrt' | 'unaryMinus', [UnderlyingReal<T>]>
& Dependency<'divide_real', [Complex<T>, UnderlyingReal<T>]>
& Dependency<'add_real', [T, UnderlyingReal<T>]>
& {add_complex_real:
ImpType<'add_real', [Complex<T>, UnderlyingReal<T>]>}
& Dependency<'equal' | 'add', [UnderlyingReal<T>, UnderlyingReal<T>]>
& Dependency<'complex', [T, T]>
& Dependency<'zero', [T]>
): ImpType<'sqrt', [Complex<T>]> =>
<T>(dep: Dependencies<'equal' | 'conservativeSqrt' | 'unaryMinus', RealType<T>>
& Dependencies<'zero' | 'complex', T>
& Dependencies<'absquare' | 're' | 'divideReal', Complex<T>>
& {
addTR: Signature<'addReal', T>,
addRR: Signature<'add', RealType<T>>,
addCR: Signature<'addReal', Complex<T>>
}): Signature<'sqrt', Complex<T>> =>
z => {
const myabs = dep.conservativeSqrt(dep.absquare(z))
const r = dep.re(z)
@ -112,13 +90,15 @@ export const sqrt =
if (dep.equal(myabs, negr)) {
// pure imaginary square root; z.im already zero
return dep.complex(
dep.zero(z.re), dep.add_real(z.im, dep.conservativeSqrt(negr)))
dep.zero(z.re), dep.addTR(z.im, dep.conservativeSqrt(negr)))
}
const num = dep.add_complex_real(z, myabs)
const denomsq = dep.add(dep.add(myabs, myabs), dep.add(r, r))
const num = dep.addCR(z, myabs)
const denomsq = dep.addRR(dep.addRR(myabs, myabs), dep.addRR(r, r))
const denom = dep.conservativeSqrt(denomsq)
return dep.divide_real(num, denom)
return dep.divideReal(num, denom)
}
export const conservativeSqrt = sqrt
$reflect!([
add, addReal, unaryMinus, conj, subtract, multiply, absquare, divideReal,
reciprocal, divide, sqrt
])

View File

@ -1,4 +1 @@
export * from './type.js'
export * from './arithmetic.js'
export * from './predicate.js'
export * from './relational.js'

View File

@ -1,21 +1,13 @@
import {Complex} from './type.js'
import {Dependency, ImpType} from '../core/Dispatcher.js'
type ComplexPredicate<T> = T extends Complex<any> ? (a: T) => boolean : never
declare module "./type" {
interface ComplexImpTypes<T> {
isReal: ComplexPredicate<T>
isSquare: ComplexPredicate<T>
}
}
import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const isReal =
<T>(dep: Dependency<'equal', [T,T]>
& Dependency<'add', [T,T]>
& Dependency<'isReal', [T]>
): ImpType<'isReal', [Complex<T>]> =>
<T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>):
Signature<'isReal', Complex<T>> =>
z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im))
export const isSquare: ImpType<'isSquare', [Complex<any>]> =
export const isSquare = (): Signature<'isSquare', Complex<unknown>> =>
z => true // FIXME: not correct for Complex<bigint> once we get there
$reflect!([isReal, isSquare])

View File

@ -1,16 +1,8 @@
import {Complex} from './type.js'
import {ImpType, Dependency} from '../core/Dispatcher.js'
type ComplexRelation<T> =
T extends Complex<any> ? (a: T, b: T) => boolean : never
declare module "./type" {
interface ComplexImpTypes<T> {
equal: ComplexRelation<T>
}
}
import {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const equal =
<T>(dep: Dependency<'equal', [T,T]>):
ImpType<'equal', [Complex<T>, Complex<T>]> =>
<T>(dep: Dependencies<'equal', T>): Signature<'equal', Complex<T>> =>
(w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im)
$reflect!([equal])

View File

@ -1,58 +1,67 @@
import {
joinTypes, typeOfDependency, Dependency, ImpType, ImpReturns
} from '../core/Dispatcher.js'
import {joinTypes, typeOfDependency} from '../core/Dispatcher.js'
import type {
ZeroType, OneType, NaNType, Dependencies, Signature, Returns
} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export type Complex<T> = {re: T; im: T;}
export type UnderlyingReal<T> =
T extends Complex<infer U> ? UnderlyingReal<U> : T
export type Complex<T> = { re: T; im: T; }
export const Complex_type = {
test: <T>(dep: {testT: (z: unknown) => z is T}) =>
name: 'Complex', // just until we have reflection to tell us
test: <T>(dep: { testT: (z: unknown) => z is T }) =>
(z: unknown): z is Complex<T> =>
typeof z === 'object' && 're' in z && 'im' in z
&& dep.testT(z.re) && dep.testT(z.im),
typeof z === 'object' && z != null && 're' in z && 'im' in z
&& dep.testT(z['re']) && dep.testT(z['im']),
infer: (dep: typeOfDependency) =>
(z: Complex<unknown>) => joinTypes(dep.typeOf(z.re), dep.typeOf(z.im)),
from: {
T: <T>(dep: Dependency<'zero', [T]>) => (t: T) =>
({re: t, im: dep.zero(t)}),
Complex: <U,T>(dep: {convert: (from: U) => T}) =>
(z: Complex<U>) => ({re: dep.convert(z.re), im: dep.convert(z.im)})
T: <T>(dep: Dependencies<'zero', T>) => (t: T) =>
({ re: t, im: dep.zero(t) }),
Complex: <U, T>(dep: { convert: (from: U) => T }) =>
(z: Complex<U>) => ({ re: dep.convert(z.re), im: dep.convert(z.im) })
}
}
export interface ComplexImpTypes<T> {
complex: (a: T, b?: T) => Complex<T>
zero: T extends Complex<infer R>
? (a: Complex<R>) => Complex<R | ImpReturns<'zero', [R]>> : never
one: T extends Complex<infer R>
? (a: Complex<R>) => Complex<R | ImpReturns<'one' | 'zero', [R]>> : never
nan: T extends Complex<infer R>
? (a: Complex<R>) => Complex<R | ImpReturns<'NaN', [R]>> : never
re: T extends Complex<infer R>
? (a: Complex<R>) => UnderlyingReal<R> : never
declare module "../interfaces/type" {
interface AssociatedTypes<T> {
Complex: T extends Complex<infer R> ? {
type: Complex<R>
zero: Complex<ZeroType<R>>
one: Complex<OneType<R> | ZeroType<R>>
nan: Complex<NaNType<R>>
real: RealType<R>
} : never
}
interface Signatures<T> {
complex: ((re: T) => Complex<T>) | ((re: T, im: T) => Complex<T>)
}
}
export const complex_unary =
<T>(dep: Dependency<'zero', [T]>): ImpType<'complex', [T]> =>
t => ({re: t, im: dep.zero(t)})
export const complex_binary = <T>(t: T, u: T): ImpReturns<'complex', [T,T]> =>
({re: t, im: u})
export const complex =
<T>(dep: Dependencies<'zero', T>): Signature<'complex', T> =>
(a, b) => ({re: a, im: b || dep.zero(a)})
export const zero =
<T>(dep: Dependency<'zero', [T]>): ImpType<'zero', [Complex<T>]> =>
z => complex_binary(dep.zero(z.re), dep.zero(z.im))
<T>(dep: Dependencies<'zero', T>
& Dependencies<'complex', Returns<'zero', T>>):
Signature<'zero', Complex<T>> =>
z => dep.complex(dep.zero(z.re), dep.zero(z.im))
export const one =
<T>(dep: Dependency<'zero' | 'one', [T]>): ImpType<'one', [Complex<T>]> =>
z => // Must provide parameter T, else TS narrows to return type of dep.one
complex_binary<T>(dep.one(z.re), dep.zero(z.im))
<T>(dep: Dependencies<'one' | 'zero', T>
& Dependencies<'complex', Returns<'one' | 'zero', T>>):
Signature<'one', Complex<T>> =>
z => dep.complex(dep.one(z.re), dep.zero(z.im))
export const nan =
<T>(dep: Dependency<'nan', [T]>): ImpType<'nan', [Complex<T>]> =>
z => complex_binary(dep.nan(z.re), dep.nan(z.im))
<T>(dep: Dependencies<'nan', T>
& Dependencies<'complex', Returns<'nan', T>>):
Signature<'nan', Complex<T>> =>
z => dep.complex(dep.nan(z.re), dep.nan(z.im))
export const re =
<T>(dep: Dependency<'re', [T]>): ImpType<'re', [Complex<T>]> =>
<T>(dep: Dependencies<'re', T>): Signature<'re', Complex<T>> =>
z => dep.re(z.re)
$reflect!([complex, zero, one, nan, re])

View File

@ -5,103 +5,29 @@
* for specific types (including their own).
*/
import {parseReflectedType, ImplementationDef} from './parseReflectedType.js'
// First helper types and functions for the Dispatcher
type TypeName = string
type Parameter = TypeName
type InputSignature = Parameter[]
type Signature = Parameter[]
type DependenciesType = Record<string, Function>
// A "canned" dependency for a builtin function:
export type typeOfDependency = {typeOf: (x: unknown) => TypeName}
// All of the implementations must publish descriptions of their
// types into the following interface, using the format
// described just below:
export interface ImpTypes<T> {}
/*****
To describe one implementation for a hypothetical operation `foo`, there
should be a property of the interface whose name starts with `foo` and whose
next character, if any, is an underscore. The type of this property
must be the type of that implementation when T matches the
first parameter of the implementation.
Thus to describe an implementation that takes a number and a string and
returns a boolean, for example, you could write
```
declare module "Dispatcher" {
interface ImpTypes<T> {
foo_example: (a: number, b: string) => boolean
}
}
```
If there is another, generic implementation that takes one argument
of any type and returns a Vector of that type, you can say
```
...
foo_generic: (a: T) => Vector<T>
...
```
In practice, each subdirectory corresponding to a type, like Complex,
defines an interface, like `ComplexImpTypes<T>` for the implementations
in that subdirectory, which can mostly be defined without suffixes because
there's typically just a single implementation within that domain.
Then the module responsible for collating all of the implementations for
that type inserts all of the properties of that interface into `ReturnTypes`
suitably suffixed to avoid collisions.
Note that if the type is not generic, it will not bother with the generic
parameter in its subdirectory ImpTypes interface.
And note again, that for generic types, the type parameter of ImpTypes
_must_ match the type of the **first** argument of the operation. Hence,
choose argument order so that you can infer all the other parameter types
and the return type from the type of the first argument.
*****/
// Helper for collecting return types
// (Really just adds the literal string Suffix onto the keys of interface IFace)
export type ForType<Suffix extends string, IFace> = keyof IFace extends string
? {[K in keyof IFace as `${K}_${Suffix}`]: IFace[K]}
: never
// Utility needed in type definitions
//dummy implementation for now
export function joinTypes(a: TypeName, b: TypeName) {
if (a === b) return a
return 'any'
}
// Used to filter keys that match a given operation name
type BeginsWith<Name extends string> = Name | `${Name}_${string}`
export type RawDependency<Name extends string, Params extends unknown[]> =
{[K in keyof ImpTypes<Params[0]>]: K extends BeginsWith<Name>
? ImpTypes<Params[0]>[K] extends (...args: Params) => any
? ImpTypes<Params[0]>[K]
: never
: never}
// The type of an implementation (with dependencies satisfied,
// based on its name and the parameters it takes
export type ImpType<Name extends string, Params extends unknown[]> =
RawDependency<Name, Params>[keyof ImpTypes<Params[0]>]
// The type of a dependency on an implementation based on its name
// and the parameters it takes (just a simple object with one property
// named the same as the operation, of value type equal to the type of
// that implementation. These can be `&`ed together in case of multiple
// dependencies:
export type Dependency<Name extends string, Params extends unknown[]> =
{[N in Name]: ImpType<N, Params>}
// Look up the return type of an implementation based on its name
// and the parameters it takes
export type ImpReturns<Name extends string, Params extends unknown[]> =
ReturnType<ImpType<Name, Params>>
// Now types used in the Dispatcher class itself
type TypeSpecification = {
name: string, // just until we get reflection, then we can remove this property
before?: TypeName[],
test: ((x: unknown) => boolean)
| ((d: DependenciesType) => (x: unknown) => boolean),
@ -115,38 +41,44 @@ type SpecificationsGroup = Record<string, SpecObject>
export class Dispatcher {
installSpecification(
name: string,
signature: InputSignature,
returns: TypeName,
dependencies: Record<string, InputSignature>,
defn: ImplementationDef,
behavior: Function // possible todo: constrain this type based
// on the signature, return type, and dependencies. Not sure if
// that's really possible, though.
) {
console.log('Pretending to install', name, signature, '=>', returns)
console.log('Pretending to install', name, 'with signatures')
for (const signature of defn.fn.signatures) {
console.log(' ', signature.args, '=>', signature.returns)
}
if (defn.fn.aliasOf) {
console.log(' As an alias of', defn.fn.aliasOf)
}
//TODO: implement me
}
installType(name: TypeName, typespec: TypeSpecification) {
console.log('Pretending to install type', name, typespec)
//TODO: implement me
}
constructor(collection: SpecificationsGroup) {
constructor(collection: SpecificationsGroup) {
const implementations = []
for (const key in collection) {
console.log('Working on', key)
for (const identifier in collection[key]) {
console.log('Handling', key, ':', identifier)
const parts = identifier.split('_')
if (parts[parts.length - 1] === 'type') {
parts.pop()
const name = parts.join('_')
this.installType(
name, collection[key][identifier] as TypeSpecification)
const item = collection[key][identifier]
if (typeof item === 'function') {
implementations.push([key, identifier, item])
} else {
const name = parts[0]
this.installSpecification(
name, ['dunno'], 'unsure', {},
collection[key][identifier] as Function)
console.log('Handling type', key, ':', identifier)
this.installType(
item.name, collection[key][identifier] as TypeSpecification)
}
}
}
for (const trio of implementations) {
const [k, id, imp] = trio
console.log('Handling implementation', id, 'from', k)
this.installSpecification(
id, parseReflectedType(id, imp.reflectedType), imp)
}
}
}

View File

@ -0,0 +1,279 @@
export type FunctionDef = {
name: string,
aliasOf?: string,
signatures: Array<{
args: Array<{ name: string, type: string }>
returns: string
}>
}
export type ImplementationDef = {
fn: FunctionDef,
dependencies: Record<string, FunctionDef>
genericParameter: string | null
}
/**
* Parse a reflected type coming out of TypeScript into a structured object, for example:
*
* '<T>(dep: configDependency & { complex: ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>); }) => (a: number) => number | Complex<number>'
*/
export function parseReflectedType(name: string, reflectedType: string): ImplementationDef {
console.log('For', name, 'parsing', reflectedType)
const [factoryArgs, fnsClause] = split(reflectedType, '=>', 2).map(trim)
const fn = parseAlias(name, fnsClause)
// extract the generic parameter like '<T>' at the start of the type
const genericParameter = factoryArgs.trim().startsWith('<')
? findBlockContents(factoryArgs, '<', '>')?.innerText || null
: null
const factoryArgsInner = findBlockContents(factoryArgs, '(', ')')
const depArg = split(factoryArgsInner.innerText, ':').map(trim)[1]
const depArgBlocks: string[] = depArg ? split(depArg, '&').map(trim) : []
const deps = depArgBlocks
.filter(depArgBlock => {
if (depArgBlock.startsWith('{') || depArgBlock === 'configDependency') {
return true
} else {
throw new SyntaxError(`Cannot parse dependency "${depArgBlock}"`)
}
})
.flatMap(parseDependencies)
const dependencies: Record<string, FunctionDef> = groupBy(deps, 'name')
return {fn, dependencies, genericParameter }
}
function parseDependencies(deps: string): FunctionDef[] {
if (deps === 'configDependency') {
return [{name: 'config', signatures: [{args: [], returns: 'Config'}]}]
}
const inner = findBlockContents(deps, '{', '}').innerText
return split(inner, ';')
.map(trim)
.filter(notEmpty)
.map(parseDependency)
}
// parse a dependency like "complex: ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>)"
function parseDependency(dep: string): FunctionDef {
const [name, def] = split(dep, ':').map(trim)
return parseAlias(name, def)
}
// Parse a possibly aliased function
function parseAlias(name: string, alias: string): FunctionDef {
const { aliasOf, innerSignature } = parseAliasOf(alias)
return { name, signatures: parseSignatures(innerSignature), aliasOf }
}
// parse function signatures like ((re: number) => Complex<number>) | ((re: number, im: number) => Complex<number>)
// But also have to succeed on (a: number) => number | Complex<number>
// That's why we only split on an alternation bar `|` that's followed by
// a parenthesis; that way we avoid splitting a union return type. Note
// this is not necessarily foolproof, as there could be a return type that
// is a union with a complicated piece that has to be enclosed in parens;
// but so far it seems to work in practice.
function parseSignatures(sigs: string) {
return split(sigs, /[|]\s*(?=[(])/)
.map(trim)
.map(stripParenthesis)
.map(signature => {
const [argsBlock, returns] = split(signature, '=>').map(trim)
if (!returns) {
throw new SyntaxError(`Failed to find return type in '${signature}'`)
}
return {
args: parseArgs(argsBlock),
returns
}
})
}
// parse args like "(re: number, im: number)"
function parseArgs(argsBlock: string) : Array<{name: string, type: string}> {
const args = findBlockContents(argsBlock, '(', ')').innerText
return split(args, ',')
.map(trim)
.map(arg => {
const [name, type] = split(arg, ':').map(trim)
return { name, type}
})
}
// parse "AliasOf<"divide", (a: Complex<T>, b: RealType<Complex<T>>) => Complex<T>>"
function parseAliasOf(signature: string) : { innerSignature: string, aliasOf: string | undefined } {
if (!signature.startsWith('AliasOf')) {
return {
innerSignature: signature,
aliasOf: undefined
}
}
const inner = findBlockContents(signature, '<', '>').innerText.trim()
const [aliasOfWithQuotes, innerSignature] = split(inner, ',').map(trim)
return {
innerSignature,
aliasOf: aliasOfWithQuotes.substring(1, aliasOfWithQuotes.length - 1) // remove double quotes
}
}
// remove the outer parenthesis, for example "((re: number) => Complex<number>)" returns "(re: number) => Complex<number>"
function stripParenthesis(text: string) : string {
return text.startsWith('(') && text.endsWith(')')
? text.substring(1, text.length - 1)
: text
}
function findBlockContents(text: string, blockStart: string, blockEnd: string, startIndex = 0) : { start: number, end: number, innerText: string } | undefined {
let i = startIndex
while (!matchSubString(text, blockStart, i) && i < text.length) {
i++
}
if (i >= text.length) {
return undefined
}
i++
const start = i
while (!matchSubString(text, blockEnd, i) || matchSubString(text, '=>', i - 1)) {
i = skipBrackets(text, i)
i++
}
if (i >= text.length) {
return undefined
}
const end = i
return {
start,
end,
innerText: text.substring(start, end)
}
}
/**
* Given a string, generate a string source for a regexp that will match
* exactly the given string.
* Uses the fact that the only characters that need to be escaped in
* a character class are \, ], and ^
*/
function regexpQuote(s: string) {
const special = '\\]^'
let re = ''
for (const char of s) {
if (special.includes(char)) re += `\\${char}`
else re += `[${char}]`
}
return re
}
/**
* Split a string by a delimiter, but ignore all occurrences of the delimiter
* that are inside bracket pairs <> () [] {}
*/
export function split(
text: string, delimiter: string | RegExp, pieces = 0): string[] {
const delim: RegExp = typeof delimiter === 'string'
? new RegExp(regexpQuote(delimiter), 'y')
: new RegExp(delimiter.source, 'y')
const parts: string[] = []
let i = 0
let n = 1
let start = 0
while (i < text.length && (pieces === 0 || n < pieces)) {
i = skipBrackets(text, i)
delim.lastIndex = i
const result = delim.exec(text)
if (result) {
parts.push(text.substring(start, i))
n += 1
i += result[0].length
start = i
}
i++
}
parts.push(text.substring(start))
return parts
}
function skipBrackets(text: string, startIndex: number) : number {
let level = 0
let i = startIndex
do {
if (isBracketOpen(text, i)) {
level++
}
if (isBracketClose(text, i) && level > 0) {
level--
}
if (level === 0) {
break
}
i++
} while(i < text.length)
return i
}
function isBracketOpen(text: string, index: number) {
const char = text[index]
return char === '(' || char === '<' || char === '[' || char === '{'
}
function isBracketClose(text: string, index: number) {
const char = text[index]
// we need to take care of not matching the ">" of the operator "=>"
return char === ')' || (char === '>' && text[index - 1] !== '=') || char === ']' || char === '}'
}
function matchSubString(text: string, search: string, index: number) : boolean {
for (let i = 0; i < search.length; i++) {
if (text[i + index] !== search[i]) {
return false
}
}
return true
}
function trim(text: string) : string {
return text.trim()
}
function notEmpty(text: string) : boolean {
return text.length > 0
}
function groupBy<T>(items: T[], key: string) : Record<string, T> {
const obj: Record<string, T> = {}
items.forEach((item) => {
obj[item[key]] = item
})
return obj
}

View File

@ -1,10 +1 @@
import { ForType } from '../core/Dispatcher.js'
import { GenericImpTypes } from './type.js'
import * as generic from './native.js'
export { generic }
declare module "../core/Dispatcher" {
interface ImpTypes<T>
extends ForType<'generic', GenericImpTypes<T>> { }
}
export * as generic from './native.js'

View File

@ -1,12 +1,9 @@
import {Dependency, ImpType, ImpReturns} from '../core/Dispatcher.js'
declare module "./type" {
interface GenericImpTypes<T> {
square: (a: T) => ImpReturns<'multiply', [T, T]>
}
}
import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const square =
<T>(dep: Dependency<'multiply', [T, T]>):
ImpType<'square', [T]> =>
t => dep.multiply(t, t)
<T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
z => dep.multiply(z, z)
// z => dep.fooBar(z, z) // fails as desired
// z => dep.multiply(z, 'foo') // still fails as desired
$reflect!([square])

View File

@ -1,11 +1,7 @@
import {Dependency, ImpType} from '../core/Dispatcher.js'
declare module "./type" {
interface GenericImpTypes<T> {
unequal: (a: T, b:T) => boolean
}
}
import {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const unequal =
<T>(dep: Dependency<'equal', [T,T]>): ImpType<'unequal', [T, T]> =>
(a, b) => !dep.equal(a, b)
<T>(dep: Dependencies<'equal', T>): Signature<'unequal', T> =>
(x, y) => !dep.equal(x, y)
$reflect!([unequal])

View File

@ -1,3 +0,0 @@
export interface GenericImpTypes<T> {
}

View File

@ -1,3 +1,4 @@
import {inspect} from 'node:util'
import {Dispatcher} from './core/Dispatcher.js'
import * as Specifications from './all.js'
@ -5,16 +6,48 @@ export default new Dispatcher(Specifications)
import {Complex} from './Complex/type.js'
import {absquare as absquare_complex} from './Complex/arithmetic.js'
import {parseReflectedType} from './core/parseReflectedType.js'
const mockRealAdd = (a: number, b: number) => a+b
const mockComplexAbsquare = (z: Complex<number>) => z.re*z.re + z.im*z.im
const mockComplex = (re: number, im: number) => ({ re, im })
const config = {
predictable: false,
epsilon: 1e-14
}
const quatAbsquare = absquare_complex({
add: mockRealAdd,
absquare: mockComplexAbsquare
add: mockRealAdd,
absquare: mockComplexAbsquare
})
const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}})
const typeTest: typeof myabs = 7 // check myabs is just a number
console.log('Result is myabs=', myabs)
console.log('Result is', myabs)
const sqrt = Specifications.numbers.sqrt({
config,
complex: mockComplex
})
console.log('Result of sqrt(16)=', sqrt(16))
console.log('Result of sqrt(-4)=', sqrt(-4))
console.log()
console.log('1) NUMBER SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.numbers.sqrt.reflectedType}"`)
console.log(
'1.2) PARSED TYPE:',
inspect(
parseReflectedType('sqrt', Specifications.numbers.sqrt.reflectedType),
{ depth: null, colors: true }))
console.log()
console.log('2) GENERIC SQUARE')
console.log(`1.1) REFLECTED TYPE: "${Specifications.generic.square.reflectedType}"`)
console.log('2.2) PARSED TYPE:', inspect(parseReflectedType('square', Specifications.generic.square.reflectedType), { depth: null, colors: true }))
console.log()
console.log('3) COMPLEX SQRT')
console.log(`1.1) REFLECTED TYPE: "${Specifications.complex.sqrt.reflectedType}"`)
console.log('3.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.complex.sqrt.reflectedType), { depth: null, colors: true }))

View File

@ -0,0 +1,18 @@
import type {Complex} from '../Complex/type.js'
import type {RealType} from './type.js'
declare module "./type" {
interface Signatures<T> {
add: (a: T, b: T) => T
unaryMinus: (a: T) => T
conj: (a: T) => T
subtract: (a: T, b: T) => T
multiply: (a: T, b: T) => T
square: (a: T) => T
absquare: (a: T) => RealType<T>
reciprocal: (a: T) => T
divide: (a: T, b: T) => T
conservativeSqrt: (a: T) => T
sqrt: (a: T)=> T extends Complex<unknown> ? T : T | Complex<T>
}
}

View File

@ -0,0 +1,10 @@
// Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored.
export type UnaryPredicate<T> = (a: T) => boolean
declare module "./type" {
interface Signatures<T> {
isReal: (a: T) => boolean
isSquare: (a: T) => boolean
}
}

View File

@ -0,0 +1,9 @@
// Warning: a module must have something besides just a "declare module"
// section; otherwise it is ignored.
export type BinaryPredicate<T> = (a: T, b: T) => T
declare module "./type" {
interface Signatures<T> {
equal: (a: T, b: T) => boolean
unequal: (a: T, b: T) => boolean
}
}

90
src/interfaces/type.ts Normal file
View File

@ -0,0 +1,90 @@
import {$$typeToString} from 'ts-macros'
/*****
* Every typocomath type has some associated types; they need
* to be published in the following interface. The key is the
* name of the type, and within the subinterface for that key,
* the type of the 'type' property is the actual TypeScript type
* we are associating the other properties to. Note the interface
* is generic with one parameter, corresponding to the fact that
* typocomath currently only allows generic types with a single
* generic parameter. This way, AssociatedTypes<SubType> can give the
* associated types for a generic type instantiated with SubType.
* That's not necessary for the 'undefined' type (or if you look in the
* `numbers` subdirectory, the 'number' type) or any concrete type,
* but that's OK, the generic parameter doesn't hurt in those cases.
****/
type ValueIntersectionByKeyUnion<T, TKey extends keyof T> = {
[P in TKey]: (k: T[P])=>void
} [TKey] extends ((k: infer I)=>void) ? I : never
export interface AssociatedTypes<T> {
undefined: {
type: undefined
zero: undefined
one: undefined
nan: undefined
real: undefined
}
}
type AssociatedTypeNames = keyof AssociatedTypes<unknown>['undefined']
type ALookup<T, Name extends AssociatedTypeNames> = ValueIntersectionByKeyUnion<{
[K in keyof AssociatedTypes<T>]:
T extends AssociatedTypes<T>[K]['type'] ? AssociatedTypes<T>[K][Name] : unknown},
keyof AssociatedTypes<T>>
// For everything to compile, zero and one must be subtypes of T:
export type ZeroType<T> = ALookup<T, 'zero'> & T
export type OneType<T> = ALookup<T, 'one'> & T
// But I believe 'nan' really might not be, like I think we will have to use
// 'undefined' for the nan of 'bigint', as it has nothing at all like NaN,
// so don't force it:
export type NaNType<T> = ALookup<T, 'nan'>
export type RealType<T> = ALookup<T, 'real'>
/*****
* The global signature patterns for all operations need to be published in the
* following interface. Each key is the name of an operation (but note that
* the Dispatcher will automatically merge operations that have the same
* name when the first underscore `_` and everything thereafter is stripped).
* The type of each key should be an interface with two properties: 'params'
* whose type is the type of the parameter list for the operation, and
* 'returns' whose type is the return type of the operation on those
* parameters. These types are generic in a parameter type T which should
* be interpreted as the type that the operation is supposed to "primarily"
* operate on, although note that some of the parameters and/or return types
* may depend on T rather than be exactly T.
* So note that the example 're' below provides essentially the same
* information that e.g.
* `type ReOp<T> = (t: T) => RealType<T>`
* would, but in a way that is much easier to manipulate in TypeScript,
* and it records the name of the operation as 're' also by virtue of the
* key 're' in the interface.
****/
export interface Signatures<T> {
zero: (a: T) => ZeroType<T>
one: (a: T) => OneType<T>
// nan needs to be able to operate on its own output for everything
// else to compile. That's why its parameter type is widened:
nan: (a: T | NaNType<T>) => NaNType<T>
re: (a: T) => RealType<T>
}
type SignatureKey<T> = keyof Signatures<T>
export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
export type Returns<Name extends SignatureKey<T>, T> =
ReturnType<Signatures<T>[Name]>
type Deps<T> = T extends unknown ? { [K in keyof T]: T[K] } : never;
export type Dependencies<Name extends SignatureKey<T>, T> =
Deps<{[K in Name]: Signature<K, T>}>
export type AliasOf<Name extends string, T> = T & {aliasOf?: Name}
// For defining implementations with type reflection
export function $reflect<ImplTuple>(tup: ImplTuple) {
+[[tup], <T>(elt: T) =>
elt.reflectedType = $$typeToString!<T>(true, false, true)]
}

View File

@ -1,10 +1,3 @@
import {ForType} from '../core/Dispatcher.js'
import {NumbersImpTypes} from './type.js'
import * as numbers from './native.js'
export {numbers}
declare module "../core/Dispatcher" {
interface ImpTypes<T>
extends ForType<'numbers', NumbersImpTypes> {}
}

View File

@ -1,50 +1,35 @@
import {configDependency} from '../core/Config.js'
import {
Dependency, ImpType
} from '../core/Dispatcher.js'
import type {Complex, UnderlyingReal} from '../Complex/type.js'
import type {configDependency} from '../core/Config.js'
import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
type UnaryNumber = (a: number) => number
type BinaryNumber = (a: number, b:number) => number
export const add = (): Signature<'add', number> => (a, b) => a + b
const unaMinus = (a: number) => -a
export const unaryMinus = (): Signature<'unaryMinus', number> => unaMinus
export const conj = (): Signature<'conj', number> => a => a
export const subtract = (): Signature<'subtract', number> => (a, b) => a - b
export const multiply = (): Signature<'multiply', number> => (a, b) => a * b
export const absquare = (): Signature<'absquare', number> => a => a * a
export const reciprocal = (): Signature<'reciprocal', number> => a => 1 / a
export const divide = (): Signature<'divide', number> => (a, b) => a / b
declare module "./type" {
interface NumbersImpTypes {
add: BinaryNumber
unaryMinus: UnaryNumber
conj: UnaryNumber
subtract: BinaryNumber
multiply: BinaryNumber
absquare: UnaryNumber
reciprocal: UnaryNumber
divide: BinaryNumber
conservativeSqrt: UnaryNumber
// Best we can do for sqrt at compile time, since actual return
// type depends on config. Not sure how this will play out
// when we make a number-only bundle, but at least the import type
// above for Complex<> does not lead to any emitted JavaScript.
sqrt: (a: number) => number | Complex<number>
}
}
export const add: ImpType<'add', [number, number]> = (a, b) => a + b
export const unaryMinus: ImpType<'unaryMinus', [number]> = a => -a
export const conj: ImpType<'conj', [number]> = a => a
export const subtract: ImpType<'subtract', [number, number]> = (a, b) => a - b
export const multiply: ImpType<'multiply', [number, number]> = (a, b) => a * b
export const absquare: ImpType<'absquare', [number]> = a => a*a
export const reciprocal: ImpType<'reciprocal', [number]> = a => 1/a
export const divide: ImpType<'divide', [number, number]> = (a, b) => a / b
export const conservativeSqrt: ImpType<'conservativeSqrt', [number]> =
a => isNaN(a) ? NaN : Math.sqrt(a)
const basicSqrt = (a: number) => isNaN(a) ? NaN : Math.sqrt(a)
export const conservativeSqrt = (): Signature<'conservativeSqrt', number> =>
basicSqrt
export const sqrt =
(dep: configDependency
& Dependency<'complex', [number, number]>): ImpType<'sqrt', [number]> => {
if (dep.config.predictable || !dep.complex) return conservativeSqrt
return a => {
if (isNaN(a)) return NaN
if (a >= 0) return Math.sqrt(a)
return dep.complex(0, Math.sqrt(unaryMinus(a)))
}
(dep: configDependency
& Dependencies<'complex', number>): Signature<'sqrt', number> => {
if (dep.config.predictable || !dep.complex) {
return basicSqrt
}
return a => {
if (isNaN(a)) return NaN
if (a >= 0) return Math.sqrt(a)
return dep.complex(0, Math.sqrt(unaMinus(a)))
}
}
$reflect!([
add, unaryMinus, conj, subtract, multiply, absquare, reciprocal, divide,
conservativeSqrt, sqrt
])

View File

@ -1,12 +1,7 @@
import {ImpType} from '../core/Dispatcher.js'
import type {Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
type NumberPredicate = (a: number) => boolean
declare module "./type" {
interface NumbersImpTypes {
isReal: NumberPredicate
isSquare: NumberPredicate
}
}
export const isReal = (): Signature<'isReal', number> => (a) => true
export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0
export const isReal: ImpType<'isReal', [number]> = a => true
export const isSquare: ImpType<'isSquare', [number]> = a => a >= 0
$reflect!([isReal, isSquare])

View File

@ -1,29 +1,23 @@
import {configDependency} from '../core/Config.js'
import {ImpType, Dependency} from '../core/Dispatcher.js'
import {Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16
type NumberRelation = (a: number, b: number) => boolean
declare module "./type" {
interface NumbersImpTypes {
equal: NumberRelation
}
}
export const equal =
(dep: configDependency): ImpType<'equal', [number, number]> =>
(x, y) => {
const eps = dep.config.epsilon
if (eps === null || eps === undefined) return x === y
if (x === y) return true
if (isNaN(x) || isNaN(y)) return false
(dep: configDependency): Signature<'equal', number> =>
(x, y) => {
const eps = dep.config.epsilon
if (eps === null || eps === undefined) return x === y
if (x === y) return true
if (isNaN(x) || isNaN(y)) return false
if (isFinite(x) && isFinite(y)) {
const diff = Math.abs(x - y)
if (diff < DBL_EPSILON) return true
return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps
}
return false
if (isFinite(x) && isFinite(y)) {
const diff = Math.abs(x - y)
if (diff < DBL_EPSILON) return true
return diff <= Math.max(Math.abs(x), Math.abs(y)) * eps
}
return false
}
$reflect!([equal])

View File

@ -1,21 +1,29 @@
import {ImpType} from '../core/Dispatcher.js'
import type {UnderlyingReal} from '../Complex/type.js'
import type { Signature } from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const number_type = {
name: 'number', // just until we have reflection to tell us
before: ['Complex'],
test: (n: unknown): n is number => typeof n === 'number',
from: {string: s => +s}
from: { string: (s: string) => +s }
}
export interface NumbersImpTypes {
zero: (a: number) => 0
one: (a: number) => 1
nan: (a: number) => typeof NaN
re: (a: number) => number
declare module "../interfaces/type" {
interface AssociatedTypes<T> {
number: {
type: number
zero: 0
one: 1
nan: typeof NaN
real: number
}
}
}
export const zero: ImpType<'zero', [number]> = a => 0
export const one: ImpType<'one', [number]> = a => 1
export const nan: ImpType<'nan', [number]> = a => NaN
export const re: ImpType<'re', [number]> = a => a
// I don't like the redundancy of repeating 'zero'; any way to eliminate that?
export const zero = (): Signature<'zero', number> => (a) => 0
export const one = (): Signature<'one', number> => (a) => 1
export const nan = (): Signature<'nan', number> => (a) => NaN
export const re = (): Signature<'re', number> => (a) => a
$reflect!([zero, one, nan, re])

View File

@ -1,7 +1,12 @@
{
"compilerOptions": {
"target": "ES2022",
"target": "esnext",
"rootDir": "./src",
"outDir": "./obj"
"outDir": "./build",
"moduleResolution": "nodenext",
"plugins": [ {
"transform": "ts-macros/dist/type-resolve",
"transformProgram": true
} ]
}
}