diff options
| -rw-r--r-- | examples/custom-effect.ts | 10 | ||||
| -rw-r--r-- | examples/ffi.ts | 12 | ||||
| -rw-r--r-- | examples/file.ts | 9 | ||||
| -rw-r--r-- | examples/greeting.ts | 14 | ||||
| -rw-r--r-- | examples/guess-number.ts | 15 | ||||
| -rw-r--r-- | src/index.ts | 45 | ||||
| -rw-r--r-- | src/runtime.ts | 31 | ||||
| -rw-r--r-- | src/stdlib/stdio.ts | 2 | ||||
| -rw-r--r-- | src/util.ts | 4 |
9 files changed, 77 insertions, 65 deletions
diff --git a/examples/custom-effect.ts b/examples/custom-effect.ts new file mode 100644 index 0000000..948caf4 --- /dev/null +++ b/examples/custom-effect.ts @@ -0,0 +1,10 @@ +import { DefineEffect, Effect } from '../src/stdlib' + +interface Wow<_A, _B> extends Effect { } + +export type main = [ + DefineEffect<"Wow", `(a, b) => { + console.log(typeToString(a), '-->', typeToString(b)) + }`>, + Wow<"a", 69>, +] diff --git a/examples/ffi.ts b/examples/ffi.ts new file mode 100644 index 0000000..7a73a0a --- /dev/null +++ b/examples/ffi.ts @@ -0,0 +1,12 @@ +import { Bind, Debug, JsExpr, Kind1 } from "../src/stdlib" + +interface PrintK<Label extends string = ""> extends Kind1 { + return: Debug<Label, this['input']> +} + +type Square<N extends number> = JsExpr<`${N} ** 2`> + +export type main = [ + Bind<JsExpr<"{ boobaa: [5 * 3, 5 * 2] }">, PrintK<'|'>>, + Bind<Square<69>, PrintK<"69^2 =">>, +] diff --git a/examples/file.ts b/examples/file.ts new file mode 100644 index 0000000..3de26d3 --- /dev/null +++ b/examples/file.ts @@ -0,0 +1,9 @@ +import { Bind, Kind1, ReadFile, PutStringLn } from '../src/stdlib' + +interface PrintK extends Kind1<string> { + return: PutStringLn<this['input']> +} + +export type main = [ + Bind<ReadFile<"./default.nix">, PrintK>, +] diff --git a/examples/greeting.ts b/examples/greeting.ts new file mode 100644 index 0000000..5e1a164 --- /dev/null +++ b/examples/greeting.ts @@ -0,0 +1,14 @@ +import { PutString, Bind, Kind1, ReadLine, Seq } from '../src/stdlib' + +interface GreetK extends Kind1<string> { + return: Seq<[ + PutString<"Hello, ">, + PutString<`${this['input']}\n`> + ]>, +} + +export type main = [ + PutString<"Your name? ">, + Bind<ReadLine, GreetK>, +] + diff --git a/examples/guess-number.ts b/examples/guess-number.ts new file mode 100644 index 0000000..aca3915 --- /dev/null +++ b/examples/guess-number.ts @@ -0,0 +1,15 @@ +import { Print, PutString, Bind, Kind1, JsExpr, ReadLine, Seq } from '../src/stdlib' + +export type main = Bind< + JsExpr<"Math.floor(Math.random() * 10)">, + StartGuessing +> + +interface AskForGuess<N extends number> extends Kind1<string> { + return: this['input'] extends `${N}` ? Print<"Yaya"> : Print<"naaah"> +} + +interface StartGuessing extends Kind1<number> { + return: Bind<Seq<[PutString<"Your guess? ">, ReadLine]>, AskForGuess<this['input']>> +} + diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index e764623..0000000 --- a/src/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Print, PutString, Bind, Debug, Kind1, GetEnv, JsExpr, ReadFile, GetArgs, ReadLine, Seq, Effect, DefineEffect } from './stdlib' - -interface PrintK<Label extends string = ""> extends Kind1<unknown> { - return: Debug<Label, this['input']> -} - -interface AskForGuess<N extends number> extends Kind1<string> { - return: this['input'] extends `${N}` ? Print<"Yaya"> : Print<"naaah"> -} - -interface StartGuessing extends Kind1<number> { - return: Bind<Seq<[PutString<"Your guess? ">, ReadLine]>, AskForGuess<this['input']>> -} - -interface Wow<_A, _B> extends Effect { } - -export type main = [ - DefineEffect<"Wow", `(a, b) => { - console.log(typeToString(a), '-->', typeToString(b)) - }`>, - Wow<"a", 69>, - - Bind<GetArgs, PrintK>, - PutString<"1,2,3? ">, - [1, 2, 3] extends infer Res ? Print<Res> : never, - Bind<GetEnv<"NODE_ENV">, PrintK>, - Bind<JsExpr<"{ boobaa: [5 * 3, 5 * 2] }">, PrintK>, - Bind<ReadFile<"./default.nix">, PrintK>, - - PutString<"Your name? ">, - Bind<ReadLine, PrintK<"Hello,">>, - - Bind< - JsExpr<"Math.floor(Math.random() * 10)">, - StartGuessing - >, - - Print<"Before times">, - Seq<[ - Print<"Hey">, - Print<"Wow">, - Bind<JsExpr<"200 * 2">, PrintK<"200 * 2 =">>, - ]>, -] - diff --git a/src/runtime.ts b/src/runtime.ts index bac9415..f2fc516 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -2,8 +2,8 @@ import { Project, ScriptTarget, Type, Node, StringLiteral, TypeFormatFlags, Synt import path from 'path' import { promises as fs } from 'fs' import readline from 'readline'; -import { stdout } from 'process'; import { v4 as uuid } from 'uuid'; +import { match } from './util'; const rl = readline.createInterface({ input: process.stdin, @@ -23,20 +23,15 @@ const project = new Project({ const typeChecker = project.getTypeChecker() -const sourceFile = project.addSourceFileAtPath(path.resolve("./src/index.ts")) +const [filePath] = process.argv.slice(2) + +const sourceFile = project.addSourceFileAtPath(path.resolve(filePath)) const entryPoint = sourceFile.getExportedDeclarations().get('main')?.[0] const typeToString = (ty: Type | undefined): string => ty ? typeChecker.compilerObject.typeToString(ty.compilerType) : '' -const getPropertyType = (n: Node, prop: string): Type | undefined => { - const tt = typeChecker.getTypeAtLocation(n) - const propSym = tt.getProperty(prop) - const ty = propSym && typeChecker.getTypeOfSymbolAtLocation(propSym, n) - return ty -} - const typeRefNode = entryPoint?.getLastChild() const RESULT_TYPE_NAME = '__$result' @@ -55,13 +50,11 @@ const addResult = (name: string, ty: string): Node | undefined => { } } -const match = <K extends string, R>(k: K | undefined, pattern: { [key in K | '_']: () => R }) => - k && pattern[k] ? pattern[k]() : pattern._() - const customEffects: Record<string, (...args: Type[]) => void> = {} -const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> => { +const evaluateType = async (effTyp: Type, node: Node): Promise<string[]> => { const name = effTyp.getSymbol()?.getName() + // console.log(name) return match(name, { DefineEffect: async () => { @@ -83,7 +76,7 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> => const [strinTyp] = effTyp.getTypeArguments() const typString = typeToString(strinTyp) const string = JSON.parse(!typString.startsWith('"') ? `"${typString}"` : typString) - stdout.write(string); + process.stdout.write(string); return [] }, @@ -115,16 +108,14 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> => Bind: async () => { const [inputTyp, chainToKind] = effTyp.getTypeArguments() - const [resultKey] = inputTyp ? await accumulateResults(inputTyp, node) : [] + const [resultKey] = inputTyp ? await evaluateType(inputTyp, node) : [] const hash = uuid() const compNode = addResult(hash, `(${typeToString(chainToKind)} & { input: ${RESULT_TYPE_NAME}[${JSON.stringify(resultKey)}]['output'] })['return']`) const compTyp = compNode?.getType().getProperty('output')?.getTypeAtLocation(node) - if (compTyp) - return accumulateResults(compTyp, node) - return [] + return compTyp ? await evaluateType(compTyp, node) : [] }, GetEnv: async () => { @@ -161,7 +152,7 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> => const [effectTyps] = effTyp.getTypeArguments() const effectResults: string[] = [] for (const item of effectTyps?.getTupleElements() ?? []) { - effectResults.push(...(await accumulateResults(item, node))) + effectResults.push(...(await evaluateType(item, node))) } const hash = uuid() @@ -189,7 +180,7 @@ const main = async () => { if (resultType) { const effects = resultType.isTuple() ? resultType.getTupleElements() : [resultType] for (const typ of effects) { - await accumulateResults(typ, typeRefNode) + await evaluateType(typ, typeRefNode) } } } diff --git a/src/stdlib/stdio.ts b/src/stdlib/stdio.ts index b20d2da..365aead 100644 --- a/src/stdlib/stdio.ts +++ b/src/stdlib/stdio.ts @@ -8,3 +8,5 @@ export interface Debug<_ extends string, T> extends Effect<T> { } export interface ReadLine extends Effect<string> { } +export type PutStringLn<S extends string> = PutString<`${S}\n`> + diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..0b60bb1 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,4 @@ + +export const match = <K extends string, R>(k: K | undefined, pattern: { [key in K | '_']: () => R }) => + k && pattern[k] ? pattern[k]() : pattern._() + |
