some refinements in the plugin
This commit is contained in:
parent
cbb79d46fe
commit
d50c1a9ccf
@ -16,7 +16,7 @@ Have a look at the section under `/src/experiment` and `/src/plugins`:
|
|||||||
- `src/plugins/typeInferPlugin.ts` is the actual plugin
|
- `src/plugins/typeInferPlugin.ts` is the actual plugin
|
||||||
- in `tsconfig.json` we configure TypeScript to run the plugin
|
- in `tsconfig.json` we configure TypeScript to run the plugin
|
||||||
- `src/experiment/arithmeticInfer.ts` with an example where we define `__infer__`
|
- `src/experiment/arithmeticInfer.ts` with an example where we define `__infer__`
|
||||||
- `build/experiment/arithmeticInfer.ts` where the `__infer__` string literal is replace with the actual types
|
- after running TypeScript: look at `build/experiment/arithmeticInfer.ts` where the `__infer__` string literal is replaced with the actual types
|
||||||
|
|
||||||
### The idea
|
### The idea
|
||||||
|
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
export function infer<T>(arg: T) : T {
|
|
||||||
console.error('infer should be replaced with runtime type information by a magic TypeScript plugin')
|
|
||||||
return arg
|
|
||||||
}
|
|
||||||
|
|
||||||
export function typed<T>(name: string, types: string, arg: T) : T {
|
export function typed<T>(name: string, types: string, arg: T) : T {
|
||||||
// TODO: implement typed-function for real
|
// TODO: implement typed-function for real
|
||||||
if (types === '__infer__') {
|
if (types === '__infer__') {
|
||||||
console.error('__infer__ should be replaced with runtime type information by the TypeScript plugin')
|
console.error('__infer__ should be replaced with runtime type information by the TypeScript plugin')
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Creating typed-function "${name}" with types ${types}`)
|
console.log(`TYPED-FUNCTION: Creating function "${name}" with types ${types}`)
|
||||||
return arg
|
return arg
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { typed } from '../generic/infer'
|
import { typed } from '../core/typed.js'
|
||||||
|
|
||||||
export const square = typed('square', '__infer__', <T>(dep: {
|
export const square = typed('square', '__infer__', <T>(dep: {
|
||||||
multiply: (a: T, b: T) => T,
|
multiply: (a: T, b: T) => T,
|
||||||
|
@ -6,45 +6,44 @@ const transformer: ts.TransformerFactory<ts.SourceFile> = context => {
|
|||||||
const checker = program.getTypeChecker()
|
const checker = program.getTypeChecker()
|
||||||
|
|
||||||
return sourceFile => {
|
return sourceFile => {
|
||||||
// For the experiment we only want to influence a single file
|
|
||||||
if (!sourceFile.fileName.endsWith('arithmeticInfer.ts')) {
|
|
||||||
return sourceFile
|
|
||||||
}
|
|
||||||
|
|
||||||
const visitor = (node: ts.Node): ts.Node => {
|
const visitor = (node: ts.Node): ts.Node => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (ts.isStringLiteral(node) && node.text === '__infer__') {
|
if (ts.isStringLiteral(node) && node.text === '__infer__') {
|
||||||
console.log('FOUND AN OCCURRENCE OF __infer__')
|
console.log('PLUGIN: FOUND AN OCCURRENCE OF __infer__')
|
||||||
|
|
||||||
|
// we're looking for a function call like typed('name', '__infer__', deps => ...)
|
||||||
const parentNode = node.parent
|
const parentNode = node.parent
|
||||||
// console.log('PARENT')
|
if (ts.isCallExpression(parentNode) && ts.isIdentifier(parentNode.expression) && parentNode.expression.escapedText === 'typed') {
|
||||||
// console.log(parentNode)
|
// console.log('PARENT')
|
||||||
|
// console.log(parentNode)
|
||||||
|
|
||||||
// TODO: validate that the parent is indeed a mathjs typed function with deps
|
// TODO: validate that argNode is an ArrowFunction
|
||||||
|
// @ts-ignore
|
||||||
|
const argNode = parentNode.arguments[2]
|
||||||
|
// @ts-ignore
|
||||||
|
const returnType = argNode.type.getText(sourceFile)
|
||||||
|
console.log('PLUGIN: RETURN TYPE')
|
||||||
|
console.log(returnType)
|
||||||
|
// (a: number) => number
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const argNode = parentNode.arguments[2]
|
const paramNode = argNode.parameters[0]
|
||||||
const returnType = argNode.type.getText(sourceFile)
|
const paramTypeSrc = paramNode.type.getText(sourceFile)
|
||||||
console.log('RETURN TYPE')
|
console.log('PLUGIN: PARAM TYPE SRC', paramTypeSrc)
|
||||||
console.log(returnType)
|
// {
|
||||||
// (a: number) => number
|
// multiply: (a: number, b: number) => number,
|
||||||
|
// unaryMinus: (x: number) => number, // just for the experiment
|
||||||
|
// }
|
||||||
|
|
||||||
const paramNode = argNode.parameters[0]
|
const type = checker.getTypeAtLocation(paramNode)
|
||||||
const paramTypeSrc = paramNode.type.getText(sourceFile)
|
const paramType = checker.typeToString(type, paramNode, ts.TypeFormatFlags.InTypeAlias)
|
||||||
console.log('PARAM TYPE SRC', paramTypeSrc)
|
console.log('PLUGIN: PARAM TYPE STRING', paramType)
|
||||||
// {
|
// { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; }
|
||||||
// multiply: (a: number, b: number) => number,
|
|
||||||
// unaryMinus: (x: number) => number, // just for the experiment
|
|
||||||
// }
|
|
||||||
|
|
||||||
const type = checker.getTypeAtLocation(paramNode)
|
const depsAndReturnType = `{ deps: ${paramType}; return: ${returnType} }`
|
||||||
const paramType = checker.typeToString(type, paramNode, ts.TypeFormatFlags.InTypeAlias)
|
|
||||||
console.log('PARAM TYPE STRING', paramType)
|
|
||||||
// { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; }
|
|
||||||
|
|
||||||
const depsAndReturnType = `{ deps: ${paramType}; return: ${returnType} }`
|
return ts.factory.createStringLiteral(depsAndReturnType)
|
||||||
|
}
|
||||||
return ts.factory.createStringLiteral(depsAndReturnType)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ts.visitEachChild(node, visitor, context)
|
return ts.visitEachChild(node, visitor, context)
|
||||||
|
Loading…
Reference in New Issue
Block a user