rl'
- Architecture
- Build Info
- Use
- Demos
- To-do List
- rlp to core desugaring
- HM memoisation prevents shadowing
- README.md -> README.org
caseinference- ADT support in Rlp/HindleyMilner.hs
- whole-program inference (wrap top-level in a
letrec) - user-supplied annotation support in Rlp/HindleyMilner.hs
- update architecture diagram
- pattern support; everywhere
[0%] - G-machine visualiser
- lambda calculus visualiser
- hmvis does not reload when redefining expressions
- in Rlp/HindleyMilner.hs, fix
listenFreshTvNames - up-to-date examples
[0/2]
- Releases
rl' will be a lazily-evaluated, purely-functional, statically-typed language
heavily imitating Haskell.
Build Info
$ 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
Use
TLDR
# 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
Options
Usage: rlpc [-l|--log FILE] [-d DEBUG FLAG] [-f COMPILATION FLAG]
[-e|--evaluator gm|ti] [--heap-trigger INT] [-x|--language rlp|core]
FILES...
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 rlp to core desugaring feature
DONE [A] HM memoisation prevents shadowing bug
CLOSED: [2024-04-04 Thu 12:29] Example:
-- >>> 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
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.
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)
DONE README.md -> README.org docs
CLOSED: [2024-03-28 Thu 10:44]
TODO
case inference feature
TODO ADT support in Rlp/HindleyMilner.hs feature
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 update architecture diagram docs
TODO
pattern support; everywhere [0%] feature
- in the type-checker
- in the desugarer
TODO G-machine visualiser docs
TODO lambda calculus visualiser docs
TODO hmvis does not reload when redefining expressions bug
To recreate:
-
enter
x = 2 - hit "type-check"
-
edit source to
x = \x -> x - 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
-
Tests
- Core lexer
- Core parser
- Evaluation model
- Benchmarks
- Stable Core lexer
- Stable Core parser
-
Stable evaluation model
- Garbage Collection
- Stable documentation for the evaluation model
February Release Plan
- Beta rl' to Core
-
UX improvements
- Actual compiler errors – no more unexceptional `error` calls
- Better CLI dump flags
- 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)
- Compiler architecture diagram
- More examples
March Release Plan
-
Tests
- rl' parser
- Type inference
- Ditch TTG in favour of a simpler AST focusing on extendability via Fix, Free, Cofree, etc. rather than boilerplate-heavy type families
- rl' type inference
- Core type checking