| name | implement-feature |
| description | Use when adding a new Brainrot language feature — a keyword, operator, builtin function, or grammar construct. Covers the lexer→parser→AST→semantic-analyzer→interpreter pipeline and the fixture/expected-output test pattern this repo uses. |
When to Use
The user asks to add a new keyword, operator, control-flow construct, type, or
stdlib (stdrot) builtin, or to extend an existing one (e.g. implement one of
the ❌ rows in the README keyword table, like gyatt/enum or chungus/union).
Step-by-Step Instructions
- Check scope first. Read
README.md's keyword/preprocessor tables and
docs/the-brainrot-programming-language.md to see if the feature is already
partially implemented or has a reserved meme name. Grep lang.l/lang.y
for the token before assuming it's new.
- Lexer (
lang.l): add the token if it's a new keyword/operator.
- Grammar (
lang.y): add/extend the production rule. Run
bison -d -Wcounterexamples lang.y -o lang.tab.c mentally in mind that
shift/reduce conflicts will fail the build (-Wcounterexamples).
- AST (
ast.c/h): add the node type/constructor if the construct needs
new AST shape.
- Semantic analysis (
semantic_analyzer.c/h): add type-checking / scope
rules. This is the most bug-prone layer (see recent history of sanitizer
fixes) — mind ownership of any String/pointer values you allocate.
- Interpreter/visitor (
interpreter.c/h, visitor.c/h, or a new file
under stdrot/ for a builtin): implement the runtime behavior.
- Wire builtins: if adding a
stdrot function, register it in
stdrot/registry.c and declare it in stdrot/stdrot_api.h.
- Add a test fixture: create
test_cases/<feature>.brainrot exercising
the happy path (and a separate file for an error case if relevant, following
the semantic_error_*.brainrot / *_fail.brainrot naming pattern).
- Add expected output: run
./brainrot test_cases/<feature>.brainrot
locally, verify the output is correct, then add it verbatim to
tests/expected_results.json keyed by the fixture's basename.
- Add an example (optional but preferred for user-facing features) in
examples/ and link it from examples/README.md.
- Update docs: mark the feature ✅ in
README.md's table and describe it
in docs/the-brainrot-programming-language.md if it's a builtin/keyword.
- Build and test:
make && make test && make valgrind. All three must
pass — the build uses -Werror -fsanitize=address,undefined. Also run
make format-check (or make format to fix) — CI's lint job blocks on
any diff.
- Open the PR using
.github/PULL_REQUEST_TEMPLATE.md: fill in every
section (Description, Related Issue, Type of Change, Checklist) — don't
submit a bare description.
Conventions and Best Practices
- Match the meme-naming spirit but don't invent new slang without checking
TRUTH.md/README for an already-agreed name; ask the user if unsure.
- Keep grammar rules narrow — prefer extending an existing production over
duplicating one, to avoid new shift/reduce conflicts.
- Follow the C style in AGENTS.md: 4-space indent,
snake_case, Allman braces, ~80 cols.
- New allocations go through
lib/arena.c or lib/mem.c where the surrounding
code already does, for consistency with existing memory-safety fixes.
Important Notes
- Never hand-edit
lang.tab.c, lang.tab.h, or lex.yy.c — they're
regenerated by make and gitignored.
- If the feature can't be fully implemented, don't half-wire it silently
(e.g. token added but no grammar rule) — either finish the slice end-to-end
or clearly flag what's stubbed.