From 4d82623f191042c362ddd2ad5e8ded99d5854169 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 6 Jan 2023 21:12:53 +0530 Subject: feat: adds then effect + fixes guess number example --- examples/guess-number.ts | 36 +++++++++++++++++++++++++++--------- src/runtime.ts | 23 ++++++++++++++++++----- src/stdlib/io.ts | 2 ++ 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 extends Kind1 { - return: this['input'] extends `${N}` ? Print<"Yaya"> : Print<"naaah"> +interface AskForGuess extends Kind1 { + 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 { - return: Bind, ReadLine]>, AskForGuess> +interface StartGuessing extends Kind1 { + return: Attempts['length'] extends 5 + ? PutStringLn<"Max attempts exceeded. Game over!"> + : Bind< + Then<[ + PutString<"Your guess? ">, + ReadLine + ]>, + AskForGuess + > } 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 => { 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 => { 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 => { }) } +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 { } -- cgit v1.3.1