Last active
February 11, 2024 14:36
-
-
Save SHoltzen/e7d26930c6fde3db8f520c07148b13cf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang plait | |
; State-passing language | |
; Language has: let bindings, variables, numbers, box and set! | |
(define-type Exp | |
(let1E (id : Symbol) (assignment : Exp) (body : Exp)) | |
(varE (id : Symbol)) | |
(numE (n : Number)) | |
(unboxE (e : Exp)) | |
(boxE (e : Exp)) | |
(setE (b : Exp) (v : Exp))) | |
(define-type-alias Heap (Number * (Hashof Number Value))) | |
(define-type-alias Store (Hashof Symbol Value)) | |
(define mt-env (hash '())) | |
(define-type Value | |
[numV (n : Number)] | |
[locV (l : Number)]) | |
(define (lookup-store (s : Symbol) (n : Store)) | |
(type-case (Optionof Value) (hash-ref n s) | |
[(none) (error s "not bound")] | |
[(some v) v])) | |
(test (lookup-store 's (hash (list (pair 's (numV 10))))) (numV 10)) | |
(test (lookup-store 's (hash (list (pair 's (locV 10))))) (locV 10)) | |
(test/exn (lookup-store 'n (hash (list (pair 's (numV 10))))) "not bound") | |
; it is important to note that extend-store will overwrite if there are | |
; overlapping symbols. | |
(extend-store : (Store Symbol Value -> Store)) | |
(define (extend-store old-store new-name value) | |
(hash-set old-store new-name value)) | |
(test (extend-store mt-env 's (numV 10)) (hash (list (pair 's (numV 10))))) | |
(test (extend-store (hash (list (pair 's (numV 20)))) 's (numV 10)) | |
(hash (list (pair 's (numV 10))))) | |
(define mt-heap (pair 0 (hash '()))) | |
(define (lookup-heap (l : Number) (h : Heap)) | |
(type-case (Optionof Value) (hash-ref (snd h) l) | |
[(none) (error 'runtime "invalid location")] | |
[(some v) v])) | |
(test (lookup-heap 0 (pair 1 (hash (list (pair 0 (numV 10)))))) (numV 10)) | |
(test (lookup-heap 0 (pair 1 (hash (list (pair 0 (locV 10)))))) (locV 10)) | |
(test/exn (lookup-heap 23 (pair 1 (hash (list (pair 0 (locV 10)))))) | |
"invalid location") | |
(extend-heap : (Heap Value -> (Number * Heap))) | |
(define (extend-heap h value) | |
(letrec [(cur-loc (fst h)) | |
(cur-heap (snd h)) | |
(new-heap (hash-set cur-heap cur-loc value))] | |
(pair cur-loc (pair (+ 1 cur-loc) new-heap)))) | |
(test (extend-heap (pair 1 (hash (list (pair 0 (numV 10))))) (locV 20)) | |
(pair 1 (pair 2 (hash (list (pair 0 (numV 10)) (pair 1 (locV 20))))))) | |
(set-heap : (Heap Number Value -> Heap)) | |
(define (set-heap h loc value) | |
(pair (fst h) (hash-set (snd h) loc value))) | |
(test (set-heap (pair 1 (hash (list (pair 0 (numV 10))))) 5 (locV 20)) | |
(pair 1 (hash (list (pair 0 (numV 10)) (pair 5 (locV 20)))))) | |
; the store will store local variables (e.g. ones in let-binds) | |
; the heap will store boxed variables | |
(interp : (Exp Store Heap -> (Value * Heap))) | |
(define (interp e store heap) | |
(type-case Exp e | |
#| | |
--------------- | |
numE n, S, H ↦ numV n, H | |
|# | |
[(numE n) (pair (numV n) heap)] | |
#| | |
e, S, H ↦ v, H' | |
--------------- | |
let x = e in e2, S, H ↦ e2, S[x -> v], H' | |
|# | |
[(let1E id assignment body) | |
(letrec [(eval-assgn (interp assignment store heap)) | |
(assgn-value (fst eval-assgn)) | |
(assgn-heap (snd eval-assgn)) | |
(new-store (extend-store store id assgn-value))] | |
(interp body new-store assgn-heap))] | |
#| | |
x in dom(S) | |
--------------- | |
x , S, H ↦ S(x), H | |
|# | |
[(varE id) (pair (lookup-store id store) heap)] | |
#| | |
e, S, H ↦ v, H' (loc, H'') = extend-heap H' v | |
--------------- | |
box e, S, H ↦ loc, H'' | |
|# | |
[(boxE e) | |
(letrec [(eval-e (interp e store heap)) | |
(value (fst eval-e)) | |
(e-heap (snd eval-e)) | |
(heap-insertion (extend-heap e-heap value))] | |
(pair (locV (fst heap-insertion)) (snd heap-insertion)))] | |
#| | |
e, S, H ↦ loc, H' | |
--------------- | |
unbox e, S, H ↦ H'(loc), H' | |
|# | |
[(unboxE body) | |
(letrec [(eval-body (interp body store heap)) | |
(body-v (fst eval-body)) | |
(body-heap (snd eval-body))] | |
(type-case Value body-v | |
[(numV n) (error 'runtime "invalid value for unbox")] | |
[(locV l) (pair (lookup-heap l body-heap) body-heap)]))] | |
#| | |
e, S, H ↦ loc , H' e2, S, H' ↦ v'', H'' | |
--------------- | |
set! e e2, S, H ↦ ???, H''[loc -> v''] | |
|# | |
[(setE body arg) | |
(letrec [(eval-body (interp body store heap)) | |
(body-v (fst eval-body)) | |
(body-heap (snd eval-body)) | |
(eval-arg (interp arg store body-heap)) | |
(eval-v (fst eval-arg)) | |
(eval-heap (snd eval-arg))] | |
(type-case Value body-v | |
[(numV n) (error 'runtime "invalid value for set!")] | |
[(locV l) (pair (numV 0) (set-heap eval-heap l eval-v))]))])) | |
; let x = box 0 in unbox x | |
(test (interp (let1E 'x (boxE (numE 0)) (unboxE (varE 'x))) mt-env mt-heap) | |
(values (numV 0) (values 1 (hash (list (pair 0 (numV 0))))))) | |
; let x = box 0 in let y = set! x 10 in unbox x | |
(test | |
(interp (let1E 'x (boxE (numE 0)) | |
(let1E 'y (setE (varE 'x) (numE 10)) | |
(unboxE (varE 'x)))) mt-env mt-heap) | |
(values (numV 10) (values 1 (hash (list (pair 0 (numV 10)))))) ) | |
; let x = box 0 in let y = box 1 in unbox x | |
(test (interp | |
(let1E 'x (boxE (numE 0)) | |
(let1E 'y (boxE (numE 1)) | |
(unboxE (varE 'x)))) mt-env mt-heap) | |
(values (numV 0) (values 2 (hash (list (pair 0 (numV 0)) (pair 1 (numV 1))))))) | |
; let x = box 0 in let y = box 1 in let z = set! y 10 in unbox x | |
(test (interp | |
(let1E 'x (boxE (numE 0)) | |
(let1E 'y (boxE (numE 1)) | |
(let1E 'z (setE (varE 'y) (numE 10)) | |
(unboxE (varE 'x))))) mt-env mt-heap) | |
(values (numV 0) (values 2 (hash (list (pair 0 (numV 0)) (pair 1 (numV 10))))))) | |
; let x = box 0 in let x = box 10 in unbox x | |
(test (interp | |
(let1E 'x (boxE (numE 0)) | |
(let1E 'x (boxE (numE 10)) | |
(unboxE (varE 'x)))) mt-env mt-heap) | |
(values (numV 10) (values 2 (hash (list (pair 0 (numV 0)) (pair 1 (numV 10))))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment