#+title: rl' #+author: Madeleine Sydney Slaga ~rl'~ will be a lazily-evaluated, purely-functional, statically-typed language heavily imitating Haskell. * Architecture [[file:rlpc.drawio.svg]] * Build Info - ~rlpc~ is built using [[https://www.haskell.org/ghcup/][Cabal]] - ~rlpc~'s documentation is built using [[https://www.sphinx-doc.org/en/master/][Sphinx]] #+BEGIN_SRC sh $ cabal build # Build the rlpc compiler $ cabal install # Install rlpc to $PATH $ cabal haddock # Build the API docs w/ Haddock $ make -C doc html # Build the primary docs w/ Sphinx # run the test suite $ cabal test --test-show-details=direct #+END_SRC * Use ** TLDR #+begin_src sh # Compile and evaluate examples/rlp/QuickSort.rl $ rlpc examples/QuickSort.rl # Compile and evaluate t.cr, with evaluation info dumped to t.log $ rlpc -ddump-eval -l t.log t.cr # Compile and evaluate t.rl, dumping the desugared Core $ rlpc -ddump-desugared t.rl # Compile and evaluate t.rl with all compiler messages enabled $ rlpc -dALL t.rl #+end_src ** Options #+begin_src sh Usage: rlpc [-l|--log FILE] [-d DEBUG FLAG] [-f COMPILATION FLAG] [-e|--evaluator gm|ti] [--heap-trigger INT] [-x|--language rlp|core] FILES... #+end_src Available debug flags include: - ~-ddump-desugared~: dump Core generated from rl' - ~-ddump-parsed-core~: dump raw Core AST - ~-ddump-parsed~: dump raw rl' AST - ~-ddump-eval~: dump evaluation logs - ~-dALL~: disable debug message filtering. enables *all* debug messages * Demos [TODO: add hmvis video here] * To-do List ** TODO [#A] rlp to core desugaring :feature: ** DONE [#A] HM memoisation prevents shadowing :bug: CLOSED: [2024-04-04 Thu 12:29] Example: #+begin_src haskell -- >>> runHM' $ infer1 [rlpExpr|let f = \x -> x in f (let f = 2 in f)|] -- Left [TyErrCouldNotUnify -- (ConT "Int#") -- (AppT (AppT FunT (ConT "Int#")) (VarT "$a2"))] -- >>> :t let f = \x -> x in f (let f = 2 in f) -- let f = \x -> x in f (let f = 2 in f) :: Int #+end_src For the time being, I just disabled the memoisation. This is very, very bad. *** Closing Remarks Fixed by entirely rewriting the type inference algorithm :P. Memoisation is no longer required; the bottom-up inference a la Algorithm M was previously hacked together using a comonadic extend with a catamorphism, which, for each node, would fold the entire subtree and memoise the result, which would then be retrieved when parent nodes attempted to infer children nodes. This sucks! It's not "bottom-up" at all! I replaced it with a gorgeous hand-rolled recursion scheme which truly works from the bottom upwards. A bonus specialisation is that it annotates each node with the result of a catamorphism from that node downwards via the cofree comonad. #+begin_src haskell dendroscribe :: (Functor f, Base t ~ f, Recursive t) => (f (Cofree f a) -> a) -> t -> Cofree f a dendroscribe c (project -> f) = c f' :< f' where f' = dendroscribe c <$> f dendroscribeM :: (Traversable f, Monad m, Base t ~ f, Recursive t) => (f (Cofree f a) -> m a) -> t -> m (Cofree f a) dendroscribeM c (project -> f) = do as <- dendroscribeM c `traverse` f a <- c as pure (a :< as) #+end_src ** DONE README.md -> README.org :docs: CLOSED: [2024-03-28 Thu 10:44] ** TODO [#A] ~case~ inference :feature: ** DONE [#A] ADT support in Rlp/HindleyMilner.hs :feature: CLOSED: [2024-04-05 Fri 12:28] ** DONE whole-program inference (wrap top-level in a ~letrec~) :feature: CLOSED: [2024-04-04 Thu 12:42] shadowing issue sucks. i'm going to have to rewrite the whole type inference system later. and i never learn, so i'm gonna use a chronomorphism :3. *** Closing Remarks I don't know how a fucking chronomorphism works. None of the experts can think of a single example of how to use it. The rewrite uses a bottom-up recursion scheme I've dubbed ~dendroscribe~. ** TODO user-supplied annotation support in Rlp/HindleyMilner.hs :feature: ** TODO [#A] update architecture diagram :docs: ** TODO pattern support; everywhere [0%] :feature: - [ ] in the type-checker - [ ] in the desugarer ** TODO [#A] G-machine visualiser :docs: ** TODO [#C] lambda calculus visualiser :docs: ** TODO hmvis does not reload when redefining expressions :bug: To recreate: 1. enter #+begin_src haskell x = 2 #+end_src 2. hit "type-check" 3. edit source to #+begin_src haskell x = \x -> x #+end_src 4. hit "type-check" ** DONE in Rlp/HindleyMilner.hs, fix ~listenFreshTvNames~ :housekeeping: CLOSED: [2024-04-04 Thu 13:17] it /does/ work in its current state, however it captures an unreasonably excessive amount of names, even for a heuristic. *** Closing Remarks Fixed with the proper Algorithm M rewrite. The original purpose of ~listenFreshTvNames~ (tracking monomorphic type variables) has been solved much more cleanly via the (non-monadic!) ~monomorphise~ function paired with the new ~ImplicitInstance~ constraint. ** TODO up-to-date examples [0/2] :docs: - [ ] quicksort (core and rlp) - [ ] factorial (core and rlp) * Releases ** +December Release+ - [X] Tests - [ ] Core lexer - [ ] Core parser - [X] Evaluation model - [ ] Benchmarks - [X] Stable Core lexer - [X] Stable Core parser - [X] Stable evaluation model - [X] Garbage Collection - [ ] Stable documentation for the evaluation model ** +February Release Plan+ - [X] Beta rl' to Core - [X] UX improvements - [X] Actual compiler errors -- no more unexceptional `error` calls - [X] Better CLI dump flags - [X] Annotate the AST with token positions for errors (NOTE: As of Feb. 1, this has been done, but the locational info is not yet used in error messages) - [X] Compiler architecture diagram - [X] More examples ** Final Release Plan SCHEDULED: <2024-04-19 Fri> *** TODO Complete all A-priority checks in the main todo-list!! *** TODO Tests - [ ] rl' parser - [ ] Type inference *** TODO Examples - [ ] quicksort - [ ] factorial - [ ] your typical FP operations -- mapping, folding, etc. *** DONE Ditch TTG in favour of fixed-points of functors Focus on extendability via Fix, Free, Cofree, etc. rather than boilerplate-heavy type families *** DONE rl' type inference *** DONE Core type checking ** Presentation SCHEDULED: <2024-05-10 Fri> *** TODO Documentation - [ ] Type inference / Algorithm M - [ ] The G-Machine *** TODO G-Machine visualiser *** TODO Post-mortem write-up e.g. what would I do differently next time, what have I learned, etc. *** TODO Final polish check [0/3] - [ ] CLI - [ ] G-Machine output - [ ] ~Compiler.JustRun~ module