NOTES.md (3795B)
[https://github.com/gingerBill/titania]
[https://news.ycombinator.com/item?id=45243925]
[https://people.inf.ethz.ch/wirth/Oberon/Oberon07.Report.pdf]
[https://people.inf.ethz.ch/wirth/ProjectOberon/PO.System.pdf]
add_operator = "+" | "-" | "xor" | "or".
mul_operator = "*" | "/" | "%" | "and".
see
Tokenizer Semicolon Insertion Rules
When a newline is seen after the following token kind, a semicolon is inserted, otherwise no semicolon is inserted:
...list
Gleam my new obsession
I love Rust, but...
[https://ericcodes.io/blog/gleam-my-new-obsession.html]
(`antirez/sds` for dynamic strings, `nothings/stb_ds` for dynamic arrays and hashmaps, and `cxong/tinydir` for reading the filesystem).
[https://old.reddit.com/r/Compilers/comments/1nmc3r9/i_wrote_a_compiler_for_a_large_subset_of_c_in_c/]
How to make stuff private and discussion on design (just mangle the names if needed)
[http://journal.stuffwithstuff.com/2025/05/26/access-control-syntax]
# symbols
- jack int 1
- test void->void 1
alice float 2
- main void->void 1
peter strings 2
- jill int 1
# Zed
[https://zed.dev/docs/extensions/developing-extensions]
# libgccjit doco
[https://gcc.gnu.org/onlinedocs/gcc-15.1.0/jit/]
# license
the hare license at the bottom
https://sr.ht/~sircmpwn/hare/
the standard library is under MPL, the compiler and executables are under GPL3
# walk down, compute bubbling up
RDP (Root‑Descend‑Process)
- Push "stacks" as you descend, nodes and local state
- Process and pop the frame off on the way back up and merge or "combine" result with its parent.
Expr ::= Add(Expr, Expr)
| Mul(Expr, Expr)
| Num(Int)
R‑D‑P Application
1. Root: Add( Mul(Num(2), Num(3)), Num(4) )
2. Descend:
- Push Add frame.
- Push left child Mul.
- Push left child Num(2) → leaf → Process → result = 2.
- Push right child Num(3) → leaf → Process → result = 3.
- Process Mul → result = 6.
- Push right child Num(4) → leaf → Process → result = 4.
3. Process Add → result = 10.
** Forget the whole tree, focus on this node and reason locally. **
R‑D‑P (Root‑Descend‑Process) turns recursive AST evaluation into a clear, iterative algorithm.
Pair it with bottom‑up traversal, the visitor pattern, or an explicit stack to keep state explicit.
This approach reduces cognitive load by isolating each node’s processing and avoiding hidden call‑stack dependencies.
Keep a whiteboard model of the tree shapes.
- Base case – literals and identifiers return a value immediately.
- Recursive step – always evaluate child nodes before applying the operator at the current node.
- After return – combine child results according to the operation; this is where side‑effects (e.g., assignment) may occur.
see [[TODO]]
## Only pure constant expressions are evaluated at compile time
print has side effects so it doesn't
2 + 3 is not run by the compiler, but it may be constant-folded in the optimizer.
you lower print to a runtime call printf
### CTFE compile time function execution
- constant expression, constant folding and propagation
- evaluator / constant interpreter
- restricted evaluator in the compiler, with env and CT heap
- try_ctfe on expression nodes
- lowering: emit literal value to IR once folded
- C++: consteval, Zig: comptime, Rust: constfn
- gate with fuel(?), depth restriction and memory limits
add_to_scope is used during semc
add_symbol is used during genc, feels wrong
when we semc we need to build the scope and symbols list for each
but then in gen we need to fetch the symbols and pad them with pointers
separate the gccjit impl to a separate tree than the symbols table of semantic analysis