Add another experiment infer2 (WIP)

This commit is contained in:
Jos de Jong 2023-03-14 09:51:28 +01:00
parent aa044a54e7
commit f8553aa748
6 changed files with 142 additions and 28 deletions

View file

@ -0,0 +1,15 @@
import { infer } from '../generic/infer'
import { Dependencies, Signature } from '../interfaces/type'
export type multiplyDep<T> = Dependencies<'multiply', T>
export const square1 =
<T>(dep: Dependencies<'multiply', T>): Signature<'square', T> =>
z => dep.multiply(z, z)
export const square2 = infer(<T>(dep: {
multiply: (a: number, b: number) => number,
unaryMinus: (x: number) => number, // just for the experiment
}): (a: number) => number =>
z => dep.multiply(z, z)
)

View file

@ -2,32 +2,6 @@ import { readFileSync } from "fs";
import * as ts from "typescript";
import { inspect } from 'util'
/**
* # The idea
*
* Create a TypeScript plugin which can replace structures like:
*
* infer(factoryFunction)
*
* where `factoryFunction` is a mathjs factory function in TypeScript, with something like:
*
* infer({ signature: factoryFunction })
*
* where `signature` is a string containing the type of the factory function and its dependencies.
*
* # How to run
*
* pnpm experiment-infer
* pnpm experiment-infer-direct
*
* # 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
*/
export function infer(sourceFile: ts.SourceFile) {
recurse(sourceFile);

74
src/plugins/infer2.ts Normal file
View file

@ -0,0 +1,74 @@
import * as ts from "typescript"
// based on: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#using-the-type-checker
infer2(process.argv.slice(2), {
target: ts.ScriptTarget.ES5,
module: ts.ModuleKind.CommonJS
})
function infer2(
fileNames: string[],
options: ts.CompilerOptions
): void {
const program = ts.createProgram(fileNames, options)
const typeChecker = program.getTypeChecker()
for (const sourceFile of program.getSourceFiles()) {
if (!sourceFile.isDeclarationFile) {
ts.forEachChild(sourceFile, visit)
}
}
return
function visit(node: ts.Node) {
// // Only consider exported nodes
// if (!isNodeExported(node)) {
// return;
// }
// console.log('Node', node.kind, node?.['name']?.escapedText)
if (ts.isModuleDeclaration(node)) {
// This is a namespace, visit its children
console.log('check')
ts.forEachChild(node, visit);
} else if (ts.isTypeAliasDeclaration(node)) {
console.log('isTypeAliasDeclaration', node.name.escapedText)
let symbol = typeChecker.getSymbolAtLocation(node.name);
if (symbol) {
const symbolType = typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration)
const symbolSignature = typeChecker.getSignaturesOfType(symbolType, ts.SignatureKind.Call)
// checker.getResolvedSignature(symbol)
console.log('symbol', symbol.getName(), symbolSignature)
// getTypeOfSymbolAtLocation
// getResolvedSignature
}
} else if (ts.isCallExpression(node)) {
console.log('isCallExpression', node.expression)
} else if (ts.isFunctionDeclaration(node)) {
console.log('isFunctionDeclaration', node.name.escapedText, { typeParameter0: node.typeParameters[0] })
if (node.name.escapedText === 'infer') {
const param0 = node.typeParameters[0]
if (ts.isPropertyDeclaration(param0)) {
const symbol = typeChecker.getSymbolAtLocation(param0)
// TODO: get resolving
// console.log('getResolvedSignature', typeChecker.getResolvedSignature(node) )
// const symbolType = typeChecker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration)
// const symbolSignature = typeChecker.getSignaturesOfType(symbolType, ts.SignatureKind.Call)
// console.log('symbol', symbol.getName(), symbolSignature)
// console.log('getSignaturesOfType', typeChecker.getSignaturesOfType(param0)
}
}
}
}
}