Contributing to the Meow Programming Language
Thank you for your interest in contributing to the Meow Programming Language! This guide covers everything you need to know to get started.
Development Environment Setup
Prerequisites
- Go 1.26+ — required (see
go.mod) - stringer — for code generation of token type names
# Install stringer
go install golang.org/x/tools/cmd/stringer@latest
Clone and Build
git clone https://github.com/135yshr/meow.git
cd meow
go build ./cmd/meow
Run Tests
go test ./...
Build and Run
# Build the compiler
go build ./cmd/meow
# Run a .nyan program
go run ./cmd/meow run examples/hello.nyan
# Show transpiled Go code
go run ./cmd/meow transpile examples/hello.nyan
# Run tests
go test ./...
# Run tests verbose
go test ./... -v
# Static analysis
go vet ./...
# Update golden files (required when changing compiler output)
go test ./compiler/ -update
# Regenerate stringer output (after changing token types)
go generate ./...
Project Structure
flowchart LR
subgraph meow[" meow/ "]
direction TB
subgraph cmd["cmd/meow/ — CLI entry point"]
cmd_main["main.go"]
end
subgraph compiler["compiler/ — Pipeline orchestration + E2E tests"]
comp_go["compiler.go"]
comp_test["compiler_test.go"]
end
subgraph pkg["pkg/"]
token["token/ — Token types, keywords, positions<br/>token.go, tokentype_string.go"]
lexer["lexer/ — iter.Seq-based tokenizer<br/>lexer.go, lexer_test.go"]
ast["ast/ — AST node definitions<br/>ast.go, types.go, walk.go"]
parser["parser/ — Pratt parser (iter.Pull)<br/>parser.go, parser_test.go"]
checker["checker/ — Type checker<br/>checker.go"]
types["types/ — Type system definitions<br/>types.go"]
codegen["codegen/ — AST → Go source generation<br/>codegen.go, codegen_test.go"]
formatter["formatter/ — Code formatter<br/>formatter.go"]
linter["linter/ — Code linter<br/>linter.go"]
mutation["mutation/ — Mutation testing<br/>mutation.go"]
end
subgraph runtime["runtime/"]
meowrt["meowrt/ — Core runtime: Value, operators, builtins<br/>value.go, operators.go, builtins.go, list.go"]
file["file/ — File I/O (snoop, stalk)<br/>file.go"]
http["http/ — HTTP client (pounce, toss, knead, swat, prowl)<br/>http.go"]
testing["testing/ — Test framework (judge, expect, refuse, run)<br/>testing.go"]
coverage["coverage/ — Statement coverage tracking<br/>coverage.go"]
end
examples["examples/ — Sample .nyan programs"]
testdata["testdata/ — Golden file tests (.nyan + .golden)"]
docs["docs/ — Documentation"]
end
Adding a New Keyword
Add the token in
pkg/token/token.go:- Add a constant in the
constblock (betweenkeywordsStartandkeywordsEnd) - Add an entry in the
keywordsmap
- Add a constant in the
Regenerate stringer output:
go generate ./...Update the lexer if needed (usually no changes — keywords are handled by
LookupIdent)Update the parser in
pkg/parser/parser.go:- Add a case in
parseStmt()orparsePrefix()as appropriate - Implement the parsing function
- Add a case in
Add AST node in
pkg/ast/ast.goif neededUpdate codegen in
pkg/codegen/codegen.go:- Handle the new AST node in
genStmt()orgenExpr()
- Handle the new AST node in
Add tests:
- Parser tests
- Golden file tests in
testdata/ - Example in
examples/
Update documentation:
docs/reference.md— add to keywords tabledocs/spec.md— add grammar and semantics- Other docs as appropriate
Adding a New Built-in Function
Implement the function in
runtime/meowrt/builtins.go(orlist.gofor list operations):- Signature:
func Name(args ...Value) Value - Use
"Hiss! ... , nya~"for error messages
- Signature:
Register in codegen — add a case in
pkg/codegen/codegen.go:- In
genCall(), map the Meow name to the Go function name - In
genTypedCall()if needed for typed mode
- In
Add tests:
- Unit tests for the runtime function
- Integration tests (golden files)
Update documentation:
docs/stdlib.md— add function documentationdocs/reference.md— add to built-in functions table
Adding a New Standard Library Package
Create the package at
runtime/<name>/:- All public functions have signature
func Name(args ...meowrt.Value) meowrt.Value - Use
"Hiss! ... , nya~"for errors
- All public functions have signature
Register in codegen — add entry to the
stdPackagesmap inpkg/codegen/codegen.go:var stdPackages = map[string]string{ "file": "github.com/135yshr/meow/runtime/file", "http": "github.com/135yshr/meow/runtime/http", "testing": "github.com/135yshr/meow/runtime/testing", "mypackage": "github.com/135yshr/meow/runtime/mypackage", // new }The existing
genMemberCallhandles routing automatically — no other codegen changes neededUsers will write:
nab "mypackage" mypackage.my_func("arg")Add tests:
- Unit tests in
runtime/<name>/<name>_test.go - Integration test with
nab
- Unit tests in
Update documentation:
docs/stdlib.md— add package sectiondocs/reference.md— mention the package
Adding a Lint Rule
Implement the rule in
pkg/linter/linter.goAdd tests for the new rule
Update documentation — mention the rule in
docs/effective-meow.md
Testing Conventions
Golden File Tests
Located in testdata/ with .nyan input and .golden expected output:
flowchart LR
subgraph testdata["testdata/"]
nyan["hello.nyan — Input program"]
golden["hello.golden — Expected output"]
end
Run golden tests:
go test ./compiler/
Update golden files when output changes:
go test ./compiler/ -update
Unit Tests
Standard Go _test.go files in each package. Follow Go testing conventions:
func TestSomething(t *testing.T) {
// ...
}
HTTP Tests
Use httptest.NewServer for local testing (see runtime/http/http_test.go).
Panic Tests
Use defer func() { recover() }() to test Hiss! error paths:
func TestHissOnInvalidInput(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("expected panic")
}
}()
SomeFunction(invalidInput)
}
Commit Style
We use gitmoji prefixes in commit messages:
| Prefix | Usage |
|---|---|
✨ feat: | New feature |
🐛 fix: | Bug fix |
♻️ refactor: | Code refactoring |
📝 docs: | Documentation |
✅ test: | Adding/updating tests |
🎨 style: | Code style/formatting |
⬆️ chore: | Dependencies/tooling |
🚀 ci: | CI/CD changes |
🔧 config: | Configuration changes |
Commit messages are in English.
Example:
✨ feat: Add string interpolation support
PR Process
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes with tests
- Ensure all tests pass:
go test ./... - Ensure code passes vet:
go vet ./... - Commit with gitmoji prefix
- Push and open a Pull Request
PR Checklist
- Tests pass (
go test ./...) - No vet warnings (
go vet ./...) - Golden files updated if output changed (
go test ./compiler/ -update) - Stringer regenerated if tokens changed (
go generate ./...) - Documentation updated for new features
- Commit messages use gitmoji prefix
Dependencies
Meow has zero runtime dependencies — standard library only. Development tools like stringer are allowed as build-time dependencies. Please do not introduce third-party runtime packages.