|
| 1 | +-- Based on: https://youtu.be/uMurx1a6Zck?t=20144 |
| 2 | +-- We want: |
| 3 | +-- 1. A Compiler (comp) |
| 4 | +-- 2. A Virtual Machine (exec) |
| 5 | +-- 3. A proof that it is correct (comp, exec = eval) |
| 6 | + |
| 7 | +inductive Regex where |
| 8 | + | emptyset: Regex |
| 9 | + | emptystr: Regex |
| 10 | + | char (c: Char): Regex |
| 11 | + | or (left: Regex) (right: Regex): Regex |
| 12 | + deriving BEq |
| 13 | + |
| 14 | +def derive (r: Regex) (c: Char): Regex := |
| 15 | + match r with |
| 16 | + | Regex.emptyset => Regex.emptyset |
| 17 | + | Regex.emptystr => Regex.emptyset |
| 18 | + | Regex.char a => if a == c then Regex.emptystr else Regex.emptystr |
| 19 | + | Regex.or a b => Regex.or (derive a c) (derive b c) |
| 20 | + |
| 21 | +-- `eval :: Expr -> Int` |
| 22 | +-- `eval :: Expr -> m Int` |
| 23 | +-- `eval :: Expr -> State s Int` |
| 24 | +-- `newtype State s v = State (s -> (s, v))` |
| 25 | +-- `eval :: Expr -> s -> (s, v)` |
| 26 | +-- `eval :: Regex -> String -> (String, Regex)` |
| 27 | +def eval (r: Regex) (s: List Char): (List Char × Regex) := |
| 28 | + (] |
| 29 | + , List.foldl derive r s) |
| 30 | + |
| 31 | +-- The instruction set |
| 32 | +-- To Calculate: `data Code = ?` |
| 33 | + |
| 34 | +-- The compiler |
| 35 | +-- Intuition: `comp :: Expr -> Code` |
| 36 | +-- Practically we need a continuation in the compiler: |
| 37 | +-- `comp :: Expr -> Code -> Code`, where initial Code is empty code |
| 38 | +-- `comp :: Regex -> NFA -> NFA`, where initial NFA is an empty NFA |
| 39 | +def comp (r: Regex) (d: NFA): NFA := |
| 40 | + sorry |
| 41 | + |
| 42 | +-- The virtual machine |
| 43 | +-- `type Stack :: [Int]` |
| 44 | +-- `exec :: Code -> Stack -> Stack` |
| 45 | +-- `exec :: Code -> Stack -> m Stack` |
| 46 | +-- `exec :: Code -> Stack -> State s Stack` |
| 47 | +-- `newtype State s v = State (s -> (s, v))` |
| 48 | +-- `exec :: NFA -> List Regex -> String -> (String, List Regex)` |
| 49 | +-- Regex = the NFA state, otherwise we cannot do an equality between eval and exec |
| 50 | +def exec (d: NFA) (current: List Regex) (s: String): (String × List Regex) := |
| 51 | + sorry |
| 52 | + |
| 53 | +-- Intuition: `comp, exec = eval` |
| 54 | +-- Intuition: `exec (comp e) s = eval e : s` |
| 55 | +-- Practically: `exec (comp e c) s = exec c (eval e : s)` |
| 56 | +-- With Effects: `exec (comp e c) s = do v <- eval e; exec c (v: s)` |
| 57 | +-- Solve this equation with 3 unknowns: comp, exec and code |
| 58 | +-- This equation has more unknowns that equations |
| 59 | +-- We solve this via constructive induction |
| 60 | +-- With Regex: `exec (comp initial_regex empty_dfa) empty_regex str` |
| 61 | +-- `= let (dstr, dregex) := eval initial_regex str in exec empty_dfa (dregex: empty_regex) dstr` |
| 62 | +-- c = any_dfa or empty_dfa |
| 63 | +-- e = initial_regex |
| 64 | +-- s = any_regexes or empty_regexs or [] |
| 65 | +-- s has to be a list of states, to keep this formula general enough |
| 66 | +-- if s is a list then we compile to an NFA, instead of a DFA |
| 67 | +-- if we are compiling an automaton then our states have to regexes to be equal to eval and eval has to return a regex. |
| 68 | +-- So this means that derivatives are probably going to be evaluator. |
| 69 | + |
| 70 | +-- e = Val n |
| 71 | +-- do v <- eval (Val n); exec c (v: s) |
| 72 | +-- ... |
| 73 | +-- = exec c' s |
| 74 | +-- c' = comp (Val n) c |
| 75 | + |
| 76 | +-- initial_regex = char c |
| 77 | +-- `let (dstr, dregex) := eval (char c) str in exec empty_dfa (dregex: empty_regex) dstr` |
| 78 | +-- `let (dstr, dregex) := ("", String.foldl derive (char c) str) in exec empty_dfa (dregex: empty_regex) dstr` |
| 79 | +-- `let dregex := String.foldl derive (char c) str in exec empty_dfa (dregex: empty_regex) ""` |
| 80 | +-- `exec (comp initial_regex empty_dfa) empty_regex str` |
| 81 | + |
| 82 | + |
| 83 | +-- comp, exec = eval |
| 84 | +-- exec (comp regex dfa) char = derive regex char |
| 85 | +-- exec (comp regex dfa) (char:str) = exec (derive regex char) str |
| 86 | +-- exec (comp (Char c) dfa) char = derive (Char c) char |
| 87 | +-- if a == c then Regex.emptystr else Regex.emptystr |
| 88 | +-- (comp (Char c) dfa) |
| 89 | +-- dfa.add[Regex.char c, c] => Regex.emptystr |
| 90 | +-- dfa.add[Regex.char c, !c] => Regex.emptyset |
| 91 | +-- = exec c' char where c' = (comp (Char c) dfa) |
0 commit comments