209 lines
7.1 KiB
Org Mode
209 lines
7.1 KiB
Org Mode
#+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
|
|
|