Compare commits
22 Commits
main
...
experiment
Author | SHA1 | Date |
---|---|---|
Jos de Jong | ab7fc4450e | |
Jos de Jong | 94a0737555 | |
Jos de Jong | 24bcf34b60 | |
Jos de Jong | 232d5d4a96 | |
Jos de Jong | 7fc9d2a2f3 | |
Jos de Jong | 26631febf9 | |
Jos de Jong | 3967f5ce2b | |
Jos de Jong | d50c1a9ccf | |
Jos de Jong | cbb79d46fe | |
Jos de Jong | dea521029e | |
Jos de Jong | 2cb8bc0099 | |
Jos de Jong | 3653077c95 | |
Glen Whitney | 16eb09fe61 | |
Jos de Jong | 6a063d7385 | |
Jos de Jong | f8553aa748 | |
Jos de Jong | aa044a54e7 | |
Jos de Jong | b9cfe706fc | |
Jos de Jong | 946b4a495f | |
Jos de Jong | 86688ca129 | |
Jos de Jong | 5872bd8537 | |
Jos de Jong | 1f2a59c802 | |
Jos de Jong | 35a8c62ff2 |
|
@ -2,7 +2,7 @@
|
||||||
*~
|
*~
|
||||||
# Typescript
|
# Typescript
|
||||||
# emitted code
|
# emitted code
|
||||||
obj
|
build
|
||||||
|
|
||||||
# ---> Node
|
# ---> Node
|
||||||
# Logs
|
# Logs
|
||||||
|
|
45
README.md
45
README.md
|
@ -5,6 +5,47 @@ A final (?) prototype for a refactor of mathjs, culminating the picomath, pocoma
|
||||||
To build and run the prototype, run:
|
To build and run the prototype, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
npx tsc
|
pnpm install
|
||||||
node obj
|
pnpm build-and-run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## experiment
|
||||||
|
|
||||||
|
Have a look at the section under `/src/experiment` and `/src/plugins`:
|
||||||
|
|
||||||
|
- `src/plugins/typeInferPlugin.ts` is the actual plugin
|
||||||
|
- in `tsconfig.json` we configure TypeScript to run the plugin
|
||||||
|
- `src/experiment/arithmeticInfer.ts` with an example where we define `__infer__`
|
||||||
|
- after running TypeScript: look at `build/experiment/arithmeticInfer.ts` where the `__infer__` string literal is replaced with the actual types
|
||||||
|
|
||||||
|
### The idea
|
||||||
|
|
||||||
|
Create a TypeScript plugin which can replace a string literal like `__infer__` in a typed-function definition:
|
||||||
|
|
||||||
|
typed('square', '__infer__', <T>(dep: { ... } => { ... })
|
||||||
|
|
||||||
|
with the actual types, something like:
|
||||||
|
|
||||||
|
typed('square', '{ deps: { multiply: (a: T, b: T) => T; }; return: (a: T) => T }', <T>(dep: { ... } => { ... })
|
||||||
|
|
||||||
|
(We can discuss what syntax we like most, this is just a POC)
|
||||||
|
|
||||||
|
### How to run
|
||||||
|
|
||||||
|
pnpm build-and-run
|
||||||
|
|
||||||
|
### Read more
|
||||||
|
|
||||||
|
- https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin
|
||||||
|
- https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
|
||||||
|
- https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker
|
||||||
|
- https://github.com/Microsoft/TypeScript/wiki/Using-the-Language-Service-API
|
||||||
|
- https://stackoverflow.com/questions/63944135/typescript-compiler-api-how-to-get-type-with-resolved-type-arguments
|
||||||
|
- https://stackoverflow.com/questions/48886508/typechecker-api-how-do-i-find-inferred-type-arguments-to-a-function
|
||||||
|
- https://blog.logrocket.com/using-typescript-transforms-to-enrich-runtime-code-3fd2863221ed/
|
||||||
|
- https://github.com/itsdouges/typescript-transformer-handbook#transforms
|
||||||
|
|
||||||
|
### Interesting libraries
|
||||||
|
|
||||||
|
- https://github.com/GoogleFeud/ts-macros/
|
||||||
|
- https://ts-morph.com
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
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',
|
'go': 'ttsc && echo {"type":"module"} > build/package.json && node build/index.js',
|
||||||
},
|
},
|
||||||
keywords: [
|
keywords: [
|
||||||
'math',
|
'math',
|
||||||
|
@ -17,7 +17,12 @@
|
||||||
type: 'git',
|
type: 'git',
|
||||||
url: 'https://code.studioinfinity.org/glen/typocomath.git',
|
url: 'https://code.studioinfinity.org/glen/typocomath.git',
|
||||||
},
|
},
|
||||||
|
dependencies: {
|
||||||
|
'@types/node': '20.5.7',
|
||||||
|
},
|
||||||
devDependencies: {
|
devDependencies: {
|
||||||
typescript: '^4.9.3',
|
'ts-node': '10.9.1',
|
||||||
|
ttypescript: '1.5.15',
|
||||||
|
typescript: '4.7.4',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
183
pnpm-lock.yaml
183
pnpm-lock.yaml
|
@ -1,15 +1,186 @@
|
||||||
lockfileVersion: 5.4
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
specifiers:
|
settings:
|
||||||
typescript: ^4.9.3
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
'@types/node':
|
||||||
|
specifier: 20.5.7
|
||||||
|
version: 20.5.7
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
typescript: 4.9.3
|
ts-node:
|
||||||
|
specifier: 10.9.1
|
||||||
|
version: 10.9.1(@types/node@20.5.7)(typescript@4.7.4)
|
||||||
|
ttypescript:
|
||||||
|
specifier: 1.5.15
|
||||||
|
version: 1.5.15(ts-node@10.9.1)(typescript@4.7.4)
|
||||||
|
typescript:
|
||||||
|
specifier: 4.7.4
|
||||||
|
version: 4.7.4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
/typescript/4.9.3:
|
/@cspotcode/source-map-support@0.8.1:
|
||||||
resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==}
|
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/trace-mapping': 0.3.9
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@jridgewell/resolve-uri@3.1.1:
|
||||||
|
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@jridgewell/sourcemap-codec@1.4.15:
|
||||||
|
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@jridgewell/trace-mapping@0.3.9:
|
||||||
|
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.1.1
|
||||||
|
'@jridgewell/sourcemap-codec': 1.4.15
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@tsconfig/node10@1.0.9:
|
||||||
|
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@tsconfig/node12@1.0.11:
|
||||||
|
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@tsconfig/node14@1.0.3:
|
||||||
|
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@tsconfig/node16@1.0.4:
|
||||||
|
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@types/node@20.5.7:
|
||||||
|
resolution: {integrity: sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==}
|
||||||
|
|
||||||
|
/acorn-walk@8.2.0:
|
||||||
|
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/acorn@8.10.0:
|
||||||
|
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
|
||||||
|
engines: {node: '>=0.4.0'}
|
||||||
|
hasBin: true
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/arg@4.1.3:
|
||||||
|
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/create-require@1.1.1:
|
||||||
|
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/diff@4.0.2:
|
||||||
|
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||||
|
engines: {node: '>=0.3.1'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/function-bind@1.1.1:
|
||||||
|
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||||
|
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
|
||||||
|
|
||||||
|
/is-core-module@2.13.0:
|
||||||
|
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
|
||||||
|
dependencies:
|
||||||
|
has: 1.0.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/make-error@1.3.6:
|
||||||
|
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/path-parse@1.0.7:
|
||||||
|
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||||
|
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
|
||||||
|
|
||||||
|
/supports-preserve-symlinks-flag@1.0.0:
|
||||||
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
|
engines: {node: '>= 0.4'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/ts-node@10.9.1(@types/node@20.5.7)(typescript@4.7.4):
|
||||||
|
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
'@swc/core': '>=1.2.50'
|
||||||
|
'@swc/wasm': '>=1.2.50'
|
||||||
|
'@types/node': '*'
|
||||||
|
typescript: '>=2.7'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@swc/core':
|
||||||
|
optional: true
|
||||||
|
'@swc/wasm':
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@cspotcode/source-map-support': 0.8.1
|
||||||
|
'@tsconfig/node10': 1.0.9
|
||||||
|
'@tsconfig/node12': 1.0.11
|
||||||
|
'@tsconfig/node14': 1.0.3
|
||||||
|
'@tsconfig/node16': 1.0.4
|
||||||
|
'@types/node': 20.5.7
|
||||||
|
acorn: 8.10.0
|
||||||
|
acorn-walk: 8.2.0
|
||||||
|
arg: 4.1.3
|
||||||
|
create-require: 1.1.1
|
||||||
|
diff: 4.0.2
|
||||||
|
make-error: 1.3.6
|
||||||
|
typescript: 4.7.4
|
||||||
|
v8-compile-cache-lib: 3.0.1
|
||||||
|
yn: 3.1.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/ttypescript@1.5.15(ts-node@10.9.1)(typescript@4.7.4):
|
||||||
|
resolution: {integrity: sha512-48ykDNHzFnPMnv4hYX1P8Q84TvCZyL1QlFxeuxsuZ48X2+ameBgPenvmCkHJtoOSxpoWTWi8NcgNrRnVDOmfSg==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
ts-node: '>=8.0.2'
|
||||||
|
typescript: '>=3.2.2'
|
||||||
|
dependencies:
|
||||||
|
resolve: 1.22.4
|
||||||
|
ts-node: 10.9.1(@types/node@20.5.7)(typescript@4.7.4)
|
||||||
|
typescript: 4.7.4
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/typescript@4.7.4:
|
||||||
|
resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==}
|
||||||
engines: {node: '>=4.2.0'}
|
engines: {node: '>=4.2.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/v8-compile-cache-lib@3.0.1:
|
||||||
|
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/yn@3.1.1:
|
||||||
|
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
dev: true
|
||||||
|
|
|
@ -1,6 +1,2 @@
|
||||||
import * as Complex from './native.js'
|
export * as Complex from './native.js'
|
||||||
import * as complex from './arithmetic.js'
|
export * as complex from './arithmetic.js'
|
||||||
|
|
||||||
export { complex }
|
|
||||||
|
|
||||||
export {Complex}
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
export function $reflect<T>(arg: T, types?: string) : T {
|
||||||
|
// TODO: implement typed-function for real
|
||||||
|
if (!types) {
|
||||||
|
console.error('types should be resolved with runtime type information by the TypeScript plugin')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`INFER: Creating function with types ${types}`)
|
||||||
|
|
||||||
|
// TODO: here we can now turn the inputs into a real typed-function with a signature
|
||||||
|
return arg
|
||||||
|
}
|
|
@ -46,13 +46,17 @@ export class Dispatcher {
|
||||||
// that's really possible, though.
|
// that's really possible, though.
|
||||||
) {
|
) {
|
||||||
console.log('Pretending to install', name, signature, '=>', returns)
|
console.log('Pretending to install', name, signature, '=>', returns)
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
// console.log(name, 'signature', reflect(signature))
|
||||||
|
// console.log(name, 'dependencies', reflect(dependencies))
|
||||||
//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) {
|
||||||
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]) {
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { $reflect } from '../core/$reflect.js'
|
||||||
|
import { Dependencies } from '../interfaces/type.js'
|
||||||
|
|
||||||
|
// unaryMinus dep is just for the experiment
|
||||||
|
// FIXME: the typescript plugin should resolve Dependencies<'multiply' | 'unaryMinus', T>
|
||||||
|
export const square = $reflect(<T>(dep: Dependencies<'multiply' | 'unaryMinus', T>): (a: T) => T =>
|
||||||
|
z => dep.multiply(z, z)
|
||||||
|
)
|
||||||
|
|
||||||
|
// export const square2 = function $reflect<T>(dep: Dependencies<'multiply' | 'unaryMinus', T>) {
|
||||||
|
// return (z: T) => dep.multiply(z, z)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export const square = $reflect(<T>(dep: {
|
||||||
|
// multiply: (a: T, b: T) => T,
|
||||||
|
// unaryMinus: (x: T) => T, // just for the experiment
|
||||||
|
// }): (a: T) => T =>
|
||||||
|
// z => dep.multiply(z, z)
|
||||||
|
// )
|
36
src/index.ts
36
src/index.ts
|
@ -1,20 +1,28 @@
|
||||||
import {Dispatcher} from './core/Dispatcher.js'
|
import { Complex } from './Complex/type.js'
|
||||||
import * as Specifications from './all.js'
|
import { absquare as absquare_complex } from './Complex/arithmetic.js'
|
||||||
|
import { square } from './experiment/arithmeticInfer.js'
|
||||||
|
|
||||||
export default new Dispatcher(Specifications)
|
const add = (a: number, b: number) => a + b
|
||||||
|
const multiply = (a: number, b: number) => a * b
|
||||||
import {Complex} from './Complex/type.js'
|
const unaryMinus = (a: number) => -a
|
||||||
import {absquare as absquare_complex} from './Complex/arithmetic.js'
|
const absquare = (z: Complex<number>) => z.re * z.re + z.im * z.im
|
||||||
|
|
||||||
const mockRealAdd = (a: number, b: number) => a+b
|
|
||||||
const mockComplexAbsquare = (z: Complex<number>) => z.re*z.re + z.im*z.im
|
|
||||||
|
|
||||||
const quatAbsquare = absquare_complex({
|
const quatAbsquare = absquare_complex({
|
||||||
add: mockRealAdd,
|
add,
|
||||||
absquare: mockComplexAbsquare
|
absquare
|
||||||
})
|
})
|
||||||
|
|
||||||
const myabs = quatAbsquare({re: {re: 0, im: 1}, im: {re:2, im: 3}})
|
const result = 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 result = 7 // check myabs is just a number
|
||||||
|
|
||||||
console.log('Result is', myabs)
|
console.log()
|
||||||
|
console.log('Result is', result)
|
||||||
|
|
||||||
|
|
||||||
|
const mySquare = square({
|
||||||
|
multiply,
|
||||||
|
unaryMinus
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
console.log('mySquare(4)=', mySquare(4))
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
import * as numbers from './native.js'
|
export * as numbers from './native.js'
|
||||||
|
|
||||||
export {numbers}
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const absquare: Signature<'absquare', number> = a => a * a
|
||||||
export const reciprocal: Signature<'reciprocal', number> = a => 1 / a
|
export const reciprocal: Signature<'reciprocal', number> = a => 1 / a
|
||||||
export const divide: Signature<'divide', number> = (a, b) => a / b
|
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 =
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
import ts from 'typescript'
|
||||||
|
|
||||||
|
const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
|
||||||
|
// TODO: get a reference to the program instance that the plugin is running in instead of creating a new program?
|
||||||
|
const program = ts.createProgram([], {})
|
||||||
|
const checker = program.getTypeChecker()
|
||||||
|
|
||||||
|
return sourceFile => {
|
||||||
|
const visitor = (node: ts.Node): ts.Node => {
|
||||||
|
// we're looking for a function call like $reflect(deps => ...)
|
||||||
|
// @ts-ignore
|
||||||
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.escapedText === '$reflect') {
|
||||||
|
console.log('PLUGIN: FOUND AN OCCURRENCE OF $reflect')
|
||||||
|
// console.log('PARENT')
|
||||||
|
// console.log(node)
|
||||||
|
|
||||||
|
// TODO: validate that argNode is an ArrowFunction
|
||||||
|
// @ts-ignore
|
||||||
|
const argNode = node.arguments[0]
|
||||||
|
// @ts-ignore
|
||||||
|
const returnType = argNode.type.getText(sourceFile)
|
||||||
|
console.log('PLUGIN: RETURN TYPE')
|
||||||
|
console.log(returnType)
|
||||||
|
// (a: number) => number
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
const paramNode = argNode.parameters[0]
|
||||||
|
const paramTypeSrc = paramNode.type.getText(sourceFile)
|
||||||
|
console.log('PLUGIN: PARAM TYPE SRC', paramTypeSrc)
|
||||||
|
// {
|
||||||
|
// multiply: (a: number, b: number) => number,
|
||||||
|
// unaryMinus: (x: number) => number, // just for the experiment
|
||||||
|
// }
|
||||||
|
|
||||||
|
// WIP
|
||||||
|
// @ts-ignore
|
||||||
|
const type = checker.getTypeAtLocation(paramNode)
|
||||||
|
const paramType = checker.typeToString(type, undefined, ts.TypeFormatFlags.InTypeAlias)
|
||||||
|
// const paramType = checker.typeToString(type)
|
||||||
|
// TDOO: get checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration)
|
||||||
|
console.log('PLUGIN: PARAM TYPE STRING', paramType)
|
||||||
|
// { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; }
|
||||||
|
|
||||||
|
|
||||||
|
// WIP
|
||||||
|
// For a function definition
|
||||||
|
// const signature = checker.getResolvedSignature(node);
|
||||||
|
// if (signature != null) {
|
||||||
|
// // outputs -- (Ctor: Ctor<Bar>): void
|
||||||
|
// console.log(signature)
|
||||||
|
// console.log('TEST 1', checker.signatureToString(signature));
|
||||||
|
// // @ts-ignore
|
||||||
|
// // console.log('TEST 2', checker.getResolvedSignatureForStringLiteralCompletions(node));
|
||||||
|
// const params = signature.getParameters();
|
||||||
|
// for (const param of params) {
|
||||||
|
// const type = checker.getTypeOfSymbolAtLocation(param, node);
|
||||||
|
// // outputs -- Ctor<Bar>
|
||||||
|
// console.log('TEST 3', checker.typeToString(type));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// WIP
|
||||||
|
const type1 = checker.getTypeAtLocation(paramNode)
|
||||||
|
const type2 = checker.getApparentType(type1)
|
||||||
|
const typeStr = checker.typeToString(type2, undefined, ts.TypeFormatFlags.InTypeAlias)
|
||||||
|
console.log('PLUGIN: RESOLVED TYPE ARGUMENT', typeStr) // TODO: not yet working
|
||||||
|
|
||||||
|
const depsAndReturnType = `{ deps: ${paramType}; return: ${returnType} }`
|
||||||
|
|
||||||
|
// Now we insert a second argument to the $reflect function call: a string with the types
|
||||||
|
// @ts-ignore
|
||||||
|
node.arguments.push(ts.factory.createStringLiteral(depsAndReturnType))
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts.visitEachChild(node, visitor, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ts.visitNode(sourceFile, visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default transformer
|
|
@ -2,6 +2,14 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
"outDir": "./obj"
|
"outDir": "./build",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"allowJs": false,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"plugins": [{
|
||||||
|
"transform": "./src/plugins/typeInferPlugin.ts",
|
||||||
|
"type": "raw"
|
||||||
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue