mirror of
https://github.com/dhil/phd-dissertation
synced 2026-03-13 11:08:25 +00:00
Compare commits
237 Commits
cf2422a312
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2d79e1d06 | ||
|
|
47410e4d14 | ||
| 81a4ecec0b | |||
| cafa8b1ba2 | |||
| 2e61275a5b | |||
| e90ba67a4b | |||
| 6aee80a71b | |||
| aea67c86b4 | |||
|
|
5ede30903f | ||
|
|
03b7c5b548 | ||
| 7535fe7ecc | |||
| 72b54ad278 | |||
| 01e707822f | |||
| 2cecb13d34 | |||
| ed634fcaa3 | |||
| c60dc80fde | |||
| e86597f4e4 | |||
| 2b7b1df8db | |||
| 20f44ad547 | |||
| 101ac96aa2 | |||
| e6182105de | |||
| 63fe9a738a | |||
| 3a9394baf8 | |||
| 6193214890 | |||
| ffe6ebd0b9 | |||
| 01a8a3d581 | |||
| 008e80ea67 | |||
| 3276537ab1 | |||
| 20551152b3 | |||
| 8679803146 | |||
| d7bd881a00 | |||
| f5685fe70d | |||
| 7f3503153f | |||
| 40c6505ae2 | |||
| b897751a38 | |||
| 3e1bbf3206 | |||
| 40948507e9 | |||
| 2a800f07e2 | |||
| d3921f24e3 | |||
| 7063acb4e7 | |||
| c9ff1d9af8 | |||
| fff15c9c83 | |||
| a24a33dcf8 | |||
| 6c128a1181 | |||
| 98784c59ab | |||
| 6492391ed4 | |||
| cea34c85e1 | |||
| 40b1144d9b | |||
| 3067bfb939 | |||
| 83b5f7db99 | |||
| 981b0d48f8 | |||
| ee8a4ab2dd | |||
| 3fda920eae | |||
| 0b198e7a25 | |||
| 740413ed1b | |||
| 7ed7a44d61 | |||
| 350d741204 | |||
| f8697be4c7 | |||
| f9b8234221 | |||
| 67598cee1e | |||
| 113b7c4620 | |||
| c52edb51f6 | |||
| a4b802e4e0 | |||
| 3b7dd13e3d | |||
| a42bfc25ab | |||
| 97a4a806e1 | |||
| 0e02128d03 | |||
| aa2b963d0e | |||
| 2f494aae67 | |||
| a36b1cf0d4 | |||
| 53b54056f8 | |||
| f80becc368 | |||
| 6c6d8e2aba | |||
| bc7d89ec5f | |||
| 69a2c881b7 | |||
| 6e5d7b01df | |||
| 49e53bac03 | |||
| 4834a6e5d3 | |||
| 3f91ab595e | |||
| 333452bed2 | |||
| 51429afdd8 | |||
| e52cc41d40 | |||
| b2eb9334ca | |||
| 754c3b823e | |||
| 363628c1d3 | |||
| 664956251c | |||
| d18a5e3058 | |||
| 00f4264547 | |||
| 5597c9657b | |||
| 8b3660b0ce | |||
| 77475e129b | |||
| 9c2da2c378 | |||
| ee92e3b483 | |||
| 6c3eb0e9cf | |||
| a476679810 | |||
| 3cb5e3622f | |||
| 11b4888263 | |||
| 68110a67ef | |||
| d4ce54795c | |||
| 2fbbf04bd4 | |||
| 0885c75c1e | |||
| 0c4108cdea | |||
| 4259ddee4d | |||
| 5340615c26 | |||
| 28fd0505ce | |||
| fe6444ff3d | |||
| 9fa5ebe6eb | |||
| 79735da80a | |||
| 75d0dac161 | |||
| a7d5117a64 | |||
| 75eb07cee1 | |||
| ccd1f59d57 | |||
| e84b4605c2 | |||
| a57ac855c2 | |||
| fac68ae974 | |||
| a4d9cc4edd | |||
| 02b9a782f3 | |||
| e419d52ee2 | |||
| 98c79cc70d | |||
| 2c51620a56 | |||
| 0f31e10582 | |||
| 9679a3cc82 | |||
| 559d9c2d37 | |||
| 5c835f5179 | |||
| 836d85ea99 | |||
| 622932494d | |||
| 111b4cb35a | |||
| 6f44524750 | |||
| 3438581826 | |||
| 650de85238 | |||
| b47c60fe57 | |||
| 696266922a | |||
| 8fad146499 | |||
| 93793648ef | |||
| d9717b7434 | |||
| 7c3942a564 | |||
| a462aa8a57 | |||
| 13d76a146b | |||
| 67a48945e9 | |||
| b73d9a213f | |||
| 475f82324d | |||
| 6f8c5364f2 | |||
| 0e2015485a | |||
| 7ec90b216d | |||
| 35af9ba572 | |||
| a3273afa50 | |||
| 1945a7307c | |||
| 307e4bd259 | |||
| 114252b64f | |||
| 21fba05959 | |||
| a41fb391fc | |||
| 85757c48fd | |||
| 28b8503b97 | |||
| 2c63d11392 | |||
| c254d293a9 | |||
| eefa6e4ad4 | |||
| 8cc91fa4b1 | |||
| 15125f206c | |||
| ef04653ad2 | |||
| 1ede601435 | |||
| 9e7c74ef0f | |||
| d1a91fb197 | |||
| 76d9c00e19 | |||
| d00227a57b | |||
| e46cd37b01 | |||
| 26b12c123a | |||
| a3e97f9510 | |||
| 09cd57fbce | |||
| 5981ac986c | |||
| a46e2fd5d6 | |||
| 4ece98ba21 | |||
| a609ca4b81 | |||
| d0061e18c2 | |||
| c28aef1c9e | |||
| 8ecfadb94e | |||
| 52b12535ae | |||
| bce45f10e3 | |||
| 1129d2bb71 | |||
| 9ba7def07b | |||
| 2eb5b0d4ba | |||
| 1c692d8cbf | |||
| 4d5bd3e08e | |||
| b13960a5e1 | |||
| 84fe38105e | |||
| aacee4d72a | |||
| 1bca580f1f | |||
| b02743df0f | |||
| b76e18488c | |||
| 60976a7013 | |||
| e88d27740d | |||
| 74c25ce63b | |||
| f9d92a231e | |||
| 50125e86ac | |||
| d6b67950b2 | |||
| fc0c6a98bb | |||
| 388dc36b20 | |||
| 61b2ce4f66 | |||
| 08b107323d | |||
| 1a93d1a5b7 | |||
| febf2a06c0 | |||
| 0861e926ee | |||
| 9f5b2ba56c | |||
| 78e291d602 | |||
| d8ac28a9ee | |||
| 817676f8e8 | |||
| 4c480a4b6e | |||
| 408b6041f6 | |||
| 950bee7ce3 | |||
| 25b48c1082 | |||
| 0cd953ac94 | |||
| 34d724919f | |||
| 2f7da6ed15 | |||
| 5f7e8eadd2 | |||
| 284139375a | |||
| 28aaebf5ec | |||
| f1d88fbcc4 | |||
| 669b708a79 | |||
| df08169725 | |||
| b609812079 | |||
| 1b2882b1eb | |||
| 7f99b18242 | |||
| 95035458ec | |||
| a29a6dc9c5 | |||
| bd3e2c8b9f | |||
| 485d02f101 | |||
| d890a327a7 | |||
| e9cd4315be | |||
| f1e1b75ef7 | |||
| 2f7a6ec818 | |||
| 2b21cfcb4e | |||
| dd0aaa32f6 | |||
| 6588c0581c | |||
| 12e24d7051 | |||
| ace6a5b37c | |||
| 7917c2ca0b | |||
| b8fd8ea43d | |||
| 617fd1112c |
7
Makefile
7
Makefile
@@ -3,8 +3,10 @@ CFLAGS=-interaction=nonstopmode -halt-on-error -file-line-error
|
|||||||
BIBC=bibtex
|
BIBC=bibtex
|
||||||
PAPER=thesis
|
PAPER=thesis
|
||||||
BIBLIO=$(PAPER)
|
BIBLIO=$(PAPER)
|
||||||
|
LATEST_COMMIT=$(shell git log --format="%h" -n 1)
|
||||||
|
|
||||||
all: $(PAPER).pdf
|
all: $(PAPER).pdf
|
||||||
|
draft: $(PAPER).pdf-draft
|
||||||
|
|
||||||
$(PAPER).aux: $(PAPER).tex
|
$(PAPER).aux: $(PAPER).tex
|
||||||
$(TEXC) $(CFLAGS) $(PAPER)
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
@@ -16,6 +18,11 @@ $(PAPER).pdf: $(PAPER).aux $(BIBLIO).bbl
|
|||||||
$(TEXC) $(CFLAGS) $(PAPER)
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
$(TEXC) $(CFLAGS) $(PAPER)
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
|
|
||||||
|
$(PAPER).pdf-draft: CFLAGS:=$(CFLAGS) "\def\DRAFT{$(LATEST_COMMIT)}\input{$(PAPER)}"
|
||||||
|
$(PAPER).pdf-draft: all
|
||||||
|
mv $(PAPER).pdf $(PAPER)-draft.pdf
|
||||||
|
tar cf thesis-draft.tar.gz $(PAPER)-draft.pdf
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.log *.aux *.toc *.out
|
rm -f *.log *.aux *.toc *.out
|
||||||
rm -f *.bbl *.blg *.fls *.xml
|
rm -f *.bbl *.blg *.fls *.xml
|
||||||
|
|||||||
120
README.md
120
README.md
@@ -1,6 +1,120 @@
|
|||||||
# PhD dissertation on foundations for programming and implementing effect handlers
|
# Foundations for programming and implementing effect handlers
|
||||||
|
|
||||||
|
A copy of my dissertation can be [downloaded via my
|
||||||
|
website](https://dhil.net/research/papers/thesis.pdf).
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Submitted on May 30, 2021. Examined on August 13, 2021.
|
||||||
|
|
||||||
|
The board of examiners were
|
||||||
|
|
||||||
|
* [Andrew Kennedy](https://github.com/andrewjkennedy) (Facebook London)
|
||||||
|
* [Edwin Brady](https://www.type-driven.org.uk/edwinb/) (University of St Andrews)
|
||||||
|
* [Ohad Kammar](http://denotational.co.uk/) (The University of Edinburgh)
|
||||||
|
* [Stephen Gilmore](https://homepages.inf.ed.ac.uk/stg/) (The University of Edinburgh)
|
||||||
|
|
||||||
|
## Thesis structure
|
||||||
|
|
||||||
|
The dissertation is structured as follows.
|
||||||
|
|
||||||
|
### Introduction
|
||||||
|
|
||||||
|
* Chapter 1 puts forth an argument for why effect handlers
|
||||||
|
matter. Following this argument it provides a basic introduction to
|
||||||
|
several different approaches to effectful programming through the
|
||||||
|
lens of the state effect. In addition, it also declares the scope
|
||||||
|
and contributions of the dissertation, and discusses some related
|
||||||
|
work.
|
||||||
|
|
||||||
|
### Programming
|
||||||
|
|
||||||
|
* Chapter 2 illustrates effect handler oriented programming by
|
||||||
|
example by implementing a small operating system dubbed Tiny UNIX,
|
||||||
|
which captures some essential traits of Ritchie and Thompson's
|
||||||
|
UNIX. The implementation starts with a basic notion of file i/o,
|
||||||
|
and then, it evolves into a feature-rich operating system with full
|
||||||
|
file i/o, multiple user environments, multi-tasking, and more, by
|
||||||
|
composing ever more effect handlers.
|
||||||
|
|
||||||
|
* Chapter 3 introduces a polymorphic fine-grain call-by-value core
|
||||||
|
calculus, λ<sub>b</sub>, which makes key use of Rémy-style row
|
||||||
|
polymorphism to implement polymorphic variants, structural records,
|
||||||
|
and a structural effect system. The calculus distils the essence of
|
||||||
|
the core of the Links programming language. The chapter also
|
||||||
|
presents three extensions of λ<sub>b</sub>, which are λ<sub>h</sub>
|
||||||
|
that adds deep handlers, λ<sup>†</sup> that adds shallow handlers,
|
||||||
|
and λ<sup>‡</sup> that adds parameterised handlers.
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
|
||||||
|
* Chapter 4 develops a higher-order continuation passing style
|
||||||
|
translation for effect handlers through a series of step-wise
|
||||||
|
refinements of an initial standard continuation passing style
|
||||||
|
translation for λ<sub>b</sub>. Each refinement slightly modifies
|
||||||
|
the notion of continuation employed by the translation. The
|
||||||
|
development ultimately leads to the key invention of generalised
|
||||||
|
continuation, which is used to give a continuation passing style
|
||||||
|
semantics to deep, shallow, and parameterised handlers.
|
||||||
|
|
||||||
|
* Chapter 5 demonstrates an application of generalised continuations
|
||||||
|
to abstract machine as we plug generalised continuations into
|
||||||
|
Felleisen and Friedman's CEK machine to obtain an adequate abstract
|
||||||
|
runtime with simultaneous support for deep, shallow, and
|
||||||
|
parameterised handlers.
|
||||||
|
|
||||||
|
### Expressiveness
|
||||||
|
|
||||||
|
* Chapter 6 shows that deep, shallow, and parameterised notions of
|
||||||
|
handlers can simulate one another up to specific notions of
|
||||||
|
administrative reduction.
|
||||||
|
|
||||||
|
* Chapter 7 studies the fundamental efficiency of effect handlers. In
|
||||||
|
this chapter, we show that effect handlers enable an asymptotic
|
||||||
|
improvement in runtime complexity for a certain class of
|
||||||
|
functions. Specifically, we consider the *generic count* problem
|
||||||
|
using a pure PCF-like base language λ<sub>b</sub><sup>→</sup> (a
|
||||||
|
simply typed variation of λ<sub>b</sub>) and its extension with
|
||||||
|
effect handlers λ<sub>h</sub><sup>→</sup>. We show that
|
||||||
|
λ<sub>h</sub><sup>→</sup> admits an asymptotically more efficient
|
||||||
|
implementation of generic count than any λ<sub>b</sub><sup>→</sup>
|
||||||
|
implementation.
|
||||||
|
|
||||||
|
### Conclusions
|
||||||
|
* Chapter 8 concludes and discusses future work.
|
||||||
|
|
||||||
|
### Appendices
|
||||||
|
|
||||||
|
* Appendix A contains a literature survey of continuations and
|
||||||
|
first-class control. I classify continuations according to their
|
||||||
|
operational behaviour and provide an overview of the various
|
||||||
|
first-class sequential control operators that appear in the
|
||||||
|
literature. The application spectrum of continuations is discussed
|
||||||
|
as well as implementation strategies for first-class control.
|
||||||
|
* Appendix B contains a proof that shows the `Get-get` equation for
|
||||||
|
state is redundant.
|
||||||
|
* Appendix C contains the proof details and gadgetry for the
|
||||||
|
complexity of the effectful generic count program.
|
||||||
|
* Appendix D provides a sample implementation of the Berger count
|
||||||
|
program and discusses it in more detail.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
To build the dissertation you need the [Informatics thesis LaTeX
|
To build the dissertation you need the [Informatics thesis LaTeX
|
||||||
class](https://github.com/dhil/inf-thesis-latex-cls).
|
class](https://github.com/dhil/inf-thesis-latex-cls) with the
|
||||||
|
University of Edinburgh crests. Invoking `make` on the command line
|
||||||
|
ought to produce a PDF copy of the dissertation named `thesis.pdf`,
|
||||||
|
e.g.
|
||||||
|
|
||||||
Don't hold your breath... This thing isn't due for a while...
|
```shell
|
||||||
|
$ make
|
||||||
|
```
|
||||||
|
|
||||||
|
## Timeline
|
||||||
|
|
||||||
|
I submitted my thesis on May 30, 2021. It was examined on August 13,
|
||||||
|
2021, where I received pass with minor corrections. The revised thesis
|
||||||
|
was submitted on December 22, 2021. It was approved on March
|
||||||
|
14, 2022. The final revision was submitted on March 23, 2022. I
|
||||||
|
received my PhD award letter on March 24, 2022. My graduation
|
||||||
|
ceremony took place in McEwan Hall on July 11, 2022.
|
||||||
|
|||||||
124
code/State.hs
Normal file
124
code/State.hs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
{- A Haskell version of the companion code for "State of effectful programming".
|
||||||
|
Tested with GHCi 8.6.5. -}
|
||||||
|
import Control.Monad.ST (runST)
|
||||||
|
import Data.STRef (newSTRef, readSTRef, writeSTRef)
|
||||||
|
-- State monad
|
||||||
|
newtype State s a = State { runState :: s -> (a,s) }
|
||||||
|
|
||||||
|
-- | State is a functor
|
||||||
|
instance Functor (State s) where
|
||||||
|
fmap f m = State (\st -> let (x, st') = runState m st in
|
||||||
|
(f x, st'))
|
||||||
|
|
||||||
|
-- | State is an applicative functor
|
||||||
|
instance Applicative (State s) where
|
||||||
|
pure x = State (\st -> (x, st))
|
||||||
|
m1 <*> m2 = State (\st -> let (f, st') = runState m1 st in
|
||||||
|
runState (fmap f m2) st')
|
||||||
|
|
||||||
|
-- | State is a monad
|
||||||
|
instance Monad (State s) where
|
||||||
|
return = pure
|
||||||
|
m >>= k = State (\st -> let (x, st') = runState m st in
|
||||||
|
runState (k x) st')
|
||||||
|
|
||||||
|
-- | State operations
|
||||||
|
get :: () -> State s s
|
||||||
|
get () = State (\st -> (st, st))
|
||||||
|
|
||||||
|
put :: s -> State s ()
|
||||||
|
put st = State (\st' -> ((), st))
|
||||||
|
|
||||||
|
-- Continuation monad
|
||||||
|
newtype Cont r a = Cont { runCont :: (a -> r) -> r }
|
||||||
|
|
||||||
|
-- | Cont is a functor
|
||||||
|
instance Functor (Cont r) where
|
||||||
|
fmap f k = Cont (\g -> runCont k (\x -> g (f x)))
|
||||||
|
|
||||||
|
-- | Cont is an applicative functor
|
||||||
|
instance Applicative (Cont r) where
|
||||||
|
pure x = Cont (\k -> k x)
|
||||||
|
k <*> k' = Cont (\r -> runCont k
|
||||||
|
(\k'' -> runCont k'
|
||||||
|
(\x -> r (k'' x))))
|
||||||
|
|
||||||
|
-- | Cont is a monad
|
||||||
|
instance Monad (Cont r) where
|
||||||
|
return = pure
|
||||||
|
m >>= k = Cont (\k' -> runCont m
|
||||||
|
(\x -> runCont (k x)
|
||||||
|
(\y -> k' y)))
|
||||||
|
|
||||||
|
-- | State operations
|
||||||
|
|
||||||
|
getk :: () -> Cont (State s a) s
|
||||||
|
getk () = Cont (\k -> State (\st -> runState (k st) st))
|
||||||
|
|
||||||
|
putk :: s -> Cont (State s a) ()
|
||||||
|
putk st' = Cont (\k -> State (\st -> runState (k ()) st'))
|
||||||
|
|
||||||
|
-- Free monad
|
||||||
|
data Free f a = Return a
|
||||||
|
| Op (f (Free f a))
|
||||||
|
|
||||||
|
-- | Free is a functor
|
||||||
|
instance Functor f => Functor (Free f) where
|
||||||
|
fmap f (Return x) = Return (f x)
|
||||||
|
fmap f (Op y) = Op (fmap (fmap f) y)
|
||||||
|
|
||||||
|
-- | Free is an applicative functor
|
||||||
|
instance Functor f => Applicative (Free f) where
|
||||||
|
pure = Return
|
||||||
|
(Return f) <*> xs = fmap f xs
|
||||||
|
(Op f) <*> xs = Op (fmap (\g -> g <*> xs) f)
|
||||||
|
|
||||||
|
-- | Free is a monad
|
||||||
|
instance Functor f => Monad (Free f) where
|
||||||
|
return = Return
|
||||||
|
(Return x) >>= k = k x
|
||||||
|
(Op y) >>= k = Op (fmap (\m' -> m' >>= k) y)
|
||||||
|
|
||||||
|
-- | Auxiliary function for constructing operation nodes
|
||||||
|
do' :: Functor f => f a -> Free f a
|
||||||
|
do' op = Op (fmap Return op)
|
||||||
|
|
||||||
|
-- Instantiate Free with state
|
||||||
|
data FreeState s r = Get (s -> r)
|
||||||
|
| Put s (() -> r)
|
||||||
|
|
||||||
|
-- | FreeState is a functor
|
||||||
|
instance Functor (FreeState s) where
|
||||||
|
fmap f (Get k) = Get (\st -> f (k st))
|
||||||
|
fmap f (Put st' k) = Put st' (\() -> f (k ()))
|
||||||
|
|
||||||
|
-- | State operations
|
||||||
|
get' :: () -> Free (FreeState s) s
|
||||||
|
get' () = do' (Get (\x -> x))
|
||||||
|
|
||||||
|
put' :: s -> Free (FreeState s) ()
|
||||||
|
put' st = do' (Put st (\() -> ()))
|
||||||
|
|
||||||
|
-- | State handler
|
||||||
|
runState' :: s -> Free (FreeState s) a -> (a, s)
|
||||||
|
runState' st0 (Op (Get k)) = runState' st0 (k st0)
|
||||||
|
runState' st0 (Op (Put st k)) = runState' st (k ())
|
||||||
|
runState' st0 (Return x) = (x, st0)
|
||||||
|
|
||||||
|
-- Generic state example
|
||||||
|
incrEven :: Monad m => (() -> m Int, Int -> m ()) -> () -> m Bool
|
||||||
|
incrEven (get, put) () = get () >>= (\st -> put (1 + st) >>= (\() -> return (even st)))
|
||||||
|
|
||||||
|
runExamples :: Int -> [(String, (Bool, Int))]
|
||||||
|
runExamples st0 = map (\(s, f) -> (s, f st0)) examples
|
||||||
|
where examples = [ ("builtin state", \st -> runST $ do
|
||||||
|
st' <- newSTRef st
|
||||||
|
v <- readSTRef st'
|
||||||
|
writeSTRef st' (v + 1)
|
||||||
|
v' <- readSTRef st'
|
||||||
|
return (even v, v'))
|
||||||
|
, ("pure state passing", \st -> (even st, st + 1))
|
||||||
|
, ("state monad", \st -> runState (incrEven (get, put) ()) st)
|
||||||
|
, ("continuation monad", \st -> runState (runCont (incrEven (getk, putk) ())
|
||||||
|
(\x -> State (\st -> (x, st)))) st)
|
||||||
|
, ("free monad", \st -> runState' st (incrEven (get', put') ())) ]
|
||||||
1469
code/ehop2022.links
Normal file
1469
code/ehop2022.links
Normal file
File diff suppressed because it is too large
Load Diff
396
code/state.ml
Normal file
396
code/state.ml
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
(* Companion for "State of effectful programming"
|
||||||
|
Tested with OCaml 4.10.0+multicore. *)
|
||||||
|
|
||||||
|
(* Generic direct-style incr_even *)
|
||||||
|
let even : int -> bool
|
||||||
|
= fun n -> n mod 2 = 0
|
||||||
|
|
||||||
|
let incr_even : (unit -> int) * (int -> unit) -> unit -> bool
|
||||||
|
= fun (get, put) () ->
|
||||||
|
let st = get () in
|
||||||
|
put (1 + st);
|
||||||
|
even st
|
||||||
|
|
||||||
|
(* Delimited control *)
|
||||||
|
module Prompt : sig
|
||||||
|
type 'a t
|
||||||
|
val make : unit -> 'a t
|
||||||
|
val reify : 'a t -> (('b -> 'a) -> 'a) -> 'b
|
||||||
|
val install : 'a t -> (unit -> 'a) -> 'a
|
||||||
|
end = struct
|
||||||
|
type 'a t = {
|
||||||
|
install : (unit -> 'a) -> 'a;
|
||||||
|
reify : 'b. (('b -> 'a) -> 'a) -> 'b
|
||||||
|
}
|
||||||
|
|
||||||
|
let make (type a) () =
|
||||||
|
let module M = struct
|
||||||
|
effect Prompt : (('b -> a) -> a) -> 'b
|
||||||
|
end
|
||||||
|
in
|
||||||
|
let reify f = perform (M.Prompt f) in
|
||||||
|
let install f =
|
||||||
|
match f () with
|
||||||
|
| x -> x
|
||||||
|
| effect (M.Prompt f) k -> f (continue k)
|
||||||
|
in
|
||||||
|
{ install; reify }
|
||||||
|
|
||||||
|
let install { install; _ } = install
|
||||||
|
let reify { reify; _ } = reify
|
||||||
|
let resume k v = continue k v
|
||||||
|
end
|
||||||
|
|
||||||
|
module type CTRL = sig
|
||||||
|
type ans
|
||||||
|
val reset : (unit -> ans) -> ans
|
||||||
|
val shift : (('a -> ans) -> ans) -> 'a
|
||||||
|
end
|
||||||
|
|
||||||
|
module Ctrl(R : sig type ans end) : sig
|
||||||
|
include CTRL with type ans = R.ans
|
||||||
|
end = struct
|
||||||
|
type ans = R.ans
|
||||||
|
|
||||||
|
let p : ans Prompt.t = Prompt.make ()
|
||||||
|
|
||||||
|
let reset m =
|
||||||
|
Prompt.install p m
|
||||||
|
|
||||||
|
let shift f =
|
||||||
|
Prompt.reify p
|
||||||
|
(fun k ->
|
||||||
|
Prompt.install p
|
||||||
|
(fun () ->
|
||||||
|
f (fun x ->
|
||||||
|
Prompt.install p
|
||||||
|
(fun () -> k x))))
|
||||||
|
end
|
||||||
|
|
||||||
|
module CtrlState
|
||||||
|
(S : sig type s end)
|
||||||
|
(R : sig type ans end): sig
|
||||||
|
type s = S.s
|
||||||
|
type ans = s -> R.ans * s
|
||||||
|
|
||||||
|
val get : unit -> s
|
||||||
|
val put : s -> unit
|
||||||
|
|
||||||
|
val run : (unit -> R.ans) -> ans
|
||||||
|
end = struct
|
||||||
|
type s = S.s
|
||||||
|
type ans = s -> R.ans * s
|
||||||
|
module Ctrl = Ctrl(struct type nonrec ans = ans end)
|
||||||
|
|
||||||
|
let get () = Ctrl.shift (fun k -> fun st -> k st st)
|
||||||
|
let put st' = Ctrl.shift (fun k -> fun st -> k () st')
|
||||||
|
|
||||||
|
let run m =
|
||||||
|
Ctrl.reset
|
||||||
|
(fun () ->
|
||||||
|
let x = m () in
|
||||||
|
fun st -> (x, st))
|
||||||
|
end
|
||||||
|
|
||||||
|
module CtrlIntState = CtrlState(struct type s = int end)(struct type ans = bool end)
|
||||||
|
|
||||||
|
(* Monadic programming *)
|
||||||
|
module type MONAD = sig
|
||||||
|
type 'a t
|
||||||
|
val return : 'a -> 'a t
|
||||||
|
val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
end
|
||||||
|
|
||||||
|
(** State monad **)
|
||||||
|
module type STATE_MONAD = sig
|
||||||
|
type ans
|
||||||
|
type s
|
||||||
|
include MONAD
|
||||||
|
|
||||||
|
val get : unit -> s t
|
||||||
|
val put : s -> unit t
|
||||||
|
val run : (unit -> ans t) -> s -> ans * s
|
||||||
|
end
|
||||||
|
|
||||||
|
module StateMonad(S : sig type s end)(R : sig type ans end): sig
|
||||||
|
include STATE_MONAD with type s = S.s
|
||||||
|
and type ans = R.ans
|
||||||
|
end = struct
|
||||||
|
type ans = R.ans
|
||||||
|
type s = S.s
|
||||||
|
type 'a t = s -> 'a * s
|
||||||
|
|
||||||
|
let return : 'a -> 'a t
|
||||||
|
= fun x -> fun st -> (x, st)
|
||||||
|
|
||||||
|
let (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
= fun m k -> fun st ->
|
||||||
|
let (x, st') = m st in
|
||||||
|
k x st'
|
||||||
|
|
||||||
|
let get : unit -> s t
|
||||||
|
= fun () st -> (st, st)
|
||||||
|
|
||||||
|
let put : s -> unit t
|
||||||
|
= fun st st' -> ((), st)
|
||||||
|
|
||||||
|
let run : (unit -> ans t) -> s -> ans * s
|
||||||
|
= fun m st -> m () st
|
||||||
|
end
|
||||||
|
|
||||||
|
module IntStateMonad = StateMonad(struct type s = int end)(struct type ans = bool end)
|
||||||
|
|
||||||
|
(** Continuation monad **)
|
||||||
|
module type CONTINUATION_MONAD = sig
|
||||||
|
type r
|
||||||
|
include MONAD with type 'a t = ('a -> r) -> r
|
||||||
|
end
|
||||||
|
|
||||||
|
module ContinuationMonad(R : sig type ans end): sig
|
||||||
|
include CONTINUATION_MONAD with type r = R.ans
|
||||||
|
end = struct
|
||||||
|
type r = R.ans
|
||||||
|
type 'a t = ('a -> r) -> r
|
||||||
|
|
||||||
|
let return : 'a -> 'a t
|
||||||
|
= fun x -> fun k -> k x
|
||||||
|
|
||||||
|
let (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
= fun m k -> fun c ->
|
||||||
|
m (fun x -> k x c)
|
||||||
|
end
|
||||||
|
|
||||||
|
module ContinuationStateMonad
|
||||||
|
(S : sig type s end)
|
||||||
|
(R : sig type ans end): sig
|
||||||
|
type s = S.s
|
||||||
|
type ans = R.ans
|
||||||
|
include CONTINUATION_MONAD with type r = s -> ans * s
|
||||||
|
|
||||||
|
val get : unit -> s t
|
||||||
|
val put : s -> unit t
|
||||||
|
val run : (unit -> ans t) -> s -> ans * s
|
||||||
|
end = struct
|
||||||
|
type s = S.s
|
||||||
|
type ans = R.ans
|
||||||
|
module ContinuationMonad : CONTINUATION_MONAD with type r = s -> ans * s
|
||||||
|
= ContinuationMonad(struct type nonrec ans = s -> ans * s end)
|
||||||
|
include ContinuationMonad
|
||||||
|
|
||||||
|
let get : unit -> s t
|
||||||
|
= fun () -> fun k -> fun st -> k st st
|
||||||
|
|
||||||
|
let put : s -> unit t
|
||||||
|
= fun st' -> fun k -> fun st -> k () st'
|
||||||
|
|
||||||
|
let run : (unit -> R.ans t) -> s -> R.ans * s =
|
||||||
|
fun m st -> m () (fun x -> fun st -> (x, st)) st
|
||||||
|
end
|
||||||
|
|
||||||
|
module ContinuationIntStateMonad
|
||||||
|
= ContinuationStateMonad(struct type s = int end)(struct type ans = bool end)
|
||||||
|
|
||||||
|
(** Free monad **)
|
||||||
|
module type FUNCTOR = sig
|
||||||
|
type 'a t
|
||||||
|
val fmap : ('a -> 'b) -> 'a t -> 'b t
|
||||||
|
end
|
||||||
|
|
||||||
|
module type FREE_MONAD = sig
|
||||||
|
type 'a op
|
||||||
|
type 'a free = Return of 'a
|
||||||
|
| Op of 'a free op
|
||||||
|
|
||||||
|
include MONAD with type 'a t = 'a free
|
||||||
|
|
||||||
|
val do' : 'a op -> 'a free
|
||||||
|
end
|
||||||
|
|
||||||
|
module FreeMonad(F : FUNCTOR) : sig
|
||||||
|
include FREE_MONAD with type 'a op = 'a F.t
|
||||||
|
end = struct
|
||||||
|
type 'a op = 'a F.t
|
||||||
|
type 'a free = Return of 'a
|
||||||
|
| Op of 'a free F.t
|
||||||
|
|
||||||
|
type 'a t = 'a free
|
||||||
|
|
||||||
|
let return : 'a -> 'a t
|
||||||
|
= fun x -> Return x
|
||||||
|
|
||||||
|
let rec (>>=) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
|
= fun m k ->
|
||||||
|
match m with
|
||||||
|
| Return x -> k x
|
||||||
|
| Op y -> Op (F.fmap (fun m' -> m' >>= k) y)
|
||||||
|
|
||||||
|
let do' : 'a F.t -> 'a free
|
||||||
|
= fun op -> Op (F.fmap (fun x -> Return x) op)
|
||||||
|
end
|
||||||
|
|
||||||
|
module type FREE_STATE = sig
|
||||||
|
type s
|
||||||
|
type 'r opsig = Get of (s -> 'r)
|
||||||
|
| Put of s * (unit -> 'r)
|
||||||
|
include FUNCTOR with type 'r t = 'r opsig
|
||||||
|
end
|
||||||
|
|
||||||
|
module FreeState(S : sig type s end) = struct
|
||||||
|
type s = S.s
|
||||||
|
type 'r opsig = Get of (s -> 'r)
|
||||||
|
| Put of s * (unit -> 'r)
|
||||||
|
type 'r t = 'r opsig
|
||||||
|
|
||||||
|
let fmap : ('a -> 'b) -> 'a t -> 'b t
|
||||||
|
= fun f op ->
|
||||||
|
match op with
|
||||||
|
| Get k -> Get (fun st -> f (k st))
|
||||||
|
| Put (st', k) -> Put (st', fun st -> f (k ()))
|
||||||
|
end
|
||||||
|
|
||||||
|
module FreeIntStateMonad: sig
|
||||||
|
include STATE_MONAD with type s = int
|
||||||
|
and type ans = bool
|
||||||
|
end = struct
|
||||||
|
|
||||||
|
module rec FreeIntState : FREE_STATE with type s = int
|
||||||
|
= FreeState(struct type s = int end)
|
||||||
|
and FreeIntStateMonad : FREE_MONAD with type 'r op = 'r FreeIntState.opsig
|
||||||
|
= FreeMonad(FreeIntState)
|
||||||
|
|
||||||
|
open FreeIntState
|
||||||
|
include FreeIntStateMonad
|
||||||
|
|
||||||
|
type s = int
|
||||||
|
type ans = bool
|
||||||
|
|
||||||
|
let get : unit -> s t
|
||||||
|
= fun () -> do' (Get (fun st -> st))
|
||||||
|
|
||||||
|
let put : s -> unit t
|
||||||
|
= fun st -> do' (Put (st, fun () -> ()))
|
||||||
|
|
||||||
|
let rec run : (unit -> ans t) -> s -> ans * s
|
||||||
|
= fun m st ->
|
||||||
|
match m () with
|
||||||
|
| Return x -> (x, st)
|
||||||
|
| Op (Get k) -> run (fun () -> k st) st
|
||||||
|
| Op (Put (st', k)) -> run k st'
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Monadic reflection **)
|
||||||
|
module Reflect
|
||||||
|
(M : MONAD)
|
||||||
|
(R : sig type ans end): sig
|
||||||
|
type ans = R.ans
|
||||||
|
|
||||||
|
val reify : (unit -> ans) -> ans M.t
|
||||||
|
val reflect : 'a M.t -> 'a
|
||||||
|
|
||||||
|
end = struct
|
||||||
|
type ans = R.ans
|
||||||
|
effect Reflect : 'a M.t -> 'a
|
||||||
|
|
||||||
|
let reify : (unit -> ans) -> ans M.t
|
||||||
|
= fun f ->
|
||||||
|
let open M in
|
||||||
|
match f () with
|
||||||
|
| x -> return x
|
||||||
|
| effect (Reflect m) k -> m >>= (continue k)
|
||||||
|
|
||||||
|
let reflect : 'a M.t -> 'a
|
||||||
|
= fun m ->
|
||||||
|
perform (Reflect m)
|
||||||
|
end
|
||||||
|
|
||||||
|
module ReflectIntStateMonad
|
||||||
|
= Reflect(IntStateMonad)(struct type ans = bool end)
|
||||||
|
|
||||||
|
module ReflectIntState = struct
|
||||||
|
open ReflectIntStateMonad
|
||||||
|
|
||||||
|
let get : unit -> int
|
||||||
|
= fun () -> reflect (IntStateMonad.get ())
|
||||||
|
|
||||||
|
let put : int -> unit
|
||||||
|
= fun st -> reflect (IntStateMonad.put st)
|
||||||
|
|
||||||
|
let run : (unit -> bool) -> int -> bool * int
|
||||||
|
= fun m st -> IntStateMonad.run (fun () -> reify m) st
|
||||||
|
end
|
||||||
|
|
||||||
|
(* Generic monadic incr_even *)
|
||||||
|
module MonadExample(T : STATE_MONAD with type s = int) = struct
|
||||||
|
let incr_even : unit -> bool T.t
|
||||||
|
= fun () ->
|
||||||
|
let open T in
|
||||||
|
(get ()) >>= (fun st -> put (1 + st)
|
||||||
|
>>= (fun () -> return (even st)))
|
||||||
|
end
|
||||||
|
|
||||||
|
(** Effect handlers **)
|
||||||
|
module type STATE_HANDLER = sig
|
||||||
|
type s
|
||||||
|
|
||||||
|
val get : unit -> s
|
||||||
|
val put : s -> unit
|
||||||
|
val run : (unit -> 'a) -> s -> 'a * s
|
||||||
|
end
|
||||||
|
|
||||||
|
module StateHandler(S : sig type s end) : STATE_HANDLER with type s = S.s = struct
|
||||||
|
type s = S.s
|
||||||
|
|
||||||
|
effect Put : s -> unit
|
||||||
|
let put st = perform (Put st)
|
||||||
|
|
||||||
|
effect Get : unit -> s
|
||||||
|
let get () = perform (Get ())
|
||||||
|
|
||||||
|
let run
|
||||||
|
= fun m st ->
|
||||||
|
let f = match m () with
|
||||||
|
| x -> (fun st -> (x, st))
|
||||||
|
| effect (Put st') k -> (fun st -> continue k () st')
|
||||||
|
| effect (Get ()) k -> (fun st -> continue k st st)
|
||||||
|
in f st
|
||||||
|
end
|
||||||
|
|
||||||
|
module IntStateHandler = StateHandler(struct type s = int end)
|
||||||
|
|
||||||
|
let run_examples () =
|
||||||
|
let examples = [
|
||||||
|
"builtin", (fun st ->
|
||||||
|
let st = ref st in let v = !st in st := 1 + v; (even v, !st));
|
||||||
|
"pure state passing", (fun st -> (even st, 1 + st));
|
||||||
|
"shift/reset", (fun st ->
|
||||||
|
CtrlIntState.run (incr_even CtrlIntState.(get, put)) st);
|
||||||
|
"state monad", (fun st ->
|
||||||
|
let module MonadStateExample = MonadExample(IntStateMonad) in
|
||||||
|
IntStateMonad.run MonadStateExample.incr_even st);
|
||||||
|
"continuation monad", (fun st ->
|
||||||
|
let module ContinuationMonadExample = MonadExample(ContinuationIntStateMonad) in
|
||||||
|
ContinuationIntStateMonad.run ContinuationMonadExample.incr_even st);
|
||||||
|
"free monad", (fun st ->
|
||||||
|
let module FreeMonadExample = MonadExample(FreeIntStateMonad) in
|
||||||
|
FreeIntStateMonad.run FreeMonadExample.incr_even st);
|
||||||
|
"monadic reflection", (fun st ->
|
||||||
|
ReflectIntState.run (incr_even ReflectIntState.(get, put)) st);
|
||||||
|
"state handler", (fun st ->
|
||||||
|
IntStateHandler.run (incr_even IntStateHandler.(get, put)) st) ]
|
||||||
|
in
|
||||||
|
List.map (fun (s, f) -> (s, f 4)) examples
|
||||||
|
(* module IntStateMRefl : MREFL with type ans := bool and type 'a t = 'a IntState.t
|
||||||
|
* = MRefl(struct type ans = bool end)(IntState)
|
||||||
|
*
|
||||||
|
* let get () = IntStateMRefl.reflect (IntState.get ())
|
||||||
|
* let put st = IntStateMRefl.reflect (IntState.put st)
|
||||||
|
* let run m st = IntState.run (IntStateMRefl.reify m) st
|
||||||
|
*
|
||||||
|
* let even : int -> bool
|
||||||
|
* = fun n -> n mod 2 = 0
|
||||||
|
*
|
||||||
|
* let incr_even : unit -> bool
|
||||||
|
* = fun () ->
|
||||||
|
* let st = get () in
|
||||||
|
* put (1 + st);
|
||||||
|
* even st *)
|
||||||
1352
code/unix-huawei2022.links
Normal file
1352
code/unix-huawei2022.links
Normal file
File diff suppressed because it is too large
Load Diff
1372
code/unix-msr2022.links
Normal file
1372
code/unix-msr2022.links
Normal file
File diff suppressed because it is too large
Load Diff
1352
code/unix-nuprl2022.links
Normal file
1352
code/unix-nuprl2022.links
Normal file
File diff suppressed because it is too large
Load Diff
1393
code/unix-tutorial.links
Normal file
1393
code/unix-tutorial.links
Normal file
File diff suppressed because it is too large
Load Diff
344
code/unix.links
344
code/unix.links
@@ -45,8 +45,6 @@ module Queue {
|
|||||||
fun singleton(x) { enqueue(x, empty) }
|
fun singleton(x) { enqueue(x, empty) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## Environment
|
## Environment
|
||||||
##
|
##
|
||||||
@@ -106,6 +104,27 @@ fun usermgr(user, envs, m) {
|
|||||||
## Basic IO
|
## Basic IO
|
||||||
##
|
##
|
||||||
typename FileDescr = Int;
|
typename FileDescr = Int;
|
||||||
|
typename FileCursor = Int;
|
||||||
|
|
||||||
|
module File {
|
||||||
|
typename T = [String];
|
||||||
|
|
||||||
|
sig empty : T
|
||||||
|
var empty = [];
|
||||||
|
|
||||||
|
sig read : (FileCursor, T) ~> Option(String)
|
||||||
|
fun read(start, file) {
|
||||||
|
switch (drop(start, file)) {
|
||||||
|
case [] -> None
|
||||||
|
case x :: _ -> Some(x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sig write : (String, FileCursor, T) ~> T
|
||||||
|
fun write(contents, fptr, file) {
|
||||||
|
take(fptr, file) ++ [contents] ++ drop(fptr, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sig stdout : FileDescr
|
sig stdout : FileDescr
|
||||||
var stdout = 1;
|
var stdout = 1;
|
||||||
@@ -113,7 +132,7 @@ var stdout = 1;
|
|||||||
sig puts : (FileDescr,String) {Puts:(FileDescr,String) -> () |_}-> ()
|
sig puts : (FileDescr,String) {Puts:(FileDescr,String) -> () |_}-> ()
|
||||||
fun puts(fd, s) { do Puts(fd, s) }
|
fun puts(fd, s) { do Puts(fd, s) }
|
||||||
|
|
||||||
sig basicIO : (Comp(a, {Puts:(FileDescr,String) -> () |e})) {Puts{_} |e}~> [String]
|
sig basicIO : (Comp(a, {Puts:(FileDescr,String) -> () |e})) {Puts{_} |e}~> File.T
|
||||||
fun basicIO(m) {
|
fun basicIO(m) {
|
||||||
handle(m()) {
|
handle(m()) {
|
||||||
case Return(_) -> []
|
case Return(_) -> []
|
||||||
@@ -121,8 +140,6 @@ fun basicIO(m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# TODO: implement file space.
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## Generic state handling.
|
## Generic state handling.
|
||||||
##
|
##
|
||||||
@@ -153,118 +170,125 @@ var stderr = 2;
|
|||||||
sig eof : String
|
sig eof : String
|
||||||
var eof = "\x00";
|
var eof = "\x00";
|
||||||
|
|
||||||
sig gets : (FileDescr) {Gets:(FileDescr) -> String |_}-> String
|
typename Mode = [|Read|Write|];
|
||||||
fun gets(fd) { do Gets(fd) }
|
|
||||||
|
|
||||||
typename Mode = [|Create|Append|];
|
typename FileDescr = Int;
|
||||||
|
typename INode = (loc:Option(Int),refc:Int);
|
||||||
|
|
||||||
sig fopen : (Mode, String) {Fopen:(Mode, String) -> FileDescr |_}-> FileDescr
|
typename INodeTable = [(INode, File.T)];
|
||||||
fun fopen(mode, filename) { do Fopen(mode, filename) }
|
typename FileTable = [(Mode, INode)];
|
||||||
|
typename
|
||||||
|
|
||||||
sig fclose : (FileDescr) {Fclose:(FileDescr) -> () |_}-> ()
|
# sig gets : (FileDescr) {Gets:(FileDescr) -> String |_}-> String
|
||||||
fun fclose(fd) { do Fclose(fd) }
|
# fun gets(fd) { do Gets(fd) }
|
||||||
|
|
||||||
typename File = Queue.T(String);
|
# sig fopen : (Mode, String) {Fopen:(Mode, String) -> FileDescr |_}-> FileDescr
|
||||||
|
# fun fopen(mode, filename) { do Fopen(mode, filename) }
|
||||||
|
|
||||||
sig emptyFile : File
|
# sig fclose : (FileDescr) {Fclose:(FileDescr) -> () |_}-> ()
|
||||||
var emptyFile = Queue.empty;
|
# fun fclose(fd) { do Fclose(fd) }
|
||||||
|
|
||||||
sig writeFile : (String, File) -> File
|
# typename File = Queue.T(String);
|
||||||
fun writeFile(s, file) { Queue.enqueue(s, file) }
|
|
||||||
|
|
||||||
sig readFile : (File) ~> (String, File)
|
# sig emptyFile : File
|
||||||
fun readFile(file) {
|
# var emptyFile = Queue.empty;
|
||||||
switch (Queue.dequeue(file)) {
|
|
||||||
case (None, file) -> (eof, file)
|
|
||||||
case (Some(s), file) -> (s, file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typename FileTable = [(FileDescr, File)];
|
# sig writeFile : (String, File) -> File
|
||||||
typename FileStore = [(String, FileDescr)];
|
# fun writeFile(s, file) { Queue.enqueue(s, file) }
|
||||||
typename FileSystem = (next:Int,ft:FileTable,fs:FileStore);
|
|
||||||
|
|
||||||
sig defaultFileSystem : () -> FileSystem
|
# sig readFile : (File) ~> (String, File)
|
||||||
fun defaultFileSystem() {
|
# fun readFile(file) {
|
||||||
var defaultTable = [ (stdin , emptyFile)
|
# switch (Queue.dequeue(file)) {
|
||||||
, (stdout, emptyFile)
|
# case (None, file) -> (eof, file)
|
||||||
, (stderr, emptyFile) ];
|
# case (Some(s), file) -> (s, file)
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
var defaultStore = [ ("stdin" , stdin)
|
# typename FileTable = [(FileDescr, File)];
|
||||||
, ("stdout", stdout)
|
# typename FileStore = [(String, FileDescr)];
|
||||||
, ("stderr", stderr) ];
|
# typename FileSystem = (next:Int,ft:FileTable,fs:FileStore);
|
||||||
|
|
||||||
(next=3,ft=defaultTable,fs=defaultStore)
|
# sig defaultFileSystem : () -> FileSystem
|
||||||
}
|
# fun defaultFileSystem() {
|
||||||
|
# var defaultTable = [ (stdin , emptyFile)
|
||||||
|
# , (stdout, emptyFile)
|
||||||
|
# , (stderr, emptyFile) ];
|
||||||
|
|
||||||
sig lookupFile : (FileDescr, FileSystem) ~> File
|
# var defaultStore = [ ("stdin" , stdin)
|
||||||
fun lookupFile(fd, fsys) {
|
# , ("stdout", stdout)
|
||||||
switch (lookup(fd, fsys.ft)) {
|
# , ("stderr", stderr) ];
|
||||||
case Nothing -> error("err: No such file(" ^^ intToString(fd) ^^ ")")
|
|
||||||
case Just(file) -> file
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sig replaceFile : (FileDescr, File, FileSystem) ~> FileSystem
|
# (next=3,ft=defaultTable,fs=defaultStore)
|
||||||
fun replaceFile(fd, file, fsys) {
|
# }
|
||||||
var ft = modify(fd, file, fsys.ft);
|
|
||||||
(fsys with ft = ft) # TODO handle nonexistent file.
|
|
||||||
}
|
|
||||||
|
|
||||||
sig createFile : (String, FileSystem) -> (FileDescr, FileSystem)
|
# sig lookupFile : (FileDescr, FileSystem) ~> File
|
||||||
fun createFile(filename, fsys) {
|
# fun lookupFile(fd, fsys) {
|
||||||
var fd = fsys.next;
|
# switch (lookup(fd, fsys.ft)) {
|
||||||
(fd, (next = fd + 1, fs = (filename, fd) :: fsys.fs, ft = (fd, emptyFile) :: fsys.ft))
|
# case Nothing -> error("err: No such file(" ^^ intToString(fd) ^^ ")")
|
||||||
}
|
# case Just(file) -> file
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
sig openFile : (Mode, String, FileSystem) ~> (FileDescr, FileSystem)
|
# sig replaceFile : (FileDescr, File, FileSystem) ~> FileSystem
|
||||||
fun openFile(mode, filename, fsys) {
|
# fun replaceFile(fd, file, fsys) {
|
||||||
var (fd, fsys') = switch (lookup(filename, fsys.fs)) {
|
# var ft = modify(fd, file, fsys.ft);
|
||||||
case Nothing -> createFile(filename, fsys)
|
# (fsys with ft = ft) # TODO handle nonexistent file.
|
||||||
case Just(fd) -> (fd, fsys)
|
# }
|
||||||
};
|
|
||||||
switch (mode) {
|
|
||||||
case Create -> error("erase")
|
|
||||||
case Append -> (fd, fsys')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sig closeFile : (File) ~> File
|
# sig createFile : (String, FileSystem) -> (FileDescr, FileSystem)
|
||||||
fun closeFile((=front,=rear)) {
|
# fun createFile(filename, fsys) {
|
||||||
(front=front ++ reverse(rear), rear=[])
|
# var fd = fsys.next;
|
||||||
}
|
# (fd, (next = fd + 1, fs = (filename, fd) :: fsys.fs, ft = (fd, emptyFile) :: fsys.ft))
|
||||||
|
# }
|
||||||
|
|
||||||
sig allowState : (() {Get-,Put- |e}~> a) -> () {Get:s,Put:(s) -> () |e}~> a
|
# sig openFile : (Mode, String, FileSystem) ~> (FileDescr, FileSystem)
|
||||||
fun allowState(f) { (f : (() {Get:s,Put:(s) -> () |e}~> a) <- (() {Get-,Put- |e}~> a)) }
|
# fun openFile(mode, filename, fsys) {
|
||||||
|
# var (fd, fsys') = switch (lookup(filename, fsys.fs)) {
|
||||||
|
# case Nothing -> createFile(filename, fsys)
|
||||||
|
# case Just(fd) -> (fd, fsys)
|
||||||
|
# };
|
||||||
|
# switch (mode) {
|
||||||
|
# case Create -> error("erase")
|
||||||
|
# case Append -> (fd, fsys')
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
sig fileIO : (Comp(a, {Get-,Put-,Gets:(FileDescr) -> String,Puts:(FileDescr,String) -> (),Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr |e})) {Get:() {}-> FileSystem,Put:(FileSystem) -> (),Gets{_},Puts{_},Fclose{_},Fopen{_} |e}~> a
|
# sig closeFile : (File) ~> File
|
||||||
fun fileIO(m) {
|
# fun closeFile((=front,=rear)) {
|
||||||
handle(allowState(m)()) {
|
# (front=front ++ reverse(rear), rear=[])
|
||||||
case Gets(fd, resume) ->
|
# }
|
||||||
var fsys = get();
|
|
||||||
var (ch, file) = readFile(lookupFile(fd, fsys));
|
|
||||||
put(replaceFile(fd, file, fsys)); resume(ch)
|
|
||||||
case Puts(fd, ch, resume) ->
|
|
||||||
var fsys = get();
|
|
||||||
var fsys' = replaceFile(fd, writeFile(ch, lookupFile(fd, fsys)), fsys);
|
|
||||||
put(fsys'); resume(())
|
|
||||||
case Fopen(mode, filename, resume) ->
|
|
||||||
var fsys = get();
|
|
||||||
var (fd, fsys') = openFile(mode, filename, fsys);
|
|
||||||
put(fsys'); resume(fd)
|
|
||||||
case Fclose(fd, resume) ->
|
|
||||||
var fsys = get();
|
|
||||||
var fsys' = replaceFile(fd, closeFile(lookupFile(fd, fsys)), fsys);
|
|
||||||
put(fsys'); resume(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sig redirect : (Comp(a, {Puts:(FileDescr,String) -> () |e}), FileDescr) {Puts:(FileDescr,String) -> () |e}~> a
|
# sig allowState : (() {Get-,Put- |e}~> a) -> () {Get:s,Put:(s) -> () |e}~> a
|
||||||
fun redirect(m, fd) {
|
# fun allowState(f) { (f : (() {Get:s,Put:(s) -> () |e}~> a) <- (() {Get-,Put- |e}~> a)) }
|
||||||
handle(m()) {
|
|
||||||
case Puts(_,s,resume) -> resume(puts(fd, s))
|
# sig fileIO : (Comp(a, {Get-,Put-,Gets:(FileDescr) -> String,Puts:(FileDescr,String) -> (),Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr |e})) {Get:() {}-> FileSystem,Put:(FileSystem) -> (),Gets{_},Puts{_},Fclose{_},Fopen{_} |e}~> a
|
||||||
}
|
# fun fileIO(m) {
|
||||||
}
|
# handle(allowState(m)()) {
|
||||||
|
# case Gets(fd, resume) ->
|
||||||
|
# var fsys = get();
|
||||||
|
# var (ch, file) = readFile(lookupFile(fd, fsys));
|
||||||
|
# put(replaceFile(fd, file, fsys)); resume(ch)
|
||||||
|
# case Puts(fd, ch, resume) ->
|
||||||
|
# var fsys = get();
|
||||||
|
# var fsys' = replaceFile(fd, writeFile(ch, lookupFile(fd, fsys)), fsys);
|
||||||
|
# put(fsys'); resume(())
|
||||||
|
# case Fopen(mode, filename, resume) ->
|
||||||
|
# var fsys = get();
|
||||||
|
# var (fd, fsys') = openFile(mode, filename, fsys);
|
||||||
|
# put(fsys'); resume(fd)
|
||||||
|
# case Fclose(fd, resume) ->
|
||||||
|
# var fsys = get();
|
||||||
|
# var fsys' = replaceFile(fd, closeFile(lookupFile(fd, fsys)), fsys);
|
||||||
|
# put(fsys'); resume(())
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
# sig redirect : (Comp(a, {Puts:(FileDescr,String) -> () |e}), FileDescr) {Puts:(FileDescr,String) -> () |e}~> a
|
||||||
|
# fun redirect(m, fd) {
|
||||||
|
# handle(m()) {
|
||||||
|
# case Puts(_,s,resume) -> resume(puts(fd, s))
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
##
|
##
|
||||||
## Processes
|
## Processes
|
||||||
@@ -331,70 +355,70 @@ fun whoami() { getenv("USER") }
|
|||||||
##
|
##
|
||||||
|
|
||||||
# Tags puts with the name of the current user.
|
# Tags puts with the name of the current user.
|
||||||
sig provenance : (Comp(a, {Getenv:(String) -> String,Puts:(FileDescr,String) -> () |e})) {Getenv:(String) -> String,Puts:(FileDescr,String) -> () |e}~> a
|
# sig provenance : (Comp(a, {Getenv:(String) -> String,Puts:(FileDescr,String) -> () |e})) {Getenv:(String) -> String,Puts:(FileDescr,String) -> () |e}~> a
|
||||||
fun provenance(m) {
|
# fun provenance(m) {
|
||||||
handle(m()) {
|
# handle(m()) {
|
||||||
case Puts(fd, s, resume) ->
|
# case Puts(fd, s, resume) ->
|
||||||
var user = whoami();
|
# var user = whoami();
|
||||||
resume(do Puts(fd, user ^^ "> " ^^ s))
|
# resume(do Puts(fd, user ^^ "> " ^^ s))
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
|
|
||||||
# An example of everything plugged together: a time-shared 'Hello World'.
|
# # An example of everything plugged together: a time-shared 'Hello World'.
|
||||||
sig example : () {Fork:Bool,Getenv:(String) -> String,Su:(User) -> (),Puts:(FileDescr,String) -> (),Yield:() |_}~> ()
|
# sig example : () {Fork:Bool,Getenv:(String) -> String,Su:(User) -> (),Puts:(FileDescr,String) -> (),Yield:() |_}~> ()
|
||||||
fun example() {
|
# fun example() {
|
||||||
var pid = fork();
|
# var pid = fork();
|
||||||
var () = {
|
# var () = {
|
||||||
if (pid) redirect(fun(){puts(stdout, "dummy")}, stderr)
|
# if (pid) redirect(fun(){puts(stdout, "dummy")}, stderr)
|
||||||
else if (fork()) su(Alice)
|
# else if (fork()) su(Alice)
|
||||||
else su(Bob)
|
# else su(Bob)
|
||||||
};
|
# };
|
||||||
var user = whoami();
|
# var user = whoami();
|
||||||
puts(stdout, "Hello World!");
|
# puts(stdout, "Hello World!");
|
||||||
var uid = getenv("UID");
|
# var uid = getenv("UID");
|
||||||
echo("My UID is " ^^ uid);
|
# echo("My UID is " ^^ uid);
|
||||||
(if (amiroot()) { yield(); echo(user ^^ " is running as root.") } else ());
|
# (if (amiroot()) { yield(); echo(user ^^ " is running as root.") } else ());
|
||||||
echo("My home dir is /home/" ^^ user)
|
# echo("My home dir is /home/" ^^ user)
|
||||||
}
|
# }
|
||||||
|
|
||||||
# Wiring of handlers.
|
# # Wiring of handlers.
|
||||||
sig init : () {Fork{_},Getenv{_},Su{_},Puts{_},Yield{_} |_}~> [String]
|
# sig init : () {Fork{_},Getenv{_},Su{_},Puts{_},Yield{_} |_}~> [String]
|
||||||
fun init() {
|
# fun init() {
|
||||||
basicIO(fun() {
|
# basicIO(fun() {
|
||||||
schedule(fun() {
|
# schedule(fun() {
|
||||||
usermgr(Root, envs, fun() {
|
# usermgr(Root, envs, fun() {
|
||||||
provenance(example)
|
# provenance(example)
|
||||||
})
|
# })
|
||||||
})
|
# })
|
||||||
})
|
# })
|
||||||
}
|
# }
|
||||||
|
|
||||||
sig example' : () {Fork:Bool,Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr,Getenv:(String) -> String,Su:(User) -> (),Puts:(FileDescr,String) -> (),Yield:() |_}~> ()
|
# sig example' : () {Fork:Bool,Fclose:(FileDescr) -> (),Fopen:(Mode,String) -> FileDescr,Getenv:(String) -> String,Su:(User) -> (),Puts:(FileDescr,String) -> (),Yield:() |_}~> ()
|
||||||
fun example'() {
|
# fun example'() {
|
||||||
var pid = fork();
|
# var pid = fork();
|
||||||
var () = {
|
# var () = {
|
||||||
if (pid) redirect(fun(){puts(stdout, "dummy")}, stderr)
|
# if (pid) redirect(fun(){puts(stdout, "dummy")}, stderr)
|
||||||
else if (fork()) su(Alice)
|
# else if (fork()) su(Alice)
|
||||||
else su(Bob)
|
# else su(Bob)
|
||||||
};
|
# };
|
||||||
var user = whoami();
|
# var user = whoami();
|
||||||
var fd = fopen(Append, user ^^ ".txt");
|
# var fd = fopen(Append, user ^^ ".txt");
|
||||||
puts(fd, "Hello World!");
|
# puts(fd, "Hello World!");
|
||||||
var uid = getenv("UID");
|
# var uid = getenv("UID");
|
||||||
echo("My UID is " ^^ uid);
|
# echo("My UID is " ^^ uid);
|
||||||
(if (amiroot()) { yield(); echo(user ^^ " is running as root.") } else ());
|
# (if (amiroot()) { yield(); echo(user ^^ " is running as root.") } else ());
|
||||||
echo("My home dir is /home/" ^^ user);
|
# echo("My home dir is /home/" ^^ user);
|
||||||
fclose(fd)
|
# fclose(fd)
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
|
||||||
sig init' : (FileSystem) {Fclose{_},Fopen{_},Fork{_},Get{_},Getenv{_},Gets{_},Put{_},Puts{_},Su{_},Yield{_}|_}~> ((), FileSystem)
|
# sig init' : (FileSystem) {Fclose{_},Fopen{_},Fork{_},Get{_},Getenv{_},Gets{_},Put{_},Puts{_},Su{_},Yield{_}|_}~> ((), FileSystem)
|
||||||
fun init'(fsys) {
|
# fun init'(fsys) {
|
||||||
runState(fsys, fun() {
|
# runState(fsys, fun() {
|
||||||
fileIO(fun() {
|
# fileIO(fun() {
|
||||||
schedule(fun() {
|
# schedule(fun() {
|
||||||
usermgr(Root, envs, example')
|
# usermgr(Root, envs, example')
|
||||||
})
|
# })
|
||||||
})
|
# })
|
||||||
})
|
# })
|
||||||
}
|
# }
|
||||||
|
|||||||
@@ -680,3 +680,18 @@ fun tcphandshakeFail() {
|
|||||||
performTCP(tcpserver, 84, sfd, cfd)
|
performTCP(tcpserver, 84, sfd, cfd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Grep
|
||||||
|
#
|
||||||
|
#sig grep : (String) {Await:Char,Yield:(Char) -> () |_}~> ()
|
||||||
|
fun grep(str) {
|
||||||
|
var cs = explode(str);
|
||||||
|
fun match(c,cs) {
|
||||||
|
switch (cs) {
|
||||||
|
case c' :: cs' ->
|
||||||
|
if (c == '\n') fail()
|
||||||
|
if (c == c')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
357
macros.tex
357
macros.tex
@@ -4,12 +4,14 @@
|
|||||||
\newcommand{\defas}[0]{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\text{def}}}}{=}}}
|
\newcommand{\defas}[0]{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\text{def}}}}{=}}}
|
||||||
\newcommand{\defnas}[0]{\mathrel{:=}}
|
\newcommand{\defnas}[0]{\mathrel{:=}}
|
||||||
\newcommand{\simdefas}[0]{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\text{def}}}}{\simeq}}}
|
\newcommand{\simdefas}[0]{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny\text{def}}}}{\simeq}}}
|
||||||
|
\newcommand{\adef}[0]{\mathrel{\overset{\makebox[0pt]{\mbox{\normalfont\tiny{\text{$\alpha$-def}}}}}{\simeq}}}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Some useful maths abbreviations
|
%% Some useful maths abbreviations
|
||||||
%%
|
%%
|
||||||
\newcommand{\C}{\ensuremath{\mathbb{C}}}
|
\newcommand{\C}{\ensuremath{\mathbb{C}}}
|
||||||
\newcommand{\N}{\ensuremath{\mathbb{N}}}
|
\newcommand{\N}{\ensuremath{\mathbb{N}}}
|
||||||
|
\newcommand{\R}{\ensuremath{\mathbb{R}}}
|
||||||
\newcommand{\Z}{\ensuremath{\mathbb{Z}}}
|
\newcommand{\Z}{\ensuremath{\mathbb{Z}}}
|
||||||
\newcommand{\B}{\ensuremath{\mathbb{B}}}
|
\newcommand{\B}{\ensuremath{\mathbb{B}}}
|
||||||
\newcommand{\BB}[1]{\ensuremath{\mathbf{#1}}}
|
\newcommand{\BB}[1]{\ensuremath{\mathbf{#1}}}
|
||||||
@@ -17,6 +19,12 @@
|
|||||||
% \newcommand{\Delim}[1]{\ensuremath{\langle\!\!\mkern-1.5mu\langle#1\rangle\!\!\mkern-1.5mu\rangle}}
|
% \newcommand{\Delim}[1]{\ensuremath{\langle\!\!\mkern-1.5mu\langle#1\rangle\!\!\mkern-1.5mu\rangle}}
|
||||||
\newcommand{\Delim}[1]{\ensuremath{\keyw{del}.#1}}
|
\newcommand{\Delim}[1]{\ensuremath{\keyw{del}.#1}}
|
||||||
\newcommand{\sembr}[1]{\ensuremath{\llbracket #1 \rrbracket}}
|
\newcommand{\sembr}[1]{\ensuremath{\llbracket #1 \rrbracket}}
|
||||||
|
\newcommand{\BigO}{\ensuremath{\mathcal{O}}}
|
||||||
|
\newcommand{\SC}{\ensuremath{\mathsf{S}}}
|
||||||
|
\newcommand{\ST}{\ensuremath{\mathsf{T}}}
|
||||||
|
\newcommand{\ar}{\ensuremath{\mathsf{ar}}}
|
||||||
|
\newcommand{\Tm}{\ensuremath{\mathsf{Tm}}}
|
||||||
|
\newcommand{\Ty}{\ensuremath{\mathsf{Ty}}}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Partiality
|
%% Partiality
|
||||||
@@ -42,6 +50,8 @@
|
|||||||
\newcommand{\UCalc}{\ensuremath{\lambda_{\mathsf{u}}}\xspace}
|
\newcommand{\UCalc}{\ensuremath{\lambda_{\mathsf{u}}}\xspace}
|
||||||
\newcommand{\param}{\ensuremath{\ddagger}}
|
\newcommand{\param}{\ensuremath{\ddagger}}
|
||||||
\newcommand{\HPCalc}{\ensuremath{\lambda_{\mathsf{h^\param}}}\xspace}
|
\newcommand{\HPCalc}{\ensuremath{\lambda_{\mathsf{h^\param}}}\xspace}
|
||||||
|
\newcommand{\HPCF}{\ensuremath{\lambda^\rightarrow_{\mathsf{h}}}\xspace}
|
||||||
|
\newcommand{\BPCF}{\ensuremath{\lambda^\rightarrow_{\mathsf{b}}}\xspace}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Calculi terms and types type-setting.
|
%% Calculi terms and types type-setting.
|
||||||
@@ -74,6 +84,8 @@
|
|||||||
\newcommand{\Inl}{\keyw{inl}}
|
\newcommand{\Inl}{\keyw{inl}}
|
||||||
\newcommand{\Inr}{\keyw{inr}}
|
\newcommand{\Inr}{\keyw{inr}}
|
||||||
\newcommand{\Thunk}{\lambda \Unit.}
|
\newcommand{\Thunk}{\lambda \Unit.}
|
||||||
|
\newcommand{\PCFRef}{\dec{Ref}}
|
||||||
|
\newcommand{\refv}{\keyw{ref}}
|
||||||
|
|
||||||
\newcommand{\Pre}[1]{\mathsf{Pre}(#1)}
|
\newcommand{\Pre}[1]{\mathsf{Pre}(#1)}
|
||||||
\newcommand{\Abs}{\mathsf{Abs}}
|
\newcommand{\Abs}{\mathsf{Abs}}
|
||||||
@@ -133,6 +145,10 @@
|
|||||||
|
|
||||||
\newcommand{\Res}{\keyw{res}}
|
\newcommand{\Res}{\keyw{res}}
|
||||||
|
|
||||||
|
\newcommand{\Cong}{\mathrm{cong}}
|
||||||
|
|
||||||
|
\newcommand{\AlgTheory}{\ensuremath{\mathcal{T}}}
|
||||||
|
|
||||||
%% Handler projections.
|
%% Handler projections.
|
||||||
\newcommand{\mret}{\mathrm{ret}}
|
\newcommand{\mret}{\mathrm{ret}}
|
||||||
\newcommand{\mops}{\mathrm{ops}}
|
\newcommand{\mops}{\mathrm{ops}}
|
||||||
@@ -141,6 +157,7 @@
|
|||||||
\newcommand{\hops}{H^{\mops}}
|
\newcommand{\hops}{H^{\mops}}
|
||||||
%\newcommand{\hex}{H^{\mathrm{ex}}}
|
%\newcommand{\hex}{H^{\mathrm{ex}}}
|
||||||
\newcommand{\hell}{H^{\ell}}
|
\newcommand{\hell}{H^{\ell}}
|
||||||
|
\newcommand{\gell}{\theta^{\ell}}
|
||||||
|
|
||||||
\newcommand{\depth}{\delta}
|
\newcommand{\depth}{\delta}
|
||||||
|
|
||||||
@@ -189,6 +206,14 @@
|
|||||||
\newcommand{\EvalCat}{\CatName{Cont}}
|
\newcommand{\EvalCat}{\CatName{Cont}}
|
||||||
\newcommand{\UEvalCat}{\CatName{UCont}}
|
\newcommand{\UEvalCat}{\CatName{UCont}}
|
||||||
\newcommand{\HandlerCat}{\CatName{HDef}}
|
\newcommand{\HandlerCat}{\CatName{HDef}}
|
||||||
|
\newcommand{\MConfCat}{\CatName{Conf}}
|
||||||
|
\newcommand{\MEnvCat}{\CatName{Env}}
|
||||||
|
\newcommand{\MValCat}{\CatName{Mval}}
|
||||||
|
\newcommand{\MGContCat}{\CatName{GenCont}}
|
||||||
|
\newcommand{\MGFrameCat}{\CatName{GenFrame}}
|
||||||
|
\newcommand{\MPContCat}{\CatName{PureCont}}
|
||||||
|
\newcommand{\MPFrameCat}{\CatName{PureFrame}}
|
||||||
|
\newcommand{\MHCloCat}{\CatName{HClo}}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Lindley's array stuff.
|
%% Lindley's array stuff.
|
||||||
@@ -223,6 +248,7 @@
|
|||||||
|
|
||||||
\newcommand{\concat}{\mathbin{+\!\!+}}
|
\newcommand{\concat}{\mathbin{+\!\!+}}
|
||||||
\newcommand{\revconcat}{\mathbin{\widehat{\concat}}}
|
\newcommand{\revconcat}{\mathbin{\widehat{\concat}}}
|
||||||
|
\newcommand{\snoc}[2]{\ensuremath{#1 \concat [#2]}}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% CPS notation
|
%% CPS notation
|
||||||
@@ -306,8 +332,9 @@
|
|||||||
% Canonical variables for handler components
|
% Canonical variables for handler components
|
||||||
\newcommand{\vhret}{h^{\mret}}
|
\newcommand{\vhret}{h^{\mret}}
|
||||||
\newcommand{\vhops}{h^{\mops}}
|
\newcommand{\vhops}{h^{\mops}}
|
||||||
\newcommand{\svhret}{\chi^{\mret}}
|
\newcommand{\sv}{\chi}
|
||||||
\newcommand{\svhops}{\chi^{\mops}}
|
\newcommand{\svhret}{\sv^{\mret}}
|
||||||
|
\newcommand{\svhops}{\sv^{\mops}}
|
||||||
|
|
||||||
% \newcommand{\dk}{\dRecord{fs,\dRecord{\vhret,\vhops}}}
|
% \newcommand{\dk}{\dRecord{fs,\dRecord{\vhret,\vhops}}}
|
||||||
\newcommand{\dk}{k}
|
\newcommand{\dk}{k}
|
||||||
@@ -335,8 +362,18 @@
|
|||||||
\newcommand{\fail}{\dec{fail}}
|
\newcommand{\fail}{\dec{fail}}
|
||||||
\newcommand{\optionalise}{\dec{optionalise}}
|
\newcommand{\optionalise}{\dec{optionalise}}
|
||||||
\newcommand{\bind}{\ensuremath{\gg\!=}}
|
\newcommand{\bind}{\ensuremath{\gg\!=}}
|
||||||
\newcommand{\return}{\dec{return}}
|
\newcommand{\return}{\dec{Return}}
|
||||||
\newcommand{\faild}{\dec{withDefault}}
|
\newcommand{\faild}{\dec{withDefault}}
|
||||||
|
\newcommand{\Free}{\dec{Free}}
|
||||||
|
\newcommand{\FreeState}{\dec{FreeState}}
|
||||||
|
\newcommand{\OpF}{\dec{Op}}
|
||||||
|
\newcommand{\DoF}{\dec{do}}
|
||||||
|
\newcommand{\getF}{\dec{get}}
|
||||||
|
\newcommand{\putF}{\dec{put}}
|
||||||
|
\newcommand{\fmap}{\dec{fmap}}
|
||||||
|
\newcommand{\toggle}{\dec{toggle}}
|
||||||
|
\newcommand{\incrEven}{\dec{incrEven}}
|
||||||
|
\newcommand{\even}{\dec{even}}
|
||||||
|
|
||||||
% Abstract machine
|
% Abstract machine
|
||||||
\newcommand{\cek}[1]{\ensuremath{\langle #1 \rangle}}
|
\newcommand{\cek}[1]{\ensuremath{\langle #1 \rangle}}
|
||||||
@@ -352,6 +389,22 @@
|
|||||||
% configurations
|
% configurations
|
||||||
\newcommand{\conf}{\mathcal{C}}
|
\newcommand{\conf}{\mathcal{C}}
|
||||||
|
|
||||||
|
% effect sugar
|
||||||
|
\newcommand{\inward}[1]{\mathcal{I}\sembr{#1}}
|
||||||
|
\newcommand{\outward}[1]{\mathcal{O}\sembr{#1}}
|
||||||
|
\newcommand{\xcomp}[1]{\outward{#1}}
|
||||||
|
\newcommand{\xval}[1]{\outward{#1}}
|
||||||
|
\newcommand{\xpre}[1]{\outward{#1}}
|
||||||
|
\newcommand{\xrow}[1]{\outward{#1}}
|
||||||
|
\newcommand{\xeff}[1]{\outward{#1}}
|
||||||
|
\newcommand{\pcomp}[1]{\inward{#1}}
|
||||||
|
\newcommand{\pval}[1]{\inward{#1}}
|
||||||
|
\newcommand{\ppre}[1]{\inward{#1}}
|
||||||
|
\newcommand{\prow}[1]{\inward{#1}}
|
||||||
|
\newcommand{\peff}[1]{\inward{#1}}
|
||||||
|
\newcommand{\eamb}{\ensuremath{E_{\mathsf{amb}}}}
|
||||||
|
\newcommand{\trval}[1]{\mathcal{T}\sembr{#1}}
|
||||||
|
|
||||||
% UNIX example
|
% UNIX example
|
||||||
\newcommand{\UNIX}{UNIX}
|
\newcommand{\UNIX}{UNIX}
|
||||||
\newcommand{\OSname}[0]{Tiny UNIX}
|
\newcommand{\OSname}[0]{Tiny UNIX}
|
||||||
@@ -459,6 +512,8 @@
|
|||||||
\newcommand{\Ready}{\dec{Ready}}
|
\newcommand{\Ready}{\dec{Ready}}
|
||||||
\newcommand{\Blocked}{\dec{Blocked}}
|
\newcommand{\Blocked}{\dec{Blocked}}
|
||||||
\newcommand{\init}{\dec{init}}
|
\newcommand{\init}{\dec{init}}
|
||||||
|
\newcommand{\Reader}{\dec{Reader}}
|
||||||
|
\newcommand{\Other}{\dec{Other}}
|
||||||
|
|
||||||
%%
|
%%
|
||||||
%% Some control operators
|
%% Some control operators
|
||||||
@@ -475,11 +530,16 @@
|
|||||||
\newcommand{\Catchcont}{\keyw{catchcont}}
|
\newcommand{\Catchcont}{\keyw{catchcont}}
|
||||||
\newcommand{\Control}{\keyw{control}}
|
\newcommand{\Control}{\keyw{control}}
|
||||||
\newcommand{\Prompt}{\#}
|
\newcommand{\Prompt}{\#}
|
||||||
\newcommand{\Controlz}{\keyw{control0}}
|
\newcommand{\Controlz}{\ensuremath{\keyw{control_0}}}
|
||||||
\newcommand{\Promptz}{\#_0}
|
\newcommand{\Spawn}{\keyw{spawn}}
|
||||||
|
\newcommand{\Promptz}{\ensuremath{\#_0}}
|
||||||
\newcommand{\Escape}{\keyw{escape}}
|
\newcommand{\Escape}{\keyw{escape}}
|
||||||
\newcommand{\shift}{\keyw{shift}}
|
\newcommand{\shift}{\keyw{shift}}
|
||||||
\newcommand{\shiftz}{\keyw{shift0}}
|
\newcommand{\shiftz}{\ensuremath{\keyw{shift_0}}}
|
||||||
|
\newcommand{\CCpp}{\ensuremath{+\CC+}}
|
||||||
|
\newcommand{\CCpm}{\ensuremath{+\CC-}}
|
||||||
|
\newcommand{\CCmp}{\ensuremath{-\CC+}}
|
||||||
|
\newcommand{\CCmm}{\ensuremath{-\CC-}}
|
||||||
\def\sigh#1{%
|
\def\sigh#1{%
|
||||||
\pmb{\left\langle\vphantom{#1}\right.}%
|
\pmb{\left\langle\vphantom{#1}\right.}%
|
||||||
#1%
|
#1%
|
||||||
@@ -487,6 +547,8 @@
|
|||||||
\newcommand{\llambda}{\ensuremath{\pmb{\lambda}}}
|
\newcommand{\llambda}{\ensuremath{\pmb{\lambda}}}
|
||||||
\newcommand{\reset}[1]{\pmb{\langle} #1 \pmb{\rangle}}
|
\newcommand{\reset}[1]{\pmb{\langle} #1 \pmb{\rangle}}
|
||||||
\newcommand{\resetz}[1]{\pmb{\langle} #1 \pmb{\rangle}_0}
|
\newcommand{\resetz}[1]{\pmb{\langle} #1 \pmb{\rangle}_0}
|
||||||
|
\newcommand{\dollarz}[2]{\ensuremath{\reset{#2 \mid #1}}}
|
||||||
|
\newcommand{\dollarzh}[2]{\ensuremath{#1\,\$_0#2}}
|
||||||
\newcommand{\fcontrol}{\keyw{fcontrol}}
|
\newcommand{\fcontrol}{\keyw{fcontrol}}
|
||||||
\newcommand{\fprompt}{\%}
|
\newcommand{\fprompt}{\%}
|
||||||
\newcommand{\splitter}{\keyw{splitter}}
|
\newcommand{\splitter}{\keyw{splitter}}
|
||||||
@@ -501,6 +563,8 @@
|
|||||||
\newcommand{\Algol}{Algol~60}
|
\newcommand{\Algol}{Algol~60}
|
||||||
\newcommand{\qq}[1]{\ensuremath{\ulcorner #1 \urcorner}}
|
\newcommand{\qq}[1]{\ensuremath{\ulcorner #1 \urcorner}}
|
||||||
\newcommand{\prompttype}{\dec{Prompt}}
|
\newcommand{\prompttype}{\dec{Prompt}}
|
||||||
|
\newcommand{\async}{\keyw{async}}
|
||||||
|
\newcommand{\await}{\keyw{await}}
|
||||||
|
|
||||||
% Language macros
|
% Language macros
|
||||||
\newcommand{\Frank}{Frank}
|
\newcommand{\Frank}{Frank}
|
||||||
@@ -509,20 +573,279 @@
|
|||||||
\newcommand{\OCaml}{OCaml}
|
\newcommand{\OCaml}{OCaml}
|
||||||
|
|
||||||
|
|
||||||
% Tikz figures
|
%%
|
||||||
\newcommand\toggle{
|
%% Asymptotic improvement macros
|
||||||
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 5cm/##1,
|
%%
|
||||||
level distance = 1.5cm}]
|
\newcommand{\LLL}{\ensuremath{\mathcal L}}
|
||||||
\node [opnode] {$\Get~\Unit$}
|
\newcommand{\naive}{naïve\xspace}
|
||||||
child{ node [opnode] {$\Put~\False$}
|
\newcommand{\naively}{naïvely\xspace}
|
||||||
|
\newcommand{\Naive}{Naïve\xspace}
|
||||||
|
\newcommand{\sem}[1]{\ensuremath{\pi_{#1}}}
|
||||||
|
\newcommand{\Iff}{\Leftrightarrow}
|
||||||
|
\newcommand{\Implies}{\Rightarrow}
|
||||||
|
\newcommand{\BCalcS}{\ensuremath{\lambda_{\textrm{\normalfont s}}\xspace}}
|
||||||
|
\newcommand{\BCalcE}{\ensuremath{\lambda_{\textrm{\normalfont e}}\xspace}}
|
||||||
|
\newcommand{\BCalcSE}{\ensuremath{\lambda_{\textrm{\normalfont se}}\xspace}}
|
||||||
|
\newcommand{\BSPCF}{\ensuremath{\lambda^\rightarrow_{\textrm{\normalfont s}}\xspace}}
|
||||||
|
\newcommand{\BEPCF}{\ensuremath{\lambda^\rightarrow_{\textrm{\normalfont e}}\xspace}}
|
||||||
|
\newcommand{\BSEPCF}{\ensuremath{\lambda^\rightarrow_{\textrm{\normalfont se}}\xspace}}
|
||||||
|
\newcommand{\IfZero}{\keyw{ifzero}}
|
||||||
|
\newcommand{\Superpoint}{\lambda\_.\Do\;\Branch~\Unit}
|
||||||
|
\newcommand{\ECount}{\dec{effcount}}
|
||||||
|
\newcommand{\Countprog}{K}
|
||||||
|
\newcommand{\Plus}{\mathsf{Plus}}
|
||||||
|
\newcommand{\Minus}{\mathsf{Minus}}
|
||||||
|
\newcommand{\Eq}{\mathsf{Eq}}
|
||||||
|
\newcommand{\BList}{\mathbb{B}^\ast}
|
||||||
|
|
||||||
|
\newcommand{\CtxCat}{\CatName{Ctx}}
|
||||||
|
\newcommand{\PureCont}{\mathsf{PureCont}}
|
||||||
|
|
||||||
|
\newcommand{\Addr}{\mathsf{Addr}}
|
||||||
|
\newcommand{\Lab}{\mathsf{Lab}}
|
||||||
|
\newcommand{\Env}{\mathsf{Env}}
|
||||||
|
|
||||||
|
\newcommand{\Time}{\dec{DTIME}}
|
||||||
|
\newcommand{\query}{\mathord{?}}
|
||||||
|
\newcommand{\ans}{\mathord{!}}
|
||||||
|
\newcommand{\labs}{\mathsf{labs}}
|
||||||
|
\newcommand{\steps}{\mathsf{steps}}
|
||||||
|
|
||||||
|
\newcommand{\tree}{\tau}
|
||||||
|
\newcommand{\tl}{\labs(\tree)}
|
||||||
|
\newcommand{\ts}{\steps(\tree)}
|
||||||
|
\newcommand{\T}[1]{\ensuremath{\mathcal{T}_{#1}}}
|
||||||
|
\newcommand{\Config}{\dec{Config}}
|
||||||
|
\newcommand{\cekl}{\langle}
|
||||||
|
\newcommand{\cekr}{\rangle}
|
||||||
|
|
||||||
|
\newcommand{\const}[1]{\ulcorner #1 \urcorner}
|
||||||
|
\newcommand{\HC}{\ensuremath{\mathcal{H}}}
|
||||||
|
|
||||||
|
\newcommand{\tr}{\mathcal{T}}
|
||||||
|
\newcommand{\tru}{\mathcal{U}}
|
||||||
|
\newcommand{\Tree}{\dec{Tree}}
|
||||||
|
\newcommand{\TimedTree}{\dec{TimedTree}}
|
||||||
|
\newcommand{\denotep}[1]{\ensuremath{\mathbb{P}\llbracket #1 \rrbracket}}
|
||||||
|
|
||||||
|
\newcommand\ttTwoTree{
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 4cm/##1,
|
||||||
|
level distance = 2.0cm}]
|
||||||
|
\node (root) [opnode] {Branch}
|
||||||
|
child { node [opnode] {Branch}
|
||||||
child { node [leaf] {$\True$}
|
child { node [leaf] {$\True$}
|
||||||
edge from parent node[left] {$\Unit$}}
|
|
||||||
edge from parent node[above left] {$\True$}
|
edge from parent node[above left] {$\True$}
|
||||||
}
|
}
|
||||||
child{ node [opnode] {$\Put~v$}
|
child { node [leaf] {$\True$}
|
||||||
child{ node [leaf] {$\False$}
|
edge from parent node[above right] {$\False$}
|
||||||
edge from parent node[right] {$\res{()}$}}
|
}
|
||||||
edge from parent node[above right] {$\res{\False}$}
|
edge from parent node[above left] {$\True$}
|
||||||
|
}
|
||||||
|
child { node [opnode] {Branch}
|
||||||
|
child { node [leaf] {$\True$}
|
||||||
|
edge from parent node[above left] {$\True$}
|
||||||
|
}
|
||||||
|
child { node [leaf] {$\True$}
|
||||||
|
edge from parent node[above right] {$\False$}
|
||||||
|
}
|
||||||
|
edge from parent node[above right] {$\False$}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
\end{tikzpicture}}
|
\end{tikzpicture}}
|
||||||
|
|
||||||
|
|
||||||
|
\newcommand{\tossTree}{
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 2.5cm/##1,
|
||||||
|
level distance = 1.0cm}]
|
||||||
|
\node (root) [opnode] {$\dec{Branch}$}
|
||||||
|
child { node [leaf] {$\dec{Heads}$}
|
||||||
|
edge from parent node[above left] {$\True$}
|
||||||
|
}
|
||||||
|
child { node [leaf] {$\dec{Tails}$}
|
||||||
|
edge from parent node[above right] {$\False$}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
|
||||||
|
\newenvironment{twoeqs}{\ba[t]{@{}r@{~}c@{~}l@{~}c@{~}r@{~}c@{~}l@{}}}{\ea}
|
||||||
|
|
||||||
|
\newcommand{\compTreeEx}{
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 2.0cm/##1,
|
||||||
|
level distance = 2.0cm}]
|
||||||
|
\node (root) [opnode] {$\getF$}
|
||||||
|
child { node [yshift=15] {$\dots$}
|
||||||
|
edge from parent {}
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\putF$}
|
||||||
|
child { node {$\True$}
|
||||||
|
edge from parent node[left] {$\Unit$}
|
||||||
|
}
|
||||||
|
edge from parent node[yshift=5,left] {$-2$}
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\putF$}
|
||||||
|
child { node {$\False$}
|
||||||
|
edge from parent node[left] {$\Unit$}
|
||||||
|
}
|
||||||
|
edge from parent node[yshift=2,left] {$-1$}
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\putF$}
|
||||||
|
child { node {$\True$}
|
||||||
|
edge from parent node[left] {$\Unit$}
|
||||||
|
}
|
||||||
|
edge from parent node[left] {$0$}
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\putF$}
|
||||||
|
child { node {$\False$}
|
||||||
|
edge from parent node[right] {$\Unit$}
|
||||||
|
}
|
||||||
|
edge from parent node[yshift=2,right] {$1$}
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\putF$}
|
||||||
|
child { node {$\True$}
|
||||||
|
edge from parent node[right] {$\Unit$}
|
||||||
|
}
|
||||||
|
edge from parent node[yshift=5,right] {$2$}
|
||||||
|
}
|
||||||
|
child { node [yshift=15] {$\dots$}
|
||||||
|
edge from parent {}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
|
||||||
|
\newcommand{\smath}[1]{\ensuremath{{\scriptstyle #1}}}
|
||||||
|
|
||||||
|
\newcommand{\InfiniteModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 3.0cm/##1,
|
||||||
|
level distance = 1.0cm}]
|
||||||
|
\node (root) [draw=none] { }
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [draw=none,rotate=165] {$\vdots$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[leaf] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node [leaf] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
%
|
||||||
|
\newcommand{\ShortConjModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 3.5cm/##1,
|
||||||
|
level distance = 1.0cm}]
|
||||||
|
\node (root) [draw=none] { }
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node [treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
%
|
||||||
|
|
||||||
|
\newcommand{\TTTwoModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 8cm/##1,
|
||||||
|
level distance = 1.5cm}]
|
||||||
|
\node (root) [draw=none] { }
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [leaf] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[leaf] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [leaf] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[leaf] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
%
|
||||||
|
\newcommand{\XORTwoModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 5.5cm/##1,
|
||||||
|
level distance = 1cm}]
|
||||||
|
\node (root) [draw=none] { }
|
||||||
|
child { node [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
%
|
||||||
|
\newcommand{\SXORTwoModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 2.5cm/##1,
|
||||||
|
level distance = 1cm}]
|
||||||
|
\node (root) [opnode] {$\smath{\query 0}$}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node [opnode] {$\smath{\query 1}$}
|
||||||
|
child { node [treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
child { node[treenode] {$\smath{\ans\False}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}
|
||||||
|
%
|
||||||
|
\newcommand{\TTZeroModel}{%
|
||||||
|
\begin{tikzpicture}[->,>=stealth',level/.style={sibling distance = 1cm/##1,
|
||||||
|
level distance = 1cm}]
|
||||||
|
\node (root) [draw=none] { }
|
||||||
|
child { node [treenode] {$\smath{\ans\True}$}
|
||||||
|
edge from parent node { }
|
||||||
|
}
|
||||||
|
;
|
||||||
|
\end{tikzpicture}}%
|
||||||
32
slides/Makefile
Normal file
32
slides/Makefile
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
TEXC=pdflatex
|
||||||
|
CFLAGS=-interaction=nonstopmode -halt-on-error -file-line-error
|
||||||
|
BIBC=bibtex
|
||||||
|
PAPER=viva
|
||||||
|
BIBLIO=$(PAPER)
|
||||||
|
LATEST_COMMIT=$(shell git log --format="%h" -n 1)
|
||||||
|
|
||||||
|
all: $(PAPER).pdf
|
||||||
|
draft: $(PAPER).pdf-draft
|
||||||
|
|
||||||
|
$(PAPER).aux: $(PAPER).tex
|
||||||
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
|
|
||||||
|
$(BIBLIO).bbl: $(PAPER).aux $(BIBLIO).bib
|
||||||
|
$(BIBC) $(PAPER)
|
||||||
|
|
||||||
|
$(PAPER).pdf: $(PAPER).aux $(BIBLIO).bbl
|
||||||
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
|
$(TEXC) $(CFLAGS) $(PAPER)
|
||||||
|
|
||||||
|
$(PAPER).pdf-draft: CFLAGS:=$(CFLAGS) "\def\DRAFT{$(LATEST_COMMIT)}\input{$(PAPER)}"
|
||||||
|
$(PAPER).pdf-draft: all
|
||||||
|
mv $(PAPER).pdf $(PAPER)-draft.pdf
|
||||||
|
tar cf thesis-draft.tar.gz $(PAPER)-draft.pdf
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.log *.aux *.toc *.out
|
||||||
|
rm -f *.bbl *.blg *.fls *.xml
|
||||||
|
rm -f *.nav *.snm
|
||||||
|
rm -f *.fdb_latexmk *.vtc *.cut
|
||||||
|
rm -f $(PAPER).pdf camera-ready.pdf submission.pdf
|
||||||
|
rm -f *.o *.cmx *.cmo
|
||||||
82
slides/viva.bib
Normal file
82
slides/viva.bib
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
@inproceedings{HillerstromL16,
|
||||||
|
author = {Daniel Hillerstr{\"{o}}m and
|
||||||
|
Sam Lindley},
|
||||||
|
title = {Liberating effects with rows and handlers},
|
||||||
|
booktitle = {TyDe@ICFP},
|
||||||
|
pages = {15--27},
|
||||||
|
publisher = {{ACM}},
|
||||||
|
year = {2016}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inproceedings{HillerstromLAS17,
|
||||||
|
author = {Daniel Hillerstr{\"{o}}m and
|
||||||
|
Sam Lindley and
|
||||||
|
Robert Atkey and
|
||||||
|
{KC} Sivaramakrishnan},
|
||||||
|
title = {Continuation Passing Style for Effect Handlers},
|
||||||
|
booktitle = {{FSCD}},
|
||||||
|
series = {LIPIcs},
|
||||||
|
volume = {84},
|
||||||
|
pages = {18:1--18:19},
|
||||||
|
OPTpublisher = {Schloss Dagstuhl - Leibniz-Zentrum fuer Informatik},
|
||||||
|
year = {2017}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inproceedings{HillerstromL18,
|
||||||
|
author = {Daniel Hillerstr{\"{o}}m and
|
||||||
|
Sam Lindley},
|
||||||
|
title = {Shallow Effect Handlers},
|
||||||
|
booktitle = {{APLAS}},
|
||||||
|
OPTseries = {Lecture Notes in Computer Science},
|
||||||
|
series = {{LNCS}},
|
||||||
|
volume = {11275},
|
||||||
|
pages = {415--435},
|
||||||
|
publisher = {Springer},
|
||||||
|
year = {2018}
|
||||||
|
}
|
||||||
|
|
||||||
|
@article{HillerstromLA20,
|
||||||
|
author = {Daniel Hillerstr{\"{o}}m and
|
||||||
|
Sam Lindley and
|
||||||
|
Robert Atkey},
|
||||||
|
title = {Effect handlers via generalised continuations},
|
||||||
|
journal = {J. Funct. Program.},
|
||||||
|
volume = {30},
|
||||||
|
pages = {e5},
|
||||||
|
year = {2020}
|
||||||
|
}
|
||||||
|
|
||||||
|
@article{HillerstromLL20,
|
||||||
|
author = {Daniel Hillerstr{\"{o}}m and
|
||||||
|
Sam Lindley and
|
||||||
|
John Longley},
|
||||||
|
title = {Effects for Efficiency: Asymptotic Speedup with First-Class Control},
|
||||||
|
journal = {Proc. {ACM} Program. Lang.},
|
||||||
|
volume = {4},
|
||||||
|
number = {{ICFP}},
|
||||||
|
pages = {100:1--100:29},
|
||||||
|
year = {2020}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Unix
|
||||||
|
@article{RitchieT74,
|
||||||
|
author = {Dennis Ritchie and
|
||||||
|
Ken Thompson},
|
||||||
|
title = {The {UNIX} Time-Sharing System},
|
||||||
|
journal = {Commun. {ACM}},
|
||||||
|
volume = {17},
|
||||||
|
number = {7},
|
||||||
|
pages = {365--375},
|
||||||
|
year = {1974}
|
||||||
|
}
|
||||||
|
|
||||||
|
# CEK & C
|
||||||
|
@InProceedings{FelleisenF86,
|
||||||
|
title={Control Operators, the {SECD}-machine, and the $\lambda$-Calculus},
|
||||||
|
author={Felleisen, Matthias and Friedman, Daniel P.},
|
||||||
|
year=1987,
|
||||||
|
booktitle = {Formal Description of Programming Concepts III},
|
||||||
|
OPTbooktitle = {The Proceedings of the Conference on Formal Description of Programming Concepts III, Ebberup, Denmark},
|
||||||
|
pages = {193--217},
|
||||||
|
OPTpublisher={North Holland}
|
||||||
|
}
|
||||||
201
slides/viva.tex
Normal file
201
slides/viva.tex
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
\documentclass[169,10pt,compress,dvipsnames]{beamer}
|
||||||
|
%%
|
||||||
|
%% Slides layout
|
||||||
|
%%
|
||||||
|
\beamertemplatenavigationsymbolsempty % hides navigation buttons
|
||||||
|
\usetheme{Madrid} % standard Madrid theme
|
||||||
|
\setbeamertemplate{footline}{} % renders the footer empty
|
||||||
|
%
|
||||||
|
\setbeamertemplate{bibliography item}{ % this is a hack to prevent Madrid theme + biblatex
|
||||||
|
\hspace{-0.4cm}\lower3pt\hbox{ % from causing bibliography entries to run over
|
||||||
|
\pgfuseimage{beamericonarticle} % the slide margins
|
||||||
|
}}
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% Packages
|
||||||
|
%%
|
||||||
|
\usepackage[utf8]{inputenc} % enable UTF-8 compatible typing
|
||||||
|
\usepackage{hyperref} % interactive PDF
|
||||||
|
\usepackage[sort&compress,square,numbers]{natbib} % Bibliography
|
||||||
|
\usepackage{bibentry} % Print bibliography entries inline.
|
||||||
|
\makeatletter % Redefine bibentry to omit hyperrefs
|
||||||
|
\renewcommand\bibentry[1]{\nocite{#1}{\frenchspacing
|
||||||
|
\@nameuse{BR@r@#1\@extra@b@citeb}}}
|
||||||
|
\makeatother
|
||||||
|
\nobibliography* % use the bibliographic data from the standard BibTeX setup.
|
||||||
|
\usepackage{amsmath,amssymb,mathtools} % maths typesetting
|
||||||
|
\usepackage{../pkgs/mathpartir} % Inference rules
|
||||||
|
\usepackage{../pkgs/mathwidth} % renders character sequences nicely in math mode
|
||||||
|
\usepackage{stmaryrd} % semantic brackets
|
||||||
|
\usepackage{xspace} % proper spacing for macros in text
|
||||||
|
|
||||||
|
\usepackage[T1]{fontenc} % 8-bit font encoding
|
||||||
|
% native support for accented characters.
|
||||||
|
\usepackage[scaled=0.85]{beramono} % smoother typewriter font
|
||||||
|
\newcommand*{\Scale}[2][4]{\scalebox{#1}{\ensuremath{#2}}}%
|
||||||
|
|
||||||
|
\input{../macros.tex}
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% Meta information
|
||||||
|
%%
|
||||||
|
\author{Daniel Hillerström}
|
||||||
|
\title{Foundations for Programming and Implementing Effect Handlers}
|
||||||
|
\institute{The University of Edinburgh, Scotland UK}
|
||||||
|
\subtitle{PhD viva}
|
||||||
|
\date{August 13, 2021}
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% Slides
|
||||||
|
%%
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
%
|
||||||
|
% Title slide
|
||||||
|
%
|
||||||
|
\begin{frame}
|
||||||
|
\maketitle
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% Dissertation overview
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{My dissertation at glance}
|
||||||
|
|
||||||
|
Three main strands of work
|
||||||
|
|
||||||
|
\begin{description}
|
||||||
|
\item[Programming] Language design and applications of effect handlers.
|
||||||
|
\item[Implementation] Canonical implementation strategies for effect handlers.
|
||||||
|
\item[Expressiveness] Exploration of the computational expressiveness of effect handlers.
|
||||||
|
\end{description}
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Calculi for deep, shallow, and parameterised handlers}
|
||||||
|
|
||||||
|
The calculi capture key aspects of the implementation of effect
|
||||||
|
handlers in Links.
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item $\HCalc$ ordinary deep handlers (fold).
|
||||||
|
\item $\SCalc$ shallow handlers (case-split).
|
||||||
|
\item $\HPCalc$ parameterised deep handlers (fold+state).
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
The actual implementation is the union of the three calculi.\\[2em]
|
||||||
|
|
||||||
|
\textbf{Relevant papers} TyDe'16~\cite{HillerstromL16},
|
||||||
|
APLAS'18~\cite{HillerstromL18}, JFP'20~\cite{HillerstromLA20}.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% UNIX
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Effect handlers as composable operating systems}
|
||||||
|
|
||||||
|
An interpretation of \citeauthor{RitchieT74}'s
|
||||||
|
UNIX~\cite{RitchieT74} in terms of effect handlers.\\[2em]
|
||||||
|
|
||||||
|
\[
|
||||||
|
\bl
|
||||||
|
\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\!\textbf{Basic idea}
|
||||||
|
\ba[m]{@{\qquad}r@{~}c@{~}l}
|
||||||
|
\text{\emph{system call}} &\approx& \text{\emph{operation invocation}}\\
|
||||||
|
\text{\emph{system call implementation}} &\approx& \text{\emph{operation interpretation}}
|
||||||
|
\ea
|
||||||
|
\el
|
||||||
|
\]\hfill\\[2em]
|
||||||
|
|
||||||
|
\textbf{Key point} Legacy code is modularly retrofitted with functionality.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% CPS translation
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{CPS transforms for effect handlers}
|
||||||
|
|
||||||
|
A higher-order CPS transform for effect handlers with generalised
|
||||||
|
continuations.\\[1em]
|
||||||
|
|
||||||
|
\textbf{Generalised continuation} Structured representation of
|
||||||
|
delimited continuations.\\[0.5em]
|
||||||
|
|
||||||
|
\[
|
||||||
|
\Scale[1.8]{\kappa = \overline{(\sigma, (\hret,\hops))}}
|
||||||
|
\]\\[1em]
|
||||||
|
|
||||||
|
\textbf{Key point} Separate the \emph{doing} layer ($\sigma$) from the \emph{being} layer ($H$).\\[2em]
|
||||||
|
|
||||||
|
\textbf{Relevant papers} FSCD'17~\cite{HillerstromLAS17},
|
||||||
|
APLAS'18~\cite{HillerstromL18}, JFP'20~\cite{HillerstromLA20}.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% Abstract machine
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Abstract machine semantics for effect handlers}
|
||||||
|
|
||||||
|
Plugging generalised continuations into \citeauthor{FelleisenF86}'s
|
||||||
|
CEK machine~\cite{FelleisenF86} yields a runtime for effect
|
||||||
|
handlers.\\[2em]
|
||||||
|
|
||||||
|
\[
|
||||||
|
\Scale[2]{\cek{C \mid E \mid K = \overline{(\sigma, (H,E))}}}
|
||||||
|
\]\\[2em]
|
||||||
|
|
||||||
|
\textbf{Relevant papers} TyDe'16~\cite{HillerstromL16},
|
||||||
|
JFP'20~\cite{HillerstromLA20}.
|
||||||
|
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% Interdefinability of handlers
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Interdefinability of effect handlers}
|
||||||
|
|
||||||
|
Deep, shallow, and parameterised handlers are interdefinable
|
||||||
|
w.r.t. to typability-preserving macro-expressiveness.
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
\item Deep as shallow, $\mathcal{D}\llbracket - \rrbracket$, image is computationally lightweight.
|
||||||
|
\item Shallow as deep, $\mathcal{S}\llbracket - \rrbracket$, image is computationally expensive.
|
||||||
|
\item Parameterised as deep, $\mathcal{P}\llbracket - \rrbracket$,
|
||||||
|
image uses explicit state-passing.
|
||||||
|
\end{itemize}
|
||||||
|
~\\[1em]
|
||||||
|
\textbf{Relevant papers} APLAS'18~\cite{HillerstromL18},
|
||||||
|
JFP'20~\cite{HillerstromLA20}.
|
||||||
|
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% Asymptotic speed up with first-class control
|
||||||
|
\begin{frame}
|
||||||
|
\frametitle{Asymptotic speed up with effect handlers}
|
||||||
|
|
||||||
|
Effect handlers can make some programs faster!
|
||||||
|
|
||||||
|
\[
|
||||||
|
\Count_n : ((\Nat_n \to \Bool) \to \Bool) \to \Nat
|
||||||
|
\]\\[1em]
|
||||||
|
%
|
||||||
|
Using type-respecting expressiveness
|
||||||
|
\begin{itemize}
|
||||||
|
\item There \textbf{exists} an implementation of $\Count_n \in \HPCF$ with
|
||||||
|
effect handlers such that the runtime for every $n$-standard predicate $P$ is
|
||||||
|
$\Count_n~P = \BigO(2^n)$.
|
||||||
|
\item \textbf{Forall} implementations of $\Count_n \in \BPCF$ the runtime for every $n$-standard predicate $P$ is $\Count_n~P = \Omega(n2^n)$
|
||||||
|
\end{itemize}
|
||||||
|
~\\[1em]
|
||||||
|
\textbf{Relevant paper} ICFP'20~\cite{HillerstromLL20}.
|
||||||
|
\end{frame}
|
||||||
|
|
||||||
|
% Background
|
||||||
|
% \begin{frame}
|
||||||
|
% \frametitle{Continuations literature review}
|
||||||
|
% \end{frame}
|
||||||
|
|
||||||
|
%
|
||||||
|
% References
|
||||||
|
%
|
||||||
|
\begin{frame}%[allowframebreaks]
|
||||||
|
\frametitle{References}
|
||||||
|
\bibliographystyle{plainnat}
|
||||||
|
\bibliography{\jobname}
|
||||||
|
\end{frame}
|
||||||
|
\end{document}
|
||||||
1241
thesis.bib
1241
thesis.bib
File diff suppressed because it is too large
Load Diff
24533
thesis.tex
24533
thesis.tex
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user