Contributing
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.