diff options
| -rw-r--r-- | examples/hello-world.ts | 20 | ||||
| -rw-r--r-- | src/context.ts | 12 | ||||
| -rw-r--r-- | src/eval.ts | 27 | ||||
| -rw-r--r-- | src/types.ts | 5 | ||||
| -rw-r--r-- | stdlib/ref.ts | 14 |
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 {} |
