aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/greeting.ts15
-rw-r--r--src/eval-env/builtins.ts66
-rw-r--r--stdlib/effect.ts6
3 files changed, 71 insertions, 16 deletions
diff --git a/examples/greeting.ts b/examples/greeting.ts
index d3d755f..8ed2181 100644
--- a/examples/greeting.ts
+++ b/examples/greeting.ts
@@ -1,12 +1,21 @@
import { Bind, Kind1 } from '../stdlib/effect'
import { PutString, ReadLine, PutStringLn } from '../stdlib/stdio'
-interface GreetK extends Kind1<string> {
- return: PutStringLn<`Hello, ${this['input']}`>
+interface ResponseK extends Kind1<string> {
+ return: PutStringLn<`Interesting that you believe "${this['input']}" is your purpose. Hmmmm...`>
}
export type main = [
PutStringLn<'Greetotron 6000 initializing...'>,
+
+ PutStringLn<'----------------'>,
PutString<'Your name? '>,
- Bind<ReadLine, GreetK>
+ Bind<ReadLine, <name extends string>() =>
+ PutStringLn<`Hello, ${name}`>>,
+
+ PutStringLn<'----------------'>,
+ PutString<'Your purpose in life? '>,
+ Bind<ReadLine, ResponseK>,
+
+ PutStringLn<'----------------'>,
]
diff --git a/src/eval-env/builtins.ts b/src/eval-env/builtins.ts
index 7e00253..f67fcc6 100644
--- a/src/eval-env/builtins.ts
+++ b/src/eval-env/builtins.ts
@@ -1,7 +1,55 @@
-import { Type } from 'ts-morph'
+import { SyntaxKind, Type } from 'ts-morph'
import { Ctx } from '../types'
import { evalList } from '../util'
+const applyFunc = (ctx: Ctx, fn: Type | undefined, val: string): Type => {
+ const resultType = (() => {
+ const baseTypes = fn?.getBaseTypes().flatMap(t => t.getSymbol()?.getName())
+
+ if (baseTypes?.includes('Kind1')) {
+ const [_, resultNode] = ctx.createResult(
+ `(${ctx.typeToString(fn)} & { input: ${val} })['return']`
+ )
+ return resultNode
+ ?.getType()
+ .getProperty('output')
+ ?.getTypeAtLocation(resultNode)
+ } else {
+ const [_key, resultNode] = ctx.createResult(`ReturnType<${ctx.typeToString(fn)}>`)
+
+ const resValueNode = resultNode
+ ?.asKind(SyntaxKind.PropertySignature)
+ ?.getChildAtIndexIfKind(2, SyntaxKind.TypeLiteral)
+ ?.getProperty('output')
+ ?.getChildAtIndexIfKind(2, SyntaxKind.TypeReference)
+
+ const functionNode = resValueNode
+ ?.getChildAtIndexIfKind(1, SyntaxKind.SyntaxList)
+ ?.getFirstChildIfKind(SyntaxKind.FunctionType)
+
+ if (functionNode) {
+ const typeParameters = functionNode.getTypeParameters() ?? []
+
+ if (typeParameters.length > 0) {
+ typeParameters[0]?.getConstraint()?.replaceWithText(val)
+ }
+
+ return resValueNode?.getType()
+ }
+ }
+
+ return undefined
+ })()
+
+ // TODO: Cleanup unwanted result node values
+
+ if (!resultType) {
+ throw new Error('Fuck shit')
+ }
+
+ return resultType
+}
+
export default (ctx: Ctx, args: Type[]) => ({
SetEvalEnvironment: async () => {
ctx.setEnv(ctx.getTypeValue(args[0]))
@@ -75,18 +123,12 @@ export default (ctx: Ctx, args: Type[]) => ({
const [resultKey] = inputTyp ? await ctx.evaluateType(ctx, inputTyp) : []
// TODO: Handle resultKey undefined case
- const [_, compNode] = ctx.createResult(
- `(${ctx.typeToString(chainToKind)} & { input: (${ctx.getResultExpr(
- resultKey
- )})['output'] })['return']`
- )
- // TODO: Avoid using getTypeAtLocation?
- const compTyp = compNode
- ?.getType()
- .getProperty('output')
- ?.getTypeAtLocation(ctx.entryPoint)
- return compTyp ? await ctx.evaluateType(ctx, compTyp) : []
+ const resultType =
+ applyFunc(ctx, chainToKind, `(${ctx.getResultExpr(resultKey)})['output']`)
+ const res = await ctx.evaluateType(ctx, resultType)
+
+ return res
},
Try: async () => {
diff --git a/stdlib/effect.ts b/stdlib/effect.ts
index 5ae9cd9..0662d00 100644
--- a/stdlib/effect.ts
+++ b/stdlib/effect.ts
@@ -7,7 +7,11 @@ export interface Kind1<Inp = unknown, Out = unknown> {
return: Out
}
-export interface Bind<_Eff extends Effect, _Fn extends Kind1> extends Effect {}
+type Func<Inp = unknown, Out = unknown>
+ = Kind1<Inp, Out>
+ | (<_T extends Inp>() => Out)
+
+export interface Bind<_Eff extends Effect, _Fn extends Func> extends Effect {}
export interface Seq<_Effs extends Effect[]> extends Effect {}