diff --git a/src/core/$reflect.ts b/src/core/$reflect.ts new file mode 100644 index 0000000..ca4f920 --- /dev/null +++ b/src/core/$reflect.ts @@ -0,0 +1,11 @@ +export function $reflect(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 +} diff --git a/src/core/typed.ts b/src/core/typed.ts deleted file mode 100644 index 3306776..0000000 --- a/src/core/typed.ts +++ /dev/null @@ -1,11 +0,0 @@ -export function typed(name: string, types: string, arg: T) : T { - // TODO: implement typed-function for real - if (types === '__infer__') { - console.error('__infer__ should be replaced with runtime type information by the TypeScript plugin') - } - - console.log(`TYPED-FUNCTION: Creating function "${name}" with types ${types}`) - - // TODO: here we can now turn the inputs into a real typed-function with a signature - return arg -} diff --git a/src/experiment/arithmeticInfer.ts b/src/experiment/arithmeticInfer.ts index be544a3..4a4a6e6 100644 --- a/src/experiment/arithmeticInfer.ts +++ b/src/experiment/arithmeticInfer.ts @@ -1,6 +1,6 @@ -import { typed } from '../core/typed.js' +import { $reflect } from '../core/$reflect.js' -export const square = typed('square', '__infer__', (dep: { +export const square = $reflect((dep: { multiply: (a: T, b: T) => T, unaryMinus: (x: T) => T, // just for the experiment }): (a: T) => T => diff --git a/src/plugins/typeInferPlugin.ts b/src/plugins/typeInferPlugin.ts index 4ca6c21..84c0dcf 100644 --- a/src/plugins/typeInferPlugin.ts +++ b/src/plugins/typeInferPlugin.ts @@ -7,43 +7,43 @@ const transformer: ts.TransformerFactory = context => { return sourceFile => { const visitor = (node: ts.Node): ts.Node => { + // we're looking for a function call like $reflect(deps => ...) // @ts-ignore - if (ts.isStringLiteral(node) && node.text === '__infer__') { - console.log('PLUGIN: FOUND AN OCCURRENCE OF __infer__') + 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) - // we're looking for a function call like typed('name', '__infer__', deps => ...) - const parentNode = node.parent - if (ts.isCallExpression(parentNode) && ts.isIdentifier(parentNode.expression) && parentNode.expression.escapedText === 'typed') { - // console.log('PARENT') - // console.log(parentNode) + // 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 - // 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 + 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 + // } - // @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 - // } + const type = checker.getTypeAtLocation(paramNode) + const paramType = checker.typeToString(type, paramNode, ts.TypeFormatFlags.InTypeAlias) + console.log('PLUGIN: PARAM TYPE STRING', paramType) + // { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; } - const type = checker.getTypeAtLocation(paramNode) - const paramType = checker.typeToString(type, paramNode, ts.TypeFormatFlags.InTypeAlias) - console.log('PLUGIN: PARAM TYPE STRING', paramType) - // { multiply: (a: number, b: number) => number; unaryMinus: (x: number) => number; } + const depsAndReturnType = `{ deps: ${paramType}; return: ${returnType} }` - 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 ts.factory.createStringLiteral(depsAndReturnType) - } + return node } return ts.visitEachChild(node, visitor, context)