Compare commits

..

7 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
22 changed files with 1361 additions and 116 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@
*~ *~
# Typescript # Typescript
# emitted code # emitted code
obj build
# ---> Node # ---> Node
# Logs # Logs

1
.npmrc Normal file
View File

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

View File

@ -2,9 +2,13 @@
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.
To build and run the prototype, run:
``` Convenience scripts:
npx tsc
node obj * `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', name: 'typocomath',
version: '0.0.1', version: '0.0.2',
description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept', description: 'A hopeful final typescipt-pragmatic mathjs proof-of-concept',
main: 'index.ts', main: 'index.ts',
scripts: { scripts: {
test: 'echo "Error: no test specified" && exit 1', 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: [ keywords: [
'math', 'math',
'algebra', 'algebra',
@ -18,8 +23,13 @@
url: 'https://code.studioinfinity.org/glen/typocomath.git', url: 'https://code.studioinfinity.org/glen/typocomath.git',
}, },
devDependencies: { devDependencies: {
'@types/node': '^20.5.0', '@types/node': '20.8.4',
'source-map': '^0.7.4', 'cpy-cli': '5.0.0',
typescript: '^4.9.3', '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

@ -6,19 +6,771 @@ settings:
devDependencies: devDependencies:
'@types/node': '@types/node':
specifier: ^20.5.0 specifier: 20.8.4
version: 20.5.0 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: source-map:
specifier: ^0.7.4 specifier: 0.7.4
version: 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: typescript:
specifier: ^4.9.3 specifier: 5.1.6
version: 4.9.3 version: 5.1.6
packages: packages:
/@types/node@20.5.0: /@babel/code-frame@7.22.13:
resolution: {integrity: sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==} 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 dev: true
/source-map@0.7.4: /source-map@0.7.4:
@ -26,8 +778,143 @@ packages:
engines: {node: '>= 8'} engines: {node: '>= 8'}
dev: true dev: true
/typescript@4.9.3: /spdx-correct@3.2.0:
resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
engines: {node: '>=4.2.0'} 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 hasBin: true
dev: 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

@ -2,6 +2,7 @@ import {Complex} from './type.js'
import type { import type {
Dependencies, Signature, Returns, RealType, AliasOf Dependencies, Signature, Returns, RealType, AliasOf
} from '../interfaces/type.js' } from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
declare module "../interfaces/type" { declare module "../interfaces/type" {
interface Signatures<T> { interface Signatures<T> {
@ -78,11 +79,10 @@ export const sqrt =
& Dependencies<'zero' | 'complex', T> & Dependencies<'zero' | 'complex', T>
& Dependencies<'absquare' | 're' | 'divideReal', Complex<T>> & Dependencies<'absquare' | 're' | 'divideReal', Complex<T>>
& { & {
addTR: Signature<'addReal', T>, addTR: Signature<'addReal', T>,
addRR: Signature<'add', RealType<T>>, addRR: Signature<'add', RealType<T>>,
addCR: Signature<'addReal', Complex<T>> addCR: Signature<'addReal', Complex<T>>
}): }): Signature<'sqrt', Complex<T>> =>
Signature<'sqrt', Complex<T>> =>
z => { z => {
const myabs = dep.conservativeSqrt(dep.absquare(z)) const myabs = dep.conservativeSqrt(dep.absquare(z))
const r = dep.re(z) const r = dep.re(z)
@ -98,4 +98,7 @@ export const sqrt =
return dep.divideReal(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,9 +1,13 @@
import {Complex} from './type.js' import {Complex} from './type.js'
import type {Dependencies, Signature} from '../interfaces/type.js' import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const isReal = export const isReal =
<T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>): <T>(dep: Dependencies<'add' | 'equal' | 'isReal', T>):
Signature<'isReal', Complex<T>> => Signature<'isReal', Complex<T>> =>
z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im)) z => dep.isReal(z.re) && dep.equal(z.re, dep.add(z.re, z.im))
export const isSquare: Signature<'isSquare', Complex<any>> = z => true // FIXME: not correct for Complex<bigint> once we get there 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,6 +1,8 @@
import {Complex} from './type.js' import {Complex} from './type.js'
import {Dependencies, Signature} from '../interfaces/type.js' import {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const equal = export const equal =
<T>(dep: Dependencies<'equal', T>): Signature<'equal', 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) (w, z) => dep.equal(w.re, z.re) && dep.equal(w.im, z.im)
$reflect!([equal])

View File

@ -2,10 +2,12 @@ import {joinTypes, typeOfDependency} from '../core/Dispatcher.js'
import type { import type {
ZeroType, OneType, NaNType, Dependencies, Signature, Returns ZeroType, OneType, NaNType, Dependencies, Signature, Returns
} from '../interfaces/type.js' } from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export type Complex<T> = { re: T; im: T; } export type Complex<T> = { re: T; im: T; }
export const Complex_type = { export const Complex_type = {
name: 'Complex', // just until we have reflection to tell us
test: <T>(dep: { testT: (z: unknown) => z is T }) => test: <T>(dep: { testT: (z: unknown) => z is T }) =>
(z: unknown): z is Complex<T> => (z: unknown): z is Complex<T> =>
typeof z === 'object' && z != null && 're' in z && 'im' in z typeof z === 'object' && z != null && 're' in z && 'im' in z
@ -61,3 +63,5 @@ export const nan =
export const re = export const re =
<T>(dep: Dependencies<'re', T>): Signature<'re', Complex<T>> => <T>(dep: Dependencies<'re', T>): Signature<'re', Complex<T>> =>
z => dep.re(z.re) z => dep.re(z.re)
$reflect!([complex, zero, one, nan, re])

View File

@ -5,6 +5,8 @@
* for specific types (including their own). * for specific types (including their own).
*/ */
import {parseReflectedType, ImplementationDef} from './parseReflectedType.js'
// First helper types and functions for the Dispatcher // First helper types and functions for the Dispatcher
type TypeName = string type TypeName = string
@ -25,6 +27,7 @@ export function joinTypes(a: TypeName, b: TypeName) {
// Now types used in the Dispatcher class itself // Now types used in the Dispatcher class itself
type TypeSpecification = { type TypeSpecification = {
name: string, // just until we get reflection, then we can remove this property
before?: TypeName[], before?: TypeName[],
test: ((x: unknown) => boolean) test: ((x: unknown) => boolean)
| ((d: DependenciesType) => (x: unknown) => boolean), | ((d: DependenciesType) => (x: unknown) => boolean),
@ -38,38 +41,44 @@ type SpecificationsGroup = Record<string, SpecObject>
export class Dispatcher { export class Dispatcher {
installSpecification( installSpecification(
name: string, name: string,
signature: Signature, defn: ImplementationDef,
returns: TypeName,
dependencies: Record<string, Signature>,
behavior: Function // possible todo: constrain this type based behavior: Function // possible todo: constrain this type based
// on the signature, return type, and dependencies. Not sure if // on the signature, return type, and dependencies. Not sure if
// that's really possible, though. // 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 //TODO: implement me
} }
installType(name: TypeName, typespec: TypeSpecification) { installType(name: TypeName, typespec: TypeSpecification) {
console.log('Pretending to install type', name, typespec) console.log('Pretending to install type', name, typespec)
//TODO: implement me //TODO: implement me
} }
constructor(collection: SpecificationsGroup) { constructor(collection: SpecificationsGroup) {
const implementations = []
for (const key in collection) { for (const key in collection) {
console.log('Working on', key) console.log('Working on', key)
for (const identifier in collection[key]) { for (const identifier in collection[key]) {
console.log('Handling', key, ':', identifier) const item = collection[key][identifier]
const parts = identifier.split('_') if (typeof item === 'function') {
if (parts[parts.length - 1] === 'type') { implementations.push([key, identifier, item])
parts.pop()
const name = parts.join('_')
this.installType(
name, collection[key][identifier] as TypeSpecification)
} else { } else {
const name = parts[0] console.log('Handling type', key, ':', identifier)
this.installSpecification( this.installType(
name, ['dunno'], 'unsure', {}, item.name, collection[key][identifier] as TypeSpecification)
collection[key][identifier] as Function)
} }
} }
} }
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,32 +1,9 @@
import type {Dependencies, Signature} from '../interfaces/type.js' import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
// This stuff would really go in interfaces/type.js or someplace like that export const square =
type Annotate<U> = U & {dependencies?: Record<string, string>, signature?: string} <T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
z => dep.multiply(z, z)
function genericImplementation<Deps extends Record<string, string>, Sig extends string>( // z => dep.fooBar(z, z) // fails as desired
deps: Deps, sig: Sig, impl: <T>(dep: Dependencies<keyof Deps, T>) => Signature<Sig, T> // z => dep.multiply(z, 'foo') // still fails as desired
) { $reflect!([square])
const rimpl: Annotate<typeof impl> = impl
rimpl.dependencies = deps
rimpl.signature = sig
return rimpl
}
// and of course it would need to be generalized somewhat from the above
// --------------
// Then here for the implementation we would have:
export const square = genericImplementation(
{multiply: 'T'}, 'square', <T>(dep) => z => dep.multiply(z, z)
)
// Note this was previously
// export const square =
// <T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
// z => dep.multiply(z, z)
// but then we couldn't get at the dependencies or the signature at runtime. So the point of
// genericImplementation is that it takes literal values for the dependencies and signature,
// from which it deduces the types of the actual dependencies of the implementation and the
// the implementation itself, and then it copies those literal values onto properties of the
// implementation, where they can be accessed at runtime as illustreated in ../index.ts

View File

@ -1,5 +1,7 @@
import {Dependencies, Signature} from '../interfaces/type.js' import {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const unequal = export const unequal =
<T>(dep: Dependencies<'equal', T>): Signature<'unequal', T> => <T>(dep: Dependencies<'equal', T>): Signature<'unequal', T> =>
(x, y) => !dep.equal(x, y) (x, y) => !dep.equal(x, y)
$reflect!([unequal])

View File

@ -1,3 +1,4 @@
import {inspect} from 'node:util'
import {Dispatcher} from './core/Dispatcher.js' import {Dispatcher} from './core/Dispatcher.js'
import * as Specifications from './all.js' import * as Specifications from './all.js'
@ -5,27 +6,48 @@ export default new Dispatcher(Specifications)
import {Complex} from './Complex/type.js' import {Complex} from './Complex/type.js'
import {absquare as absquare_complex} from './Complex/arithmetic.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 mockRealAdd = (a: number, b: number) => a+b
const mockComplexAbsquare = (z: Complex<number>) => z.re*z.re + z.im*z.im 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({ const quatAbsquare = absquare_complex({
add: mockRealAdd, add: mockRealAdd,
absquare: mockComplexAbsquare absquare: mockComplexAbsquare
}) })
const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}}) const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}})
const typeTest: typeof myabs = 7 // check myabs is just a number 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('Dependencies of square are', Specifications.generic.square.dependencies) console.log()
console.log('Signature of square is', Specifications.generic.square.signature) 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 }))
const realSquare = Specifications.generic.square<number>({multiply: (a,b) => a*b}) console.log()
console.log('Square of 2.5 is', realSquare(2.5)) 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 }))
// and note the following fail with a type error as desired: console.log()
// const fakeSquare = Specifications.generic.square<number>({multiply: (a,b,c) => a*b*c}) console.log('3) COMPLEX SQRT')
// const stringSquare = Specifications.generic.square<string>({multiply: (a,b) => a*b}) console.log(`1.1) REFLECTED TYPE: "${Specifications.complex.sqrt.reflectedType}"`)
// console.log('Square of three is', stringSquare('three')) console.log('3.2) PARSED TYPE:', inspect(parseReflectedType('sqrt', Specifications.complex.sqrt.reflectedType), { depth: null, colors: true }))

View File

@ -1,3 +1,5 @@
import {$$typeToString} from 'ts-macros'
/***** /*****
* Every typocomath type has some associated types; they need * Every typocomath type has some associated types; they need
* to be published in the following interface. The key is the * to be published in the following interface. The key is the
@ -13,6 +15,10 @@
* but that's OK, the generic parameter doesn't hurt in those cases. * 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> { export interface AssociatedTypes<T> {
undefined: { undefined: {
type: undefined type: undefined
@ -24,10 +30,10 @@ export interface AssociatedTypes<T> {
} }
type AssociatedTypeNames = keyof AssociatedTypes<unknown>['undefined'] type AssociatedTypeNames = keyof AssociatedTypes<unknown>['undefined']
type ALookup<T, Name extends AssociatedTypeNames> = { type ALookup<T, Name extends AssociatedTypeNames> = ValueIntersectionByKeyUnion<{
[K in keyof AssociatedTypes<T>]: [K in keyof AssociatedTypes<T>]:
T extends AssociatedTypes<T>[K]['type'] ? AssociatedTypes<T>[K][Name] : never T extends AssociatedTypes<T>[K]['type'] ? AssociatedTypes<T>[K][Name] : unknown},
}[keyof AssociatedTypes<T>] keyof AssociatedTypes<T>>
// For everything to compile, zero and one must be subtypes of T: // For everything to compile, zero and one must be subtypes of T:
export type ZeroType<T> = ALookup<T, 'zero'> & T export type ZeroType<T> = ALookup<T, 'zero'> & T
@ -68,8 +74,17 @@ export interface Signatures<T> {
type SignatureKey<T> = keyof Signatures<T> type SignatureKey<T> = keyof Signatures<T>
export type Signature<Name, T> = Signatures<T>[Name & SignatureKey<T>] export type Signature<Name extends SignatureKey<T>, T> = Signatures<T>[Name]
export type Returns<Name extends SignatureKey<T>, T> = ReturnType<Signatures<T>[Name]> export type Returns<Name extends SignatureKey<T>, T> =
export type Dependencies<Name, T> = {[K in Name & SignatureKey<T>]: Signature<K, 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} 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,25 +1,35 @@
import type {configDependency} from '../core/Config.js' import type {configDependency} from '../core/Config.js'
import type {Dependencies, Signature} from '../interfaces/type.js' import type {Dependencies, Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const add: Signature<'add', number> = (a, b) => a + b export const add = (): Signature<'add', number> => (a, b) => a + b
export const unaryMinus: Signature<'unaryMinus', number> = a => -a const unaMinus = (a: number) => -a
export const conj: Signature<'conj', number> = a => a export const unaryMinus = (): Signature<'unaryMinus', number> => unaMinus
export const subtract: Signature<'subtract', number> = (a, b) => a - b export const conj = (): Signature<'conj', number> => a => a
export const multiply: Signature<'multiply', number> = (a, b) => a * b export const subtract = (): Signature<'subtract', number> => (a, b) => a - b
export const absquare: Signature<'absquare', number> = a => a * a export const multiply = (): Signature<'multiply', number> => (a, b) => a * b
export const reciprocal: Signature<'reciprocal', number> = a => 1 / a export const absquare = (): Signature<'absquare', number> => a => a * a
export const divide: Signature<'divide', number> = (a, b) => a / b export const reciprocal = (): Signature<'reciprocal', number> => a => 1 / a
export const divide = (): Signature<'divide', number> => (a, b) => a / b
const basicSqrt = 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 conservativeSqrt = (): Signature<'conservativeSqrt', number> =>
basicSqrt
export const sqrt = export const sqrt =
(dep: configDependency & Dependencies<'complex', number>): (dep: configDependency
Signature<'sqrt', number> => { & Dependencies<'complex', number>): Signature<'sqrt', number> => {
if (dep.config.predictable || !dep.complex) return basicSqrt if (dep.config.predictable || !dep.complex) {
return a => { return basicSqrt
if (isNaN(a)) return NaN }
if (a >= 0) return Math.sqrt(a) return a => {
return dep.complex(0, Math.sqrt(unaryMinus(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,2 +1,4 @@
export * from './type.js' export * from './type.js'
export * from './arithmetic.js' export * from './arithmetic.js'
export * from './predicate.js'
export * from './relational.js'

View File

@ -1,4 +1,7 @@
import type {Signature} from '../interfaces/type.js' import type {Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
export const isReal: Signature<'isReal', number> = (a) => true export const isReal = (): Signature<'isReal', number> => (a) => true
export const isSquare: Signature<'isSquare', number> = (a) => a >= 0 export const isSquare = (): Signature<'isSquare', number> => (a) => a >= 0
$reflect!([isReal, isSquare])

View File

@ -1,5 +1,6 @@
import {configDependency} from '../core/Config.js' import {configDependency} from '../core/Config.js'
import {Signature} from '../interfaces/type.js' import {Signature} from '../interfaces/type.js'
import {$reflect} from '../interfaces/type.js'
const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16 const DBL_EPSILON = Number.EPSILON || 2.2204460492503130808472633361816E-16
@ -19,3 +20,4 @@ export const equal =
return false return false
} }
$reflect!([equal])

View File

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

View File

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