aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2023-01-06 19:46:10 +0530
committerAkshay Nair <phenax5@gmail.com>2023-01-06 19:46:10 +0530
commitd0baefe81d90d44f61322716e20850a7f6f5eaa5 (patch)
treefa46e265f7e8fd7e4afa5d36eb00233ffcace6cc /src
parente319818b8cc27450237f4b6b96022458ae478ab2 (diff)
downloadts-types-lang-d0baefe81d90d44f61322716e20850a7f6f5eaa5.tar.gz
ts-types-lang-d0baefe81d90d44f61322716e20850a7f6f5eaa5.zip
feat: adds seq and refactors runtime
Diffstat (limited to 'src')
-rw-r--r--src/index.ts25
-rw-r--r--src/runtime.ts128
-rw-r--r--src/stdlib/io.ts4
3 files changed, 90 insertions, 67 deletions
diff --git a/src/index.ts b/src/index.ts
index 7ee4461..df2643a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,17 +1,38 @@
-import { Program, Print, PutString, Bind, Debug, Kind1, GetEnv, JsExpr, ReadFile, GetArgs, ReadLine } from './stdlib'
+import { Program, Print, PutString, Bind, Debug, Kind1, GetEnv, JsExpr, ReadFile, GetArgs, ReadLine, Seq } 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']>>
+}
+
export type main = Program<[
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>,
- // ChainIO<ReadLine, WithInputK>,
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 dae492c..164e66e 100644
--- a/src/runtime.ts
+++ b/src/runtime.ts
@@ -43,11 +43,11 @@ const RESULT_TYPE_NAME = '__$result'
const [resultTypeNode] = sourceFile.addStatements(`type ${RESULT_TYPE_NAME} = {}`)
-const addResult = (name: string, ty: string) => {
+const addResult = (name: string, ty: string): Node | undefined => {
if (resultTypeNode.isKind(SyntaxKind.TypeAliasDeclaration)) {
const value = resultTypeNode.getChildAtIndex(3)
if (value.isKind(SyntaxKind.TypeLiteral)) {
- value.addProperty({
+ return value.addProperty({
name: JSON.stringify(name),
type: `{ output: ${ty} }`,
})
@@ -62,6 +62,28 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> =>
const name = effTyp.getSymbol()?.getName()
return match(name, {
+ Print: async () => {
+ console.log(...effTyp.getTypeArguments().map(typeToString));
+ return []
+ },
+
+ PutString: async () => {
+ const [strinTyp] = effTyp.getTypeArguments()
+ const typString = typeToString(strinTyp)
+ const string = JSON.parse(!typString.startsWith('"') ? `"${typString}"` : typString)
+ stdout.write(string);
+ return []
+ },
+
+ Debug: async () => {
+ const [labelTyp, valueTyp] = effTyp.getTypeArguments()
+ const label = JSON.parse(typeToString(labelTyp))
+ const value = typeToString(valueTyp)
+ console.log(label, value)
+ // TODO: Return value
+ return []
+ },
+
ReadFile: async () => {
const [pathTyp] = effTyp.getTypeArguments()
const filePath = JSON.parse(typeToString(pathTyp))
@@ -71,10 +93,26 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> =>
return [hash]
},
+ WriteFile: async () => {
+ const [pathTyp, contentsTyp] = effTyp.getTypeArguments()
+ const filePath = JSON.parse(typeToString(pathTyp))
+ const contents = JSON.parse(typeToString(contentsTyp))
+ await fs.writeFile(filePath, contents)
+ return []
+ },
+
Bind: async () => {
- const inputTyp = effTyp.getProperty('input')?.getTypeAtLocation(node)
- const inputResults = inputTyp && await accumulateResults(inputTyp, node)
- return inputResults ?? []
+ const [inputTyp, chainToKind] = effTyp.getTypeArguments()
+ const [resultKey] = inputTyp ? await accumulateResults(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 []
},
GetEnv: async () => {
@@ -107,6 +145,20 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> =>
return [hash]
},
+ Seq: async () => {
+ const [effectTyps] = effTyp.getTypeArguments()
+ const effectResults: string[] = []
+ for (const item of effectTyps?.getTupleElements() ?? []) {
+ effectResults.push(...(await accumulateResults(item, node)))
+ }
+
+ const hash = uuid()
+ addResult(hash, `[
+ ${effectResults.map(r => `${RESULT_TYPE_NAME}[${JSON.stringify(r)}]`).join(', ')}
+ ]`)
+ return [hash]
+ },
+
_: async () => {
console.log(`${name} result effect is unhandled`)
return []
@@ -114,58 +166,10 @@ const accumulateResults = async (effTyp: Type, node: Node): Promise<string[]> =>
})
}
-const evalAccumulator = async (effNode: Node, node: Node) => {
- const effTyp = effNode.getType()
- const name = effTyp.getSymbol()?.getName()
-
- return match(name, {
- Print: async () => {
- console.log(...effTyp.getTypeArguments().map(typeToString));
- },
-
- PutString: async () => {
- const [strinTyp] = effTyp.getTypeArguments()
- const typString = typeToString(strinTyp)
- const string = JSON.parse(!typString.startsWith('"') ? `"${typString}"` : typString)
- stdout.write(string);
- },
-
- Debug: async () => {
- const [labelTyp, valueTyp] = effTyp.getTypeArguments()
- const label = JSON.parse(typeToString(labelTyp))
- const value = typeToString(valueTyp)
- console.log(label, value)
- },
-
- ReadFile: async () => {
- const [hash] = await accumulateResults(effTyp, node)
- effNode.replaceWithText(`${RESULT_TYPE_NAME}[${JSON.stringify(hash)}]`)
- },
-
- WriteFile: async () => {
- const [pathTyp, contentsTyp] = effTyp.getTypeArguments()
- const filePath = JSON.parse(typeToString(pathTyp))
- const contents = JSON.parse(typeToString(contentsTyp))
- await fs.writeFile(filePath, contents)
- },
-
- Bind: async () => {
- const chainToKind = effTyp.getProperty('chainTo')?.getTypeAtLocation(node)
- const [hashRes] = await accumulateResults(effTyp, node)
- const chainRes = `(${typeToString(chainToKind)} & { input: ${RESULT_TYPE_NAME}[${JSON.stringify(hashRes)}]['output'] })['return']`
- const updateEffNode = effNode.replaceWithText(chainRes)
- await evalAccumulator(updateEffNode, node)
- },
-
- ReplacePlaceholders: async () => { },
-
- _: async () => {
- console.log(effNode.print())
- console.log('TTTT', typeToString(effTyp))
- console.log(`${name} effect is unhandled`)
- }
- })
-}
+// const evalAccumulator = async (effNode: Node, node: Node) => {
+// const effTyp = effNode.getType()
+// await accumulateResults(effTyp, node)
+// }
const main = async () => {
if (typeRefNode) {
@@ -175,14 +179,8 @@ const main = async () => {
const exitCodeTy = getPropertyType(typeRefNode, 'exitCode')
const effectTypes = getPropertyType(typeRefNode, 'effects')
if (effectTypes?.isTuple()) {
- const effectNodes = entryPoint.getChildrenOfKind(SyntaxKind.TypeReference)
- .flatMap(n => n.getChildrenOfKind(SyntaxKind.TupleType))
- .flatMap(tt => tt.getChildrenOfKind(SyntaxKind.SyntaxList))
- .flatMap(n => n.getChildren())
- .filter(n => !n.isKind(SyntaxKind.CommaToken))
-
- for (const n of effectNodes) {
- await evalAccumulator(n, typeRefNode)
+ for (const typ of effectTypes.getTupleElements()) {
+ await accumulateResults(typ, typeRefNode)
}
}
diff --git a/src/stdlib/io.ts b/src/stdlib/io.ts
index 00b74b1..c1e4574 100644
--- a/src/stdlib/io.ts
+++ b/src/stdlib/io.ts
@@ -16,3 +16,7 @@ export interface Bind<Eff extends EffectAtom, Fn extends Kind1> extends EffectAt
chainTo: Fn
}
+export interface Seq<Effs extends EffectAtom[]> extends EffectAtom {
+ effects: Effs
+}
+