aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--examples/guess-number.ts36
-rw-r--r--src/runtime.ts23
-rw-r--r--src/stdlib/io.ts2
3 files changed, 47 insertions, 14 deletions
diff --git a/examples/guess-number.ts b/examples/guess-number.ts
index aca3915..8f5d535 100644
--- a/examples/guess-number.ts
+++ b/examples/guess-number.ts
@@ -1,15 +1,33 @@
-import { Print, PutString, Bind, Kind1, JsExpr, ReadLine, Seq } from '../src/stdlib'
+import { Print, PutString, Bind, Kind1, JsExpr, ReadLine, Then, PutStringLn } from '../src/stdlib'
-export type main = Bind<
- JsExpr<"Math.floor(Math.random() * 10)">,
- StartGuessing
->
+export type main = [
+ PutStringLn<"You have 5 guesses">,
+ 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 AskForGuess<N extends number, Attempts extends 0[]> extends Kind1<string> {
+ return: `${this['input']}` extends `${N}`
+ ? PutStringLn<"Yay! You got it right!">
+ : Then<[
+ Print<`Wrong guess. Total attempts: ${
+ [...Attempts, 0] extends infer Ls extends 0[] ? Ls['length'] : 0
+ }`>,
+ (StartGuessing<[...Attempts, 0]> & { input: N })['return'],
+ ]>
}
-interface StartGuessing extends Kind1<number> {
- return: Bind<Seq<[PutString<"Your guess? ">, ReadLine]>, AskForGuess<this['input']>>
+interface StartGuessing<Attempts extends 0[] = []> extends Kind1<number> {
+ return: Attempts['length'] extends 5
+ ? PutStringLn<"Max attempts exceeded. Game over!">
+ : Bind<
+ Then<[
+ PutString<"Your guess? ">,
+ ReadLine
+ ]>,
+ AskForGuess<this['input'], Attempts>
+ >
}
diff --git a/src/runtime.ts b/src/runtime.ts
index f2fc516..91393be 100644
--- a/src/runtime.ts
+++ b/src/runtime.ts
@@ -150,11 +150,7 @@ const evaluateType = async (effTyp: Type, node: Node): Promise<string[]> => {
Seq: async () => {
const [effectTyps] = effTyp.getTypeArguments()
- const effectResults: string[] = []
- for (const item of effectTyps?.getTupleElements() ?? []) {
- effectResults.push(...(await evaluateType(item, node)))
- }
-
+ const effectResults = await evalList(effectTyps?.getTupleElements() ?? [], node)
const hash = uuid()
addResult(hash, `[
${effectResults.map(r => `${RESULT_TYPE_NAME}[${JSON.stringify(r)}]`).join(', ')}
@@ -162,6 +158,15 @@ const evaluateType = async (effTyp: Type, node: Node): Promise<string[]> => {
return [hash]
},
+ Then: async () => {
+ const [effectTyps] = effTyp.getTypeArguments()
+ const effectResults = await evalList(effectTyps?.getTupleElements() ?? [], node)
+ const resultKey = effectResults[effectResults.length - 1]
+ const hash = uuid()
+ addResult(hash, `${RESULT_TYPE_NAME}[${JSON.stringify(resultKey)}]['output']`)
+ return [hash]
+ },
+
_: async () => {
if (name && customEffects[name]) {
customEffects[name](...effTyp.getTypeArguments())
@@ -173,6 +178,14 @@ const evaluateType = async (effTyp: Type, node: Node): Promise<string[]> => {
})
}
+const evalList = async (effectTyps: Type[], node: Node) => {
+ const effectResults: string[] = []
+ for (const item of effectTyps ?? []) {
+ effectResults.push(...(await evaluateType(item, node)))
+ }
+ return effectResults
+}
+
const main = async () => {
if (typeRefNode) {
const resultType = entryPoint?.getType()
diff --git a/src/stdlib/io.ts b/src/stdlib/io.ts
index d8e3ed2..d256628 100644
--- a/src/stdlib/io.ts
+++ b/src/stdlib/io.ts
@@ -9,5 +9,7 @@ export interface Bind<_Eff extends Effect, _Fn extends Kind1> extends Effect { }
export interface Seq<_Effs extends Effect[]> extends Effect { }
+export interface Then<_Effs extends Effect[]> extends Effect { }
+
export interface DefineEffect<_Name extends string, _Func extends string> extends Effect { }