From 7fc9d2a2f360742c262934ed0443d08a54502d16 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Fri, 8 Sep 2023 14:10:03 +0200 Subject: [PATCH 1/2] remove name argument from the reflect function --- src/core/{typed.ts => $reflect.ts} | 4 ++-- src/experiment/arithmeticInfer.ts | 4 ++-- src/plugins/typeInferPlugin.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/core/{typed.ts => $reflect.ts} (65%) diff --git a/src/core/typed.ts b/src/core/$reflect.ts similarity index 65% rename from src/core/typed.ts rename to src/core/$reflect.ts index 3306776..abd069d 100644 --- a/src/core/typed.ts +++ b/src/core/$reflect.ts @@ -1,10 +1,10 @@ -export function typed(name: string, types: string, arg: T) : T { +export function $reflect(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}`) + 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/experiment/arithmeticInfer.ts b/src/experiment/arithmeticInfer.ts index be544a3..c36ed92 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('__infer__', (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..08a19ae 100644 --- a/src/plugins/typeInferPlugin.ts +++ b/src/plugins/typeInferPlugin.ts @@ -13,13 +13,13 @@ const transformer: ts.TransformerFactory = context => { // 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') { + if (ts.isCallExpression(parentNode) && ts.isIdentifier(parentNode.expression) && parentNode.expression.escapedText === '$reflect') { // console.log('PARENT') // console.log(parentNode) // TODO: validate that argNode is an ArrowFunction // @ts-ignore - const argNode = parentNode.arguments[2] + const argNode = parentNode.arguments[1] // @ts-ignore const returnType = argNode.type.getText(sourceFile) console.log('PLUGIN: RETURN TYPE') From 232d5d4a96b3d9face1ba428224d631d28a44330 Mon Sep 17 00:00:00 2001 From: Jos de Jong Date: Fri, 8 Sep 2023 14:25:14 +0200 Subject: [PATCH 2/2] make defining `__infer__` redundant --- src/core/$reflect.ts | 6 ++-- src/experiment/arithmeticInfer.ts | 2 +- src/plugins/typeInferPlugin.ts | 60 +++++++++++++++---------------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/core/$reflect.ts b/src/core/$reflect.ts index abd069d..ca4f920 100644 --- a/src/core/$reflect.ts +++ b/src/core/$reflect.ts @@ -1,7 +1,7 @@ -export function $reflect(types: string, arg: T) : T { +export function $reflect(arg: T, types?: string) : T { // TODO: implement typed-function for real - if (types === '__infer__') { - console.error('__infer__ should be replaced with runtime type information by the TypeScript plugin') + if (!types) { + console.error('types should be resolved with runtime type information by the TypeScript plugin') } console.log(`INFER: Creating function with types ${types}`) diff --git a/src/experiment/arithmeticInfer.ts b/src/experiment/arithmeticInfer.ts index c36ed92..4a4a6e6 100644 --- a/src/experiment/arithmeticInfer.ts +++ b/src/experiment/arithmeticInfer.ts @@ -1,6 +1,6 @@ import { $reflect } from '../core/$reflect.js' -export const square = $reflect('__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 08a19ae..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 === '$reflect') { - // 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[1] - // @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)