aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/hello-world.ts20
-rw-r--r--src/context.ts12
-rw-r--r--src/eval.ts27
-rw-r--r--src/types.ts5
-rw-r--r--stdlib/ref.ts14
5 files changed, 77 insertions, 1 deletions
diff --git a/examples/hello-world.ts b/examples/hello-world.ts
new file mode 100644
index 0000000..fcdb8e9
--- /dev/null
+++ b/examples/hello-world.ts
@@ -0,0 +1,20 @@
+import { Bind, Do, Kind1 } from "../stdlib/effect";
+import { CreateRef, GetRef, Ref, SetRef } from "../stdlib/ref";
+import { Print } from "../stdlib/stdio";
+
+interface PrintK extends Kind1 {
+ return: Print<this['input']>
+}
+
+interface Func extends Kind1<Ref> {
+ return: Do<[
+ SetRef<this['input'], 69>,
+ Bind<GetRef<this['input']>, PrintK>,
+ ]>
+}
+
+export type main = [
+ Bind<CreateRef<200>, Func>,
+ Print<1>,
+]
+
diff --git a/src/context.ts b/src/context.ts
index bdae0d3..6b7875c 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -65,6 +65,13 @@ export const createContext = (options: CtxOptions): Ctx => {
}
}
+ const refMap: Map<string, string> = new Map
+ const createRef = (ty: string): string => {
+ const key = uuid()
+ refMap.set(key, ty)
+ return key
+ }
+
const ctx: Ctx = {
sourceFile,
typeChecker,
@@ -72,6 +79,11 @@ export const createContext = (options: CtxOptions): Ctx => {
typeToString,
getTypeValue,
+ createRef,
+ getRef: (k: string) => refMap.get(k),
+ setRef: (k: string, ty: string) => refMap.set(k, ty),
+ deleteRef: (k: string) => refMap.delete(k),
+
createResult,
getResultExpr,
printResultNode: () => console.log(resultTypeNode?.print()),
diff --git a/src/eval.ts b/src/eval.ts
index 12997b1..8b53982 100644
--- a/src/eval.ts
+++ b/src/eval.ts
@@ -4,7 +4,6 @@ import readline from 'readline'
import { match } from './util'
import { Ctx } from './types'
-import { assert } from 'console'
const rl = readline.createInterface({
input: process.stdin,
@@ -39,6 +38,32 @@ export const evaluateType = async (
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))
diff --git a/src/types.ts b/src/types.ts
index e3ea7e9..059c0c2 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -17,6 +17,11 @@ export interface Ctx {
getResultExpr: (key?: string) => string
printResultNode: () => void
+ createRef: (ty: string) => string,
+ getRef: (key: string) => any,
+ setRef: (key: string, ty: string) => void,
+ deleteRef: (key: string) => void,
+
addCustomEffect: (name: string, expr: string) => void
runCustomEffect: (name: string, args: Type[]) => Promise<string[]>
hasCustomEffect: (name: string) => boolean
diff --git a/stdlib/ref.ts b/stdlib/ref.ts
new file mode 100644
index 0000000..22650f7
--- /dev/null
+++ b/stdlib/ref.ts
@@ -0,0 +1,14 @@
+import { Effect } from './effect'
+
+// TODO: Make Ref opaque
+// declare const $ref: unique symbol
+
+export type Ref = string // & { [$ref]: true }
+
+export interface CreateRef<_Val> extends Effect<Ref> {}
+
+export interface GetRef<_Key extends Ref> extends Effect {}
+
+export interface SetRef<_Key extends Ref, _Val> extends Effect {}
+
+export interface DeleteRef<_Key extends Ref> extends Effect {}