aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/custom-effect.ts10
-rw-r--r--examples/ffi.ts12
-rw-r--r--examples/file.ts9
-rw-r--r--examples/greeting.ts14
-rw-r--r--examples/guess-number.ts15
-rw-r--r--src/index.ts45
-rw-r--r--src/runtime.ts31
-rw-r--r--src/stdlib/stdio.ts2
-rw-r--r--src/util.ts4
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._()
+