diff --git a/.gitignore b/.gitignore index a136337..9674ea3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ +*.agdai +*.blg *.pdf +/gentex +/agda.sty +/main.log diff --git a/Justfile b/Justfile deleted file mode 100644 index f69f868..0000000 --- a/Justfile +++ /dev/null @@ -1,2 +0,0 @@ -watch: - watchexec -e tex -- tectonic main.tex diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..104a5e1 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +SOURCE_MODULES := $(shell find src/Project -name "*.agda" -exec basename {} \;) +GENERATED_TEX := $(patsubst %.agda, gentex/Project/%.tex, $(SOURCE_MODULES)) + +gentex/Project/%.tex: src/Project/%.agda + agda --latex-dir=gentex --latex $< + +agda.sty: $(GENERATED_TEX) + cp gentex/agda.sty agda.sty + +main.pdf: main.tex agda.sty + tectonic --keep-logs main.tex + +watch: + watchexec -e tex -- make main.pdf + +.PHONY: watch diff --git a/cesk.png b/cesk.png new file mode 100644 index 0000000..b7ebebe Binary files /dev/null and b/cesk.png differ diff --git a/csci8980-project.agda-lib b/csci8980-project.agda-lib new file mode 100644 index 0000000..e7d169e --- /dev/null +++ b/csci8980-project.agda-lib @@ -0,0 +1,3 @@ +name: csci8980-project +depend: standard-library +include: ./src diff --git a/main.tex b/main.tex index 891586d..8f54446 100644 --- a/main.tex +++ b/main.tex @@ -1,22 +1,49 @@ \documentclass{beamer} - \usepackage[utf8]{inputenc} +\usepackage{agda} +\usepackage{caption} +\usepackage{catchfilebetweentags} +\usepackage{cite} +\usepackage{newunicodechar} +\usepackage{url} + +\usetheme{CambridgeUS} +\usecolortheme{lily} +\setbeamercovered{transparent} + \usepackage{tikz} \usetikzlibrary{positioning} -%Information to be included in the title page: -\title{Sample title} -\author{Anonymous} -\institute{Overleaf} -\date{2021} +\titlegraphic{ + \centering + \includegraphics[width=.3\textwidth,height=.5\textheight]{cesk.png} +} +\title{First class continuations with CEK machines in Agda} +\author{Michael Zhang} +\date{} \begin{document} \frame{\titlepage} +\section{Primer on CESK} + \begin{frame} -\frametitle{Sample frame title} -This is some text in the first frame. This is some text in the first frame. This is some text in the first frame. + \frametitle{What is a CESK machine?} + + \begin{itemize}[<+->] + \item Abstract machine for interpreters, introduced by Matthias Felleisen. + \item Stands for $C$ontrol, $E$nvironment, $S$tore, $K$ontinuation. + \item Based on Matt Might's blog post on CESK machines \cite{might-cesk}. + \end{itemize} +\end{frame} + +\begin{frame} + \frametitle{How does it work?} + + \begin{itemize}[<+->] + \item + \end{itemize} \end{frame} \begin{frame} @@ -27,16 +54,31 @@ This is some text in the first frame. This is some text in the first frame. This \node[draw, align=left, squarednode](ceskState){ C = $\lambda x . (\lambda y . x + y)$ \\ $E$ = [] \\ - $S$ = [] \\ $\kappa$ = halt }; - \node[squarednode](ceskState2)[right=of ceskState]{CESK}; + \node[squarednode](ceskState2)[right=of ceskState]{CEK}; %lines \draw[->] (ceskState.east) -- (ceskState2.west); \end{tikzpicture} \end{frame} +\section{Implementation} + +\begin{frame} + \frametitle{Hellosu} + + \include{./gentex/Project/Cesk.tex} +\end{frame} + +\section{Conclusion} + +\begin{frame} + \frametitle{Resources} + \bibliography{res}{} + \bibliographystyle{plain} +\end{frame} + \end{document} % vim: set sw=2 : diff --git a/res.bib b/res.bib new file mode 100644 index 0000000..051a316 --- /dev/null +++ b/res.bib @@ -0,0 +1,21 @@ +@phdthesis{ + felleisen-cesk, + author = "Matthias Felleisen", + howpublished = {\url{https://www2.ccs.neu.edu/racket/pubs/dissertation-felleisen.pdf}}, +} + +@misc{ + might-cesk, + author = "Matt Might", + title = "Writing an interpreter, CESK-style", + howpublished = {\url{https://matt.might.net/articles/cesk-machines}}, +} + +@misc{ + source-code, + author = "Michael Zhang", + title = "First class continuations with CEK machines in Agda", + howpublished = {\url{https://git.sr.ht/~mzhang/csci8980-f21-project}}, +} + +@comment vim: set sw=2 : diff --git a/src/Project/Cesk.agda b/src/Project/Cesk.agda new file mode 100644 index 0000000..639e313 --- /dev/null +++ b/src/Project/Cesk.agda @@ -0,0 +1,40 @@ +{-# OPTIONS --allow-incomplete-matches --allow-unsolved-metas #-} + +module Project.Cesk where + +open import Data.Product renaming (_,_ to ⦅_,_⦆) +open import Project.Definitions using (Aexp; Exp; Env; State; Letk; Kont; Value; Type; atomic; kont; letk; lookup; call/cc; case; mkState; halt; `ℕ; _,_; _k⇒_; _⇒_; _∋_; _·_; _∘_; _[_∶_]; ∅) +open import Project.Util using (_$_) +open import Project.Do using (StepResult; part; done; do-kont; do-apply) + +open Aexp +open Value +open State + +astep : ∀ {Γ A} → Aexp Γ A → Env Γ → Value A +astep zero _ = zero +astep (suc c) e = suc $ astep c e +astep (` id) e = lookup e id +astep (ƛ body) e = clo body e + +inject : (A : Type) → Exp ∅ A → State A +inject A C = mkState A ∅ C ∅ halt + +step : ∀ {Tω : Type} → State Tω → StepResult Tω +step (mkState Tc Γ (case c cz cs) E K) with ⦅ astep c E , astep cs E ⦆ +... | ⦅ zero , _ ⦆ = part $ mkState Tc Γ cz E K +... | ⦅ suc n , clo {Γc} cc cloE ⦆ = + part $ mkState Tc (Γc , `ℕ) cc (cloE [ `ℕ ∶ n ]) K +step (mkState Tc Γ (C₁ · C₂) E K) = + let C₁′ = astep C₁ E in + let C₂′ = astep C₂ E in + do-apply C₁′ C₂′ K +step (mkState Tc Γ (atomic x) E K) with K +... | halt = done $ astep x E +... | kont l = part $ do-kont l $ astep x E +step (mkState Tc Γ (call/cc C) E K) = + part $ mkState ({! !} k⇒ {! !}) Γ {! !} {! !} {! !} + +-- 3 + (call/cc k . k 2 + k 4) +-- (k . k 2 + k 4) (\x . 3 + x) +-- ((\x . 3 + x) 2 + (\x . 3 + x) 4) \ No newline at end of file diff --git a/src/Project/Definitions.agda b/src/Project/Definitions.agda new file mode 100644 index 0000000..9a1cca4 --- /dev/null +++ b/src/Project/Definitions.agda @@ -0,0 +1,101 @@ +module Project.Definitions where + +open import Data.Maybe using (Maybe; just; nothing) +open import Data.Nat using (ℕ; zero; suc) +open import Data.Product renaming (_,_ to _ʻ_) +open import Project.Util using (_$_) + +infix 4 _∋_ +infix 4 _·_ +infixl 6 _,_ +infixr 7 _⇒_ + +data Type : Set where + _⇒_ : Type → Type → Type + _k⇒_ : Type → Type → Type + `ℕ : Type + +data Context : Set where + ∅ : Context + _,_ : Context → Type → Context + +data Value : Type → Set + +data Env : Context → Set where + ∅ : Env ∅ + _[_∶_] : ∀ {Γ} → Env Γ → (A : Type) → Value A → Env (Γ , A) + +data _∋_ : Context → Type → Set where + zero : ∀ {Γ A} → Γ , A ∋ A + suc : ∀ {Γ A B} → Γ ∋ A → Γ , B ∋ A + +lookup : ∀ {Γ A} → Env Γ → Γ ∋ A → Value A +lookup ∅ () +lookup (env [ A ∶ x ]) zero = x +lookup (env [ A ∶ x ]) (suc id) = lookup env id + +data Aexp Context : Type → Set +data Exp Context : Type → Set + +data Aexp Γ where + -- Natural numbers + zero : Aexp Γ `ℕ + suc : Aexp Γ `ℕ → Aexp Γ `ℕ + + -- Functions + `_ : ∀ {A} → Γ ∋ A → Aexp Γ A + ƛ : ∀ {B} {A : Type} → Exp (Γ , A) B → Aexp Γ (A ⇒ B) + +data Exp Γ where + -- Atomic expressions + atomic : ∀ {A} → Aexp Γ A → Exp Γ A + + -- Natural numbers + case : ∀ {A} → Aexp Γ `ℕ → Exp Γ A → Aexp Γ (`ℕ ⇒ A) → Exp Γ A + + -- Functions + _·_ : ∀ {A B} → Aexp Γ (A ⇒ B) → Aexp Γ A → Exp Γ B + _∘_ : ∀ {A B} → Aexp Γ (A k⇒ B) → Exp Γ B + + -- Call/cc + call/cc : ∀ {Tω A B} → Exp Γ (A ⇒ B) → Exp Γ Tω + +data Kont (Tω : Type) : Type → Set + +data Value where + -- Natural numbers + zero : Value `ℕ + suc : Value `ℕ → Value `ℕ + + -- Functions + clo : ∀ {Γ} {A B : Type} → Exp (Γ , A) B → Env Γ → Value (A ⇒ B) + + -- Call/CC + kont : ∀ {Tω Ti Tc} → Kont Tω Tc → Value (Ti k⇒ Tc) + +record Letk (Tv Tω : Type) : Set + +record Letk Tv Tω where + inductive + constructor letk + field + {Tc} : Type + Γ : Context + C : Exp (Γ , Tv) Tc + E : Env Γ + K : Kont Tω Tc + +data Kont Tω where + halt : Kont Tω Tω + kont : ∀ {Tc} → Letk Tc Tω → Kont Tω Tc + +-- A is the type of C +-- B is the eventual type +record State (Tω : Type) : Set where + constructor mkState + field + Tc : Type + Γ : Context + C : Exp Γ Tc + E : Env Γ + K : Kont Tω Tc \ No newline at end of file diff --git a/src/Project/Do.agda b/src/Project/Do.agda new file mode 100644 index 0000000..f0d0ee0 --- /dev/null +++ b/src/Project/Do.agda @@ -0,0 +1,21 @@ +module Project.Do where + +open import Project.Definitions using (Letk; Kont; Exp; Value; State; Type; kont; halt; letk; clo; zero; suc; mkState; `_; `ℕ; _·_; _⇒_; _,_; _[_∶_]) +open import Project.Util using (_$_) + +data StepResult (A : Type) : Set where + part : State A → StepResult A + done : Value A → StepResult A + +-- Apply the continuation to the value, resulting in a state. +do-kont : ∀ {Tv Tω} (L : Letk Tv Tω) → Value Tv → State Tω +do-kont {Tv} {Tω} (letk {Tc} Γ C E k) v = + let Γ′ = Γ , Tv in + let E′ = E [ Tv ∶ v ] in + mkState Tc Γ′ C E′ k + +do-apply : ∀ {A B Tω} → Value (A ⇒ B) → Value A → Kont Tω B → StepResult Tω +do-apply (clo {Γ} {A} {B} body e) v k = + let Γ′ = Γ , A in + let E′ = e [ A ∶ v ] in + part $ mkState B Γ′ body E′ k \ No newline at end of file diff --git a/src/Project/Util.agda b/src/Project/Util.agda new file mode 100644 index 0000000..a2029f4 --- /dev/null +++ b/src/Project/Util.agda @@ -0,0 +1,6 @@ +module Project.Util where + +infixr 0 _$_ + +_$_ : ∀ {a b : Set} → (a → b) → a → b +f $ x = f x \ No newline at end of file