aboutsummaryrefslogtreecommitdiff
path: root/src/eval-env/builtins.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/eval-env/builtins.ts')
-rw-r--r--src/eval-env/builtins.ts142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/eval-env/builtins.ts b/src/eval-env/builtins.ts
new file mode 100644
index 0000000..3adde06
--- /dev/null
+++ b/src/eval-env/builtins.ts
@@ -0,0 +1,142 @@
+import { Type } from 'ts-morph'
+import { Ctx } from "../types"
+
+export default (ctx: Ctx, args: Type[]) => ({
+ SetEvalEnvironment: async () => {
+ ctx.setEnv(ctx.getTypeValue(args[0]))
+ return []
+ },
+
+ DefineEffect: async () => {
+ const [nameTyp, exprTyp] = args
+ const name = nameTyp?.getLiteralValue() as string
+ const exprStr = exprTyp?.getLiteralValue() as string
+
+ ctx.addCustomEffect(name, exprStr)
+ return []
+ },
+
+ CreateRef: async () => {
+ const val = ctx.typeToString(args[0])
+ const refKey = ctx.createRef(val)
+ const [resultKey, _] = ctx.createResult(JSON.stringify(refKey))
+ return [resultKey]
+ },
+
+ GetRef: async () => {
+ const refKey = ctx.getTypeValue(args[0])
+ const val = ctx.getRef(refKey)
+ if (!val) throw new Error('Ref has been deleted')
+ const [resultKey, _] = ctx.createResult(val)
+ return [resultKey]
+ },
+
+ SetRef: async () => {
+ const [ keyTy, valTyp ] = args
+ ctx.setRef(ctx.getTypeValue(keyTy), ctx.typeToString(valTyp))
+ return []
+ },
+
+ DeleteRef: async () => {
+ ctx.deleteRef(ctx.getTypeValue(args[0]))
+ return []
+ },
+
+ Pure: async () => {
+ const [valTyp] = args
+ const [resultKey, _] = ctx.createResult(ctx.typeToString(valTyp))
+ return [resultKey]
+ },
+
+ Print: async () => {
+ console.log(...args.map(ctx.typeToString))
+ return []
+ },
+
+ PutString: async () => {
+ const [strinTyp] = args
+ const typString = ctx.getTypeValue(strinTyp) ?? ctx.typeToString(strinTyp)
+ process.stdout.write(typString)
+ return []
+ },
+
+ Debug: async () => {
+ const [labelTyp, valueTyp] = args
+ const label = ctx.getTypeValue(labelTyp)
+ const value = ctx.typeToString(valueTyp)
+ console.log(label, value)
+ const [resultKey, _] = ctx.createResult(JSON.stringify(value))
+ return [resultKey]
+ },
+
+ Bind: async () => {
+ const [inputTyp, chainToKind] = args
+ 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) : []
+ },
+
+ Try: async () => {
+ const [effTyp, catchK] = args
+
+ try {
+ if (!effTyp) throw new Error('wow')
+ return await ctx.evaluateType(ctx, effTyp)
+ } catch(e) {
+ const error = JSON.stringify((e as any)?.message ?? e)
+ const catchResExpr = `(${ctx.typeToString(catchK)} & { input: ${error} })['return']`
+ const [resultKey, _] = ctx.createResult(catchResExpr)
+ return [resultKey]
+ }
+ },
+
+ Throw: async () => {
+ throw args[0] && ctx.getTypeValue(args[0])
+ },
+
+ JsExpr: async () => {
+ const [exprTyp] = args
+ const exprStr = ctx.getTypeValue(exprTyp)
+ const result = eval(`JSON.stringify(${exprStr})`)
+ const [resultKey, _] = ctx.createResult(`${result}`)
+ return [resultKey]
+ },
+
+ Seq: async () => {
+ const [effectTyps] = args
+ const effectResults = await evalList(
+ ctx,
+ effectTyps?.getTupleElements() ?? []
+ )
+ const [resultKey, _] = ctx.createResult(`[
+ ${effectResults.map(ctx.getResultExpr).join(', ')}
+ ]`)
+ return [resultKey]
+ },
+
+ Do: async () => {
+ const [effectTyps] = args
+ const effectResults = await evalList(
+ ctx,
+ effectTyps?.getTupleElements() ?? []
+ )
+ // TODO: Use last type's result instead of last result key
+ const lastResKey = effectResults[effectResults.length - 1]
+ const [resultKey, _] = ctx.createResult(
+ `(${ctx.getResultExpr(lastResKey)})['output']`
+ )
+ return [resultKey]
+ },
+})