diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/context.ts | 8 | ||||
| -rw-r--r-- | src/eval-env/builtins.ts | 236 | ||||
| -rw-r--r-- | src/eval-env/test.ts | 2 | ||||
| -rw-r--r-- | src/eval.ts | 20 | ||||
| -rw-r--r-- | src/index.ts | 7 | ||||
| -rw-r--r-- | src/types.ts | 12 | ||||
| -rw-r--r-- | src/util.ts | 4 |
7 files changed, 149 insertions, 140 deletions
diff --git a/src/context.ts b/src/context.ts index 485083a..06fe041 100644 --- a/src/context.ts +++ b/src/context.ts @@ -61,12 +61,12 @@ export const createContext = (options: CtxOptions): Ctx => { const getTypeValue = (ty: Type | undefined): any => { try { return JSON.parse(typeToString(ty)) - } catch(_) { + } catch (_) { return null } } - const refMap: Map<string, string> = new Map + const refMap: Map<string, string> = new Map() const createRef = (ty: string): string => { const key = uuid() refMap.set(key, ty) @@ -83,7 +83,9 @@ export const createContext = (options: CtxOptions): Ctx => { typeToString, getTypeValue, - get currentEnv() { return currentEnv }, + get currentEnv() { + return currentEnv + }, setEnv, createRef, diff --git a/src/eval-env/builtins.ts b/src/eval-env/builtins.ts index f9c4ce8..7e00253 100644 --- a/src/eval-env/builtins.ts +++ b/src/eval-env/builtins.ts @@ -1,143 +1,145 @@ import { Type } from 'ts-morph' -import { Ctx } from "../types" +import { Ctx } from '../types' import { evalList } from '../util' export default (ctx: Ctx, args: Type[]) => ({ - SetEvalEnvironment: async () => { - ctx.setEnv(ctx.getTypeValue(args[0])) - return [] - }, + SetEvalEnvironment: async () => { + ctx.setEnv(ctx.getTypeValue(args[0])) + return [] + }, - DefineEffect: async () => { - const [nameTyp, exprTyp] = args - const name = nameTyp?.getLiteralValue() as string - const exprStr = exprTyp?.getLiteralValue() as string + DefineEffect: async () => { + const [nameTyp, exprTyp] = args + const name = nameTyp?.getLiteralValue() as string + const exprStr = exprTyp?.getLiteralValue() as string - ctx.addCustomEffect(name, exprStr) - return [] - }, + ctx.addCustomEffect(name, exprStr) + return [] + }, - CreateRef: async () => { - const val = ctx.typeToString(args[0]) - const refKey = ctx.createRef(val) - const [resultKey, _] = ctx.createResult(JSON.stringify(refKey)) - return [resultKey] - }, + CreateRef: async () => { + const val = ctx.typeToString(args[0]) + const refKey = ctx.createRef(val) + const [resultKey, _] = ctx.createResult(JSON.stringify(refKey)) + return [resultKey] + }, - GetRef: async () => { - const refKey = ctx.getTypeValue(args[0]) - const val = ctx.getRef(refKey) - if (!val) throw new Error('Ref has been deleted') - const [resultKey, _] = ctx.createResult(val) - return [resultKey] - }, + GetRef: async () => { + const refKey = ctx.getTypeValue(args[0]) + const val = ctx.getRef(refKey) + if (!val) throw new Error('Ref has been deleted') + const [resultKey, _] = ctx.createResult(val) + return [resultKey] + }, - SetRef: async () => { - const [ keyTy, valTyp ] = args - ctx.setRef(ctx.getTypeValue(keyTy), ctx.typeToString(valTyp)) - return [] - }, + SetRef: async () => { + const [keyTy, valTyp] = args + ctx.setRef(ctx.getTypeValue(keyTy), ctx.typeToString(valTyp)) + return [] + }, - DeleteRef: async () => { - ctx.deleteRef(ctx.getTypeValue(args[0])) - return [] - }, + DeleteRef: async () => { + ctx.deleteRef(ctx.getTypeValue(args[0])) + return [] + }, - Pure: async () => { - const [valTyp] = args - const [resultKey, _] = ctx.createResult(ctx.typeToString(valTyp)) - return [resultKey] - }, + Pure: async () => { + const [valTyp] = args + const [resultKey, _] = ctx.createResult(ctx.typeToString(valTyp)) + return [resultKey] + }, - Print: async () => { - console.log(...args.map(ctx.typeToString)) - return [] - }, + Print: async () => { + console.log(...args.map(ctx.typeToString)) + return [] + }, - PutString: async () => { - const [strinTyp] = args - const typString = ctx.getTypeValue(strinTyp) ?? ctx.typeToString(strinTyp) - process.stdout.write(typString) - return [] - }, + PutString: async () => { + const [strinTyp] = args + const typString = ctx.getTypeValue(strinTyp) ?? ctx.typeToString(strinTyp) + process.stdout.write(typString) + return [] + }, - Debug: async () => { - const [labelTyp, valueTyp] = args - const label = ctx.getTypeValue(labelTyp) - const value = ctx.typeToString(valueTyp) - console.log(label, value) - const [resultKey, _] = ctx.createResult(JSON.stringify(value)) - return [resultKey] - }, + Debug: async () => { + const [labelTyp, valueTyp] = args + const label = ctx.getTypeValue(labelTyp) + const value = ctx.typeToString(valueTyp) + console.log(label, value) + const [resultKey, _] = ctx.createResult(JSON.stringify(value)) + return [resultKey] + }, - Bind: async () => { - const [inputTyp, chainToKind] = args - const [resultKey] = inputTyp ? await ctx.evaluateType(ctx, inputTyp) : [] + Bind: async () => { + const [inputTyp, chainToKind] = args + const [resultKey] = inputTyp ? await ctx.evaluateType(ctx, inputTyp) : [] - // TODO: Handle resultKey undefined case - const [_, compNode] = ctx.createResult( - `(${ctx.typeToString(chainToKind)} & { input: (${ctx.getResultExpr( - resultKey - )})['output'] })['return']` - ) - // TODO: Avoid using getTypeAtLocation? - const compTyp = compNode - ?.getType() - .getProperty('output') - ?.getTypeAtLocation(ctx.entryPoint) + // TODO: Handle resultKey undefined case + const [_, compNode] = ctx.createResult( + `(${ctx.typeToString(chainToKind)} & { input: (${ctx.getResultExpr( + resultKey + )})['output'] })['return']` + ) + // TODO: Avoid using getTypeAtLocation? + const compTyp = compNode + ?.getType() + .getProperty('output') + ?.getTypeAtLocation(ctx.entryPoint) - return compTyp ? await ctx.evaluateType(ctx, compTyp) : [] - }, + return compTyp ? await ctx.evaluateType(ctx, compTyp) : [] + }, - Try: async () => { - const [effTyp, catchK] = args + Try: async () => { + const [effTyp, catchK] = args - try { - if (!effTyp) throw new Error('wow') - return await ctx.evaluateType(ctx, effTyp) - } catch(e) { - const error = JSON.stringify((e as any)?.message ?? e) - const catchResExpr = `(${ctx.typeToString(catchK)} & { input: ${error} })['return']` - const [resultKey, _] = ctx.createResult(catchResExpr) - return [resultKey] - } - }, + try { + if (!effTyp) throw new Error('wow') + return await ctx.evaluateType(ctx, effTyp) + } catch (e) { + const error = JSON.stringify((e as any)?.message ?? e) + const catchResExpr = `(${ctx.typeToString( + catchK + )} & { input: ${error} })['return']` + const [resultKey, _] = ctx.createResult(catchResExpr) + return [resultKey] + } + }, - Throw: async () => { - throw args[0] && ctx.getTypeValue(args[0]) - }, + Throw: async () => { + throw args[0] && ctx.getTypeValue(args[0]) + }, - JsExpr: async () => { - const [exprTyp] = args - const exprStr = ctx.getTypeValue(exprTyp) - const result = eval(`JSON.stringify(${exprStr})`) - const [resultKey, _] = ctx.createResult(`${result}`) - return [resultKey] - }, + JsExpr: async () => { + const [exprTyp] = args + const exprStr = ctx.getTypeValue(exprTyp) + const result = eval(`JSON.stringify(${exprStr})`) + const [resultKey, _] = ctx.createResult(`${result}`) + return [resultKey] + }, - Seq: async () => { - const [effectTyps] = args - const effectResults = await evalList( - ctx, - effectTyps?.getTupleElements() ?? [] - ) - const [resultKey, _] = ctx.createResult(`[ + Seq: async () => { + const [effectTyps] = args + const effectResults = await evalList( + ctx, + effectTyps?.getTupleElements() ?? [] + ) + const [resultKey, _] = ctx.createResult(`[ ${effectResults.map(ctx.getResultExpr).join(', ')} ]`) - return [resultKey] - }, + return [resultKey] + }, - Do: async () => { - const [effectTyps] = args - const effectResults = await evalList( - ctx, - effectTyps?.getTupleElements() ?? [] - ) - // TODO: Use last type's result instead of last result key - const lastResKey = effectResults[effectResults.length - 1] - const [resultKey, _] = ctx.createResult( - `(${ctx.getResultExpr(lastResKey)})['output']` - ) - return [resultKey] - }, + Do: async () => { + const [effectTyps] = args + const effectResults = await evalList( + ctx, + effectTyps?.getTupleElements() ?? [] + ) + // TODO: Use last type's result instead of last result key + const lastResKey = effectResults[effectResults.length - 1] + const [resultKey, _] = ctx.createResult( + `(${ctx.getResultExpr(lastResKey)})['output']` + ) + return [resultKey] + }, }) diff --git a/src/eval-env/test.ts b/src/eval-env/test.ts index eddf366..84ae138 100644 --- a/src/eval-env/test.ts +++ b/src/eval-env/test.ts @@ -12,7 +12,7 @@ export default (ctx: Ctx, args: Type[]) => ({ } console.log('[✓]') - } catch(e) { + } catch (e) { console.log('[TEST FAILED]') throw e } diff --git a/src/eval.ts b/src/eval.ts index 2b93e49..d7055a3 100644 --- a/src/eval.ts +++ b/src/eval.ts @@ -5,8 +5,8 @@ import { Ctx } from './types' import * as builtins from './eval-env/builtins' type EffDefn = { - default: (ctx: Ctx, args: Type[]) => Record<string, () => Promise<string[]>>, - cleanup?: () => void, + default: (ctx: Ctx, args: Type[]) => Record<string, () => Promise<string[]>> + cleanup?: () => void } const mergeEffDefns = (a: EffDefn, b: EffDefn): EffDefn => ({ default: (ctx: Ctx, args: Type[]) => ({ @@ -20,7 +20,7 @@ const mergeEffDefns = (a: EffDefn, b: EffDefn): EffDefn => ({ }) const cleanupActions = new Set<undefined | (() => void)>() -export const cleanup = () => cleanupActions.forEach(f => f?.()) +export const cleanup = () => cleanupActions.forEach((f) => f?.()) let prevEnv: string @@ -37,16 +37,20 @@ export const evaluateType = async ( const envDefns = await match(ctx.currentEnv, { node: () => import('./eval-env/node') as Promise<EffDefn>, - 'test.node': async () => mergeEffDefns( - await import('./eval-env/test'), - await import('./eval-env/node'), - ), + 'test.node': async () => + mergeEffDefns( + await import('./eval-env/test'), + await import('./eval-env/node') + ), _: async () => { throw new Error(`Invalid env: ${ctx.currentEnv}`) }, }) - const { default: envEffects, cleanup } = mergeEffDefns(builtins as unknown as EffDefn, envDefns) + const { default: envEffects, cleanup } = mergeEffDefns( + builtins as unknown as EffDefn, + envDefns + ) // Update cleanup if env has changed if (prevEnv !== ctx.currentEnv) { diff --git a/src/index.ts b/src/index.ts index a144c57..f6d46d6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,7 +6,9 @@ import { evalList } from './util' const main = () => { program .name('ts-types-lang') - .description(`A runtime for typescript's type system that turns it into a general purpose, purely functional programming language!`) + .description( + `A runtime for typescript's type system that turns it into a general purpose, purely functional programming language!` + ) program .command('run') @@ -24,5 +26,4 @@ const main = () => { return program.parseAsync() } -main() - .finally(() => cleanup()) +main().finally(() => cleanup()) diff --git a/src/types.ts b/src/types.ts index d9e874e..c0258db 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,13 +17,13 @@ export interface Ctx { getResultExpr: (key?: string) => string printResultNode: () => void - currentEnv: string, - setEnv: (e: string) => void, + currentEnv: string + setEnv: (e: string) => void - createRef: (ty: string) => string, - getRef: (key: string) => any, - setRef: (key: string, ty: string) => void, - deleteRef: (key: string) => void, + createRef: (ty: string) => string + getRef: (key: string) => any + setRef: (key: string, ty: string) => void + deleteRef: (key: string) => void addCustomEffect: (name: string, expr: string) => void runCustomEffect: (name: string, args: Type[]) => Promise<string[]> diff --git a/src/util.ts b/src/util.ts index 13bdb35..f7bb20a 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,5 +1,5 @@ -import { Type } from "ts-morph" -import { Ctx } from "./types" +import { Type } from 'ts-morph' +import { Ctx } from './types' export const match = <K extends string, R>( k: K | undefined, |
