{"owner":"vlang","repo":"v","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"files":{"AGENTS.md":"<!-- V_AGENTS.md  v1.1  2026-02-04 -->\n\n# V Repo Guide\n\nPractical quick reference for the V compiler, standard library, and tools.\nWritten for AI coding agents; useful for humans too.\n\n## Contents\n* Quick Start\n* Top Rules\n* Agent Rules\n* Safety (Do Not Brick the Repo)\n* Divergences From Repo Docs\n* Quick Decisions\n* Common Workflow\n* Reporting\n* Prerequisites\n* Build & Rebuild\n* Run Programs\n* Testing\n* Code Style\n* Modules and Imports\n* C/JS Interop Hygiene\n* Environment-Specific Code (files and `$if`)\n* Compile-Time Code and Reflection\n* Debug\n* Compiler Architecture\n* Key Directories\n* Test Locations\n* Error Reporting (checker/parser)\n* Option/Result Types\n* Tools\n* Commits and PRs\n* Environment Variables\n* Gotchas\n\n## Quick Start\nGet operational from the repo root in three steps:\n\n1. Build once (only if `./v` is missing): `make`\n2. Build a working compiler:\n   * Debug-friendly (recommended): `./v -g -keepc -o ./vnew cmd/v`\n3. Use `./vnew` for everything:\n   * Run a file: `./vnew run examples/hello_world.v`\n   * Run tests: `./vnew -silent test vlib/v/`\n   * Format: `./vnew fmt -w path/to/file.v`\n\nThen read Top Rules and Agent Rules before making changes.\n\n## Top Rules\n* Use `./v` only to build `./vnew`; use `./vnew` for everything else.\n* Put all V flags immediately after `./vnew` and before the\n  subcommand/file, e.g. `./vnew -g run file.v`\n  (not `./vnew run file.v -g`); flags after the subcommand are passed\n  to that subcommand.\n* Rebuild `./vnew` after compiler or core module changes\n  (see Build & Rebuild).\n* Run the smallest relevant tests; see Testing for triggers and\n  minimums.\n* Ask before large refactors or wide file touches (see Agent Rules).\n* Do not stash or modify unrelated files unless explicitly instructed.\n* This guide assumes agents run locally, not in CI; CI notes are\n  informational only.\n* When a summary is required, include behavior change, tests run, and\n  touched file paths.\n* If instructions overlap, prefer Build & Rebuild, Testing, and\n  Reporting.\n* If duplicates drift, treat Build & Rebuild, Testing, and Reporting as\n  canonical and align other sections to them.\n\n## Agent Rules\n\n### Repo root\nAll commands assume the repo root as the working directory. The default\nlocation is `/opt/v`, but this may differ in your environment. If a\ncommand fails due to missing paths, verify with `pwd` and adjust\naccordingly. Use a per-command workdir only when a task requires a\nsubdir.\n\n### Tone and output\n* Be concise by default. If the user asks for depth, provide it while\n  keeping structure tight.\n* Keep output easy to scan: short sections, bullets when listing,\n  commands in backticks, no filler.\n* Use a strict, operational tone unless higher-priority instructions\n  override it.\n* Ask only when required. If information is missing, ask a direct\n  question.\n\n### File access and edit scope\n* You may read and edit all files in the V repo without asking for\n  permission. This is file access, not change scope; scope is\n  constrained below. Reading is always OK.\n  Edits to `ci/` or `Dockerfile*` still require an explicit ask.\n* Run build, test, and format commands without asking for permission.\n  These are validation steps, not code changes. Only ask about edit\n  scope, not about running `fmt`, targeted tests, or `check-md`.\n* Only modify files required for the user request; avoid unrelated\n  refactors. If duplication is harmful, small refactors to remove it\n  are OK only when needed. Only refactor duplication in code you are\n  already touching, and only when it directly supports the request or\n  fixes a bug there. \"Touching\" means files already modified for the\n  request.\n* Avoid unrelated file changes; call them out if present.\n* Avoid touching `thirdparty/` unless explicitly requested. If changes\n  are needed there, ask for approval before proceeding.\n\n### When to ask\n* Ask before large refactors or wide file touches across multiple repo-root\n  directories like `cmd/`, `vlib/`, `doc/`, and `examples/`.\n  Exception: docs-only changes across many files are OK without asking;\n  call them out in the summary.\n* Ask before large behavioral changes within a single subsystem or file,\n  even if the file count is small. Examples: changes to parser rules,\n  checker resolution, codegen output shape, diagnostic text/ordering, or\n  tool CLI behavior. Large means user-visible changes in CLI flags,\n  output, diagnostics, or codegen shape. If unsure whether a change is\n  \"large,\" ask.\n* Ask before touching `ci/` or `Dockerfile*` unless explicitly\n  requested. If changes are needed there, confirm whether local\n  validation is expected or if CI-only coverage is acceptable.\n\n### Bootstrap\n* Bootstrap/compiler usage rules: see Top Rules and Build & Rebuild.\n\n### Completeness and summaries\n* If you cannot complete a requested step, state the blocker and partial\n  progress (what was attempted and what remains).\n* After substantial work, provide a short summary and list touched file\n  paths. Substantial work means any behavioral change, or changes in\n  more than one file. Always include tests run (or \"Not run\" with\n  reason) in the summary.\n* Never change tests just to silence failures. Update expectations only\n  when behavior changes are intended, and note the rationale in the\n  summary.\n\n### New files and deeper guidance\n* New file checklist: format with `./vnew fmt -w`, add doc comments for\n  any public functions, run `./vnew check-md` for markdown files, and\n  keep Markdown lines <= 100 chars. Add or update tests when introducing\n  a new public API.\n* For deeper edge cases, consult `CONTRIBUTING.md` and `TESTS.md`.\n\n## Safety (Do Not Brick the Repo)\n* Do not overwrite the working `./v` binary.\n  * Never run `./v self` without `-o`.\n  * Build with `./v -o ./vnew cmd/v`, then use `./vnew` for all checks.\n* Keep generated C when debugging backend issues: add `-keepc`.\n* Avoid hidden/bidirectional Unicode characters in source/markdown\n  files.\n* If the compiler becomes unusable, recover with:\n  1. `git stash`\n  2. `make`\n  3. `git stash apply`\n  Check `git status` before stashing to avoid hiding unrelated work.\n  Do not stash unless explicitly instructed or the compiler is bricked.\n\n## Divergences From Repo Docs\nThe repo docs use `v` in examples. In this environment:\n* Use `./v -g -keepc -o ./vnew cmd/v` instead of `v self`.\n* Use `./vnew` for all builds, runs, and tests.\n* `TESTS.md` suggests `v test-all` before PRs; ask before running\n  `./vnew test-all`.\nThese overrides exist to keep agent workflows reproducible and to avoid\nbreaking the bootstrap compiler.\n\n## Quick Decisions\n* For rebuild and test choices, follow Build & Rebuild and Testing.\n* Follow Common Workflow for the default execution order.\n* For broader workflow guidance, see `CONTRIBUTING.md`.\n\n### Compact decision table (rebuild/tests)\nUse this table to pick the minimum rebuild/tests quickly. See Build &\nRebuild and Testing for full details and edge cases.\nCommands omit `./vnew` for brevity; assume the `./vnew` prefix.\nThis table is the minimum set; check Testing for additional triggers.\nREPL and backend changes have additional triggers in Testing.\nNote: `cmd/v/` is compiler scope; treat changes there as compiler\nchanges.\nWhen in doubt, ask before proceeding.\nIf you read only one section for tests, **read Testing**.\n\n| Change area | Rebuild? | Minimum tests to run |\n| --- | --- | --- |\n| Docs only (`.md`) | No | `check-md file.md` |\n| Compiler (`vlib/v/`, `cmd/v/`) | Yes | `-silent vlib/v/compiler_errors_test.v`; `test vlib/v/` |\n| Core modules (builtin/strings/os/strconv/time) | Yes | Smallest relevant tests |\n| Parser-only (`vlib/v/parser/`) | Yes | `test vlib/v/parser/` |\n| Checker-only (`vlib/v/checker/`) | Yes | `test vlib/v/checker/` |\n| Comptime (`vlib/v/comptime/`) | Yes | `test vlib/v/tests/`; comptime-related tests |\n| vlib (non-compiler) | No | Nearest `*_test.v` or `test vlib/path/` |\n| Tools (`cmd/tools/`) | No | Tool-specific test; else nearest `*_test.v` |\n| Diagnostic/output changes | Yes | `vlib/v/slow_tests/inout/compiler_test.v` |\n| C codegen (`vlib/v/gen/c/`) | Yes | `vlib/v/gen/c/coutput_test.v` |\n\n## Common Workflow\n0. Before work: `git status`; ensure `./vnew` exists; rebuild if needed.\n   If `./vnew` is missing, see Quick Start or Build & Rebuild.\n1. Edit the relevant files.\n2. If compiler sources or core modules changed, rebuild `./vnew` with\n   `./v -g -keepc -o ./vnew cmd/v` (see Build & Rebuild).\n3. Format touched `.v`/`.vsh` files and run `./vnew check-md` on\n   touched markdown.\n4. Run the smallest relevant tests for the change scope (see Testing).\n\nSee Build & Rebuild for rebuild triggers and flags.\n\n## Reporting\n* When a summary is required (see Agent Rules), it must include:\n  * Behavior changes (or \"No behavior change\").\n  * Tests run (or \"Not run\" with a reason).\n  * Touched file paths.\n  * Note unrelated changes if present.\n  * Note doc updates if public behavior/tool output changed.\n* If public behavior or tool output changes, update relevant docs\n  (README.md, `doc/`, `tutorials/`) and note it.\n  For example: README.md for top-level CLI usage, `doc/` for\n  compiler/tool docs, `tutorials/` for learning material.\n* If you add or change a public API, update module docs or README and\n  note it. Public API includes stdlib functions/types and user-visible\n  compiler flags, diagnostics, tool CLI behavior (including `cmd/tools`\n  and stdlib CLI tools), or output formats.\n* Update `CHANGELOG.md` or `ROADMAP.md` only when explicitly requested.\n* Public behavior includes compiler output, diagnostics, user-facing\n  CLI, and stdlib API. This includes developer-facing flags, error\n  codes, or output ordering changes.\n* Internal refactors with no public behavior change do not require doc\n  updates.\n* If unsure whether behavior is public, ask the user before updating\n  docs.\n* Acceptable reasons for not running tests: docs-only change, no\n  relevant tests, or environment constraints. Be specific.\n* Docs-only changes: run `./vnew check-md file.md`; no other tests\n  required unless a test explicitly reads those docs.\n  No rebuild is needed unless compiler or core modules changed.\n* For docs-only, explicitly mention `check-md` in the summary.\n* If you update `.out` files, state the rationale in the summary.\n* Do not update `.out` files unless a behavior change is intended;\n  otherwise treat mismatches as regressions.\n* Example summary line: `Behavior change: none` or\n  `Behavior change: fixed X`.\n* Behavior change includes output, API, error messages, and test\n  expectations.\n* If blocked, note what was attempted and why it failed.\n* If tooling/network restrictions block a step, state the restriction\n  and the closest viable alternative.\n* Use `git status` to confirm touched files before reporting.\n\n## Prerequisites\n* Toolchain: `make`, `git`, and a C compiler (`clang` or `gcc`).\n* Windows: use `makev.bat` for the initial build.\n\n## Build & Rebuild\n* Initial build (only if `./v` is missing): `make`\n  (Windows: `makev.bat`).\n* Build `./vnew` (debug-friendly, recommended for agent workflows):\n  `./v -g -keepc -o ./vnew cmd/v`\n* Never run `./v self` directly; only build `./vnew` with the commands\n  above.\n* If `./v` is missing, run `make` first, then build `./vnew`.\n* If `./vnew` is missing but `./v` exists, run `./v -o ./vnew cmd/v`.\n* This section is the source of truth for rebuild triggers.\n  If a rule appears elsewhere, defer to this section.\n* Rebuild triggers:\n  * Compiler sources in `vlib/v/` or `cmd/v/`.\n  * Core modules: `builtin`, `strings`, `os`, `strconv`, `time`.\n* If `./v` exists but compiler sources changed, still rebuild `./vnew`\n  before tests.\n* If unsure whether compiler/core changes happened, rebuild `./vnew`.\n* Common flags:\n  * `-g` debug info (V line numbers).\n  * `-cg` debug info (C line numbers); often combined with `-keepc`.\n  * `-keepc` keep generated C file(s).\n  * `-prod` optimized build.\n  * `-o file` output path/name.\n  * `-cc clang` pick a C compiler.\n  * `-cstrict` be stricter about the generated C.\n  * `-b js|native|wasm` select a backend.\n  * `-os <os>` cross-compile target selection (when supported).\n\n## Code Style\n* Comments: add succinct comments only when code is not self-explanatory.\n  Do not delete existing comments unless they are incorrect; you may fix\n  grammar or spelling without changing meaning.\n  Add V doc comments right before each new or modified public function\n  or method.\n  The V doc comments should start with the name of the fn,\n  example: `// the_name does ...`\n* Copy pasta: avoid copy pasta. If there's duplicate logic, move to a\n  function only when it is required for the request and within code you\n  are already touching.\n* Avoid using `unsafe{ code }` blocks where possible, and minimize\n  their scope. `unsafe` is acceptable for low-level interop (e.g. C\n  pointer casts, manual memory management) but should never wrap\n  ordinary V logic. When `unsafe` is required, keep the block as small\n  as possible and add a comment explaining why it is necessary.\n* Keep Markdown lines <= 100 chars (the checker is strict).\n  Apply to touched lines in modified Markdown files.\n* Avoid hidden/bidirectional Unicode characters in source/markdown\n  files.\n* Non-V files: keep existing formatting; only reformat if required by\n  the change.\n* Treat `.vv` files in `vlib/v/slow_tests/inout/` as fixtures; avoid\n  formatting unless a behavior change is intended and output\n  expectations are updated.\n* Formatting and check commands are in Tools.\n\n## Modules and Imports\n* Module names must match their directory name (no hierarchy in the\n  `module` line). Mismatches cause silent import failures.\n* Imports follow the folder hierarchy (e.g. `import abc.def`).\n\n## C/JS Interop Hygiene\n* Avoid using `C.` or `JS.` symbols in plain `.v` files.\n  * Use `.c.v` / `.js.v` files.\n  * Enable `-Wimpure-v` to catch accidental impurity.\n* Do not refactor existing `C.`/`JS.` uses in `.v` files unless\n  required. If you must change those lines, prefer moving the interop\n  code to `.c.v`/`.js.v`.\n* For C interop, use correct `const_` prefixes in C function\n  redeclarations when needed (helps with `-cstrict` and C static\n  analysis tooling).\n\n## Environment-Specific Code (files and `$if`)\nV supports environment-specific file suffixes. Prefer them when the\nwhole file is platform/backend specific.\n\nCommon patterns:\n* Backend splits:\n  * `*.c.v` (C backend), `*.js.v` (JS backend), `*.native.v` (native\n    backend), `*.wasm.v` (WASM backend)\n* OS splits:\n  * `*_windows.c.v`, `*_linux.c.v`, `*_nix.c.v`, with `*_default.c.v`\n    as fallback\n* Flag splits:\n  * `*_d_customflag.v` is included only with `-d customflag`\n  * `*_notd_customflag.v` is included only when that flag is NOT passed\n\nNotes:\n* Do not use combinatorial suffixes like `_d_flag_linux.c.v`; use\n  `_d_flag.v` plus `$if linux {}` inside the file.\n* For smaller platform differences, use compile-time `$if` blocks:\n  * `$if windows { ... } $else { ... }`\n* See Compile-Time Code and Reflection for the full `$if` reference.\n\n## Compile-Time Code and Reflection\nV uses `$` as a prefix for compile-time (comptime) operations. These\nare evaluated by the compiler, not at runtime. AI agents frequently\nconfuse comptime and runtime constructs; this section clarifies the\nboundaries.\n\n### Compile-time `$if`\n`$if` evaluates conditions at compile time. It is not a runtime `if`.\nUse it for platform, compiler, and custom-flag checks:\n* `$if windows { ... } $else $if linux { ... } $else { ... }`\n* `$if debug { ... }` (enabled by `-g` or `-cg`)\n* `$if prod { ... }` (enabled by `-prod`)\n* `$if custom_flag ? { ... }` (enabled by `-d custom_flag`)\n\nFull list of builtin `$if` options: see the table at\n<https://docs.vlang.io/conditional-compilation.html>.\n\nCommon mistakes:\n* Using runtime `if` where `$if` is needed for platform-specific code.\n  Runtime `if` will fail to compile if it references platform-specific\n  symbols; `$if` excludes the block entirely on non-matching platforms.\n* Forgetting the `?` suffix for custom flags: `$if myflag ? { ... }`.\n  Without `?`, the compiler treats it as a builtin option and silently\n  ignores it.\n\n### Compile-time `$for`\n`$for` iterates over type metadata at compile time. It works with:\n* `StructType.fields` - iterate struct fields\n* `StructType.methods` - iterate struct methods\n* `EnumType.values` - iterate enum values\n* `StructType.attributes` - iterate struct attributes\n* `SumType.variants` - iterate sum type variants\n* `method.params` - iterate method parameters\n\nInside `$for` blocks, use `$if` to branch on field/method types:\n```v oksyntax\nfn main() {\n\t$for field in MyStruct.fields {\n\t\t$if field.typ is string {\n\t\t\tprintln(field.name)\n\t\t}\n\t}\n}\n```\n\nAlso works with generics: `T.fields`, `param.fields` where\n`fn gen[T](param T) {}`.\n\nCommon mistakes:\n* Using runtime `for` to iterate struct fields. This does not work;\n  V has no runtime reflection. Always use `$for`.\n* Calling `obj.$method()` outside a `$for m in Type.methods` block.\n  The `$method()` call is only valid inside a comptime method\n  iteration.\n* Assuming comptime `$for` produces a runtime loop. It does not; the\n  compiler unrolls it into concrete code for each field/method/variant.\n\n### Compile-time functions\nOnly the following `$`-prefixed functions are supported:\n* `$embed_file('path')` - embed a file's contents into the binary.\n  Paths can be absolute, relative to the source file, or use pseudo\n  variables like `@VEXEROOT` or `@VMODROOT`.\n* `$tmpl('path')` - compile a V template file (used by veb).\n* `$env('VAR')` - read an environment variable at compile time.\n* `$d('ident', default)` - read a `-d ident=value` compile-time\n  define, with a default fallback.\n* `$res('path')` - embed a resource (Android).\n* `$compile_error('msg')` - emit a compile-time error.\n* `$compile_warn('msg')` - emit a compile-time warning.\n* `$pkgconfig('name')` - query pkg-config at compile time.\n\nCommon mistakes:\n* Inventing comptime functions that do not exist (e.g. `$typeof`,\n  `$sizeof` as comptime calls). Use `typeof(expr).name` and\n  `sizeof(Type)` instead; these are builtins, not `$`-prefixed.\n* Assuming `$embed_file` returns a string. It returns an\n  `EmbedFileData` object; use `.to_string()` or `.to_bytes()`.\n* Using `$env` where a runtime `os.getenv` is appropriate, or vice\n  versa. `$env` is baked in at compile time and cannot change at\n  runtime.\n\n### Compile-time pseudo variables\nThese are `@`-prefixed identifiers substituted at compile time:\n* `@FN` - current function name.\n* `@METHOD` - `ReceiverType.MethodName`.\n* `@MOD` - current module name.\n* `@STRUCT` - current struct name.\n* `@FILE`, `@DIR`, `@LINE`, `@COLUMN`, `@FILE_LINE` - source\n  location.\n* `@LOCATION` - file, line, and current type+method; good for logging.\n* `@VEXE`, `@VEXEROOT` - path to the V compiler and its directory.\n* `@VHASH`, `@VCURRENTHASH` - compiler commit hashes.\n* `@VMOD_FILE`, `@VMODHASH`, `@VMODROOT` - nearest `v.mod` info.\n* `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP` - build time (UTC).\n  Override with the `SOURCE_DATE_EPOCH` env var for reproducible\n  builds.\n* `@OS`, `@CCOMPILER`, `@BACKEND`, `@PLATFORM` - build environment.\n\n### Compile-time type groups\nComptime type groups combine multiple types into a higher-level type\nfor use in generic or comptime `$if` checks:\n* `$int` - all integer types\n* `$float` - all float types\n* `$array` - all array types\n* `$map` - all map types\n* `$struct` - all struct types\n* `$enum` - all enum types\n* `$alias` - all type aliases\n* `$sumtype` - all sum types\n* `$function` - all function types\n* `$interface` - all interface types\n* `$option` - all option types\n\nExample: `$if field.typ is $int { ... }`\n\n### Comptime changes and testing\nComptime logic lives in `vlib/v/comptime/` and is exercised by the\nchecker, parser, and cgen stages. Changes here require a rebuild of\n`./vnew` and should be tested with `./vnew -silent test vlib/v/tests/` plus\nany comptime-specific tests. See the decision table and Testing.\n\n## Run Programs\n* Compile and run: `./vnew run file.v`.\n* Just compile: `./vnew file.v` (creates executable).\n* With debug info: `./vnew -g run file.v`.\n* Debug run (C line numbers): `./vnew -keepc -cg run file.v`.\n* Example: `./vnew run examples/hello_world.v`.\n\n## Testing\nRun:\n* File (shows test output): `./vnew path/to/file_test.v`.\n* File (test runner report only): `./vnew test path/to/file_test.v`.\n* Dir: `./vnew -silent test path/to/dir/`.\n* Dir with statistics/metrics: `./vnew -stats test path/to/dir/`.\n* Compiler: `./vnew -silent vlib/v/compiler_errors_test.v`.\n* Fix outputs (only when intended):\n  `VAUTOFIX=1 ./vnew -silent vlib/v/compiler_errors_test.v`.\n* All: `./vnew test-all`.\n  Ask before running `./vnew test-all` unless explicitly requested.\n\nWhen:\n* Rule of thumb: for localized changes, run the smallest relevant\n  tests. If any trigger below matches, run the listed tests.\n* Minimum tests listed are the floor, not the ceiling; add targeted\n  tests for cross-cutting changes.\n* If unsure which tests apply, ask the user before proceeding.\n* If in doubt, prefer the smallest targeted test and ask.\n* Run all tests that apply. Start with the smallest targeted tests;\n  add slow tests as needed. Order does not matter.\n* Compiler changes (`vlib/v/` or `cmd/v/`):\n  Run `./vnew -silent vlib/v/compiler_errors_test.v`,\n  `./vnew -silent test vlib/v/`.\n* Parser-only changes (`vlib/v/parser/`):\n  Run `./vnew -silent test vlib/v/parser/`.\n* Checker-only changes (`vlib/v/checker`):\n  Run `./vnew -silent test vlib/v/checker/`.\n* vlib changes: Run nearest `*_test.v` or\n  `./vnew -silent test vlib/path/`.\n* Tool changes (`cmd/tools/`): Run tool-specific tests. If none exist,\n  run the smallest relevant `*_test.v` that exercises the tool.\n  Note: `cmd/v/` is compiler scope, not tools.\n  Examples: `cmd/tools/vfmt` -> `vlib/v/fmt/fmt_test.v` .\n  `cmd/tools/vdoc` -> `cmd/tools/vdoc/vdoc_test.v`.\n* Diagnostic/output changes:\n  Run `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.\n* C codegen changes: Run `./vnew -silent vlib/v/gen/c/coutput_test.v`.\n  Consider a stricter validation pass:\n  `./vnew -cstrict -cc clang -silent test vlib/v/`.\n* REPL changes: Run `./vnew -silent vlib/v/slow_tests/repl/repl_test.v`.\n* Broad refactors: Run `./vnew -silent test-all`.\n* Backend-specific changes: run the smallest relevant tests for the\n  affected backend. JS/native/WASM backends are incomplete, so avoid\n  broad `-b <backend> test vlib/` runs. Prefer targeted `*_test.v`\n  files or small test dirs with `-b js|native|wasm`.\n\nIf time-constrained, prioritize\n`./vnew -silent vlib/v/compiler_errors_test.v` and the smallest targeted tests.\nRun `vlib/v/slow_tests/inout/compiler_test.v`\nand `vlib/v/gen/c/coutput_test.v` when output or codegen changes are\nlikely.\nSee `TESTS.md` for more guidance on test selection and output\nexpectations.\nSee `CONTRIBUTING.md` for broader workflow guidance.\n\nConcrete triggers:\n* `vlib/v/slow_tests/inout/compiler_test.v` when error text or output\n  formatting changes, or changes in checker/parser error reporting.\n* `vlib/v/gen/c/coutput_test.v` for changes under `vlib/v/gen/c/` or\n  C codegen output paths.\n\nTypes:\n* Standard: `*_test.v` files with `test_` functions.\n* Output: `.vv` source + `.out` expected output in\n  `vlib/v/slow_tests/inout/`.\n  Example: `./vnew -silent vlib/v/slow_tests/inout/compiler_test.v`.\n* `vlib/v/tests/**` may use `.run.out` expectations; run with\n  `./vnew -silent test vlib/v/tests`.\n\nDocs-only guidance: see Reporting.\nIf time-boxed, run at least the smallest relevant test and note\nskipped coverage in the summary.\n\n### Useful env variables and flags while testing\n* `VAUTOFIX=1` - Auto-update .out files when tests fail (run twice).\n  Use only when a behavior change is intended.\n* `VTEST_ONLY=glob_pattern` - Run only tests matching pattern.\n* `VTEST_HIDE_OK=1` - Hide successful tests, show only failures.\n* `./vnew -silent test path/to/dir/` - Show only failed tests (if any), and a summary report.\n* `-cc tcc` can speed test builds when TCC is available.\n* Output expectations: update `.out` files only when behavior changes\n  are intended; note the rationale in the summary.\n\n## Debug\n* See what the C compiler is doing:\n  * `-showcc` prints the C compile command.\n  * `-show-c-output` prints the C compiler output.\n* Build a temporary compiler for debug flags:\n  * `./vnew -o ./w -d trace_checker cmd/v`\n  * Then run: `./w file.v`\n* Keep and inspect generated C:\n  * `-keepc -cg` is the common combo.\n  * `-printfn <name> -o file.c` emits only the named C function to standart\n    output. The `name` uses the `modulename__fnname` format (e.g.\n    `main__main`). This flag can be repeated to print multiple\n    functions. Methods/generics may use more complex C names; use\n    `-keepc` to confirm exact symbols.\n* Trace stages:\n  `-d trace_scanner|trace_parser|trace_checker|trace_gen`.\n  These flags can help diagnose a problem when a stage stops earlier\n  than expected.\n* Time stages: `-d time_parsing|time_checking`.\n* V panics: `-keepc -g`.\n* C segfaults: `-keepc -cg -cc clang`.\n* JS/native/wasm: prefer small, focused test files with\n  `-b js|native|wasm` and `-show-c-output` where applicable; avoid\n  broad `-b <backend> test vlib/`.\n* Quick code location technique:\n  When debugging code generation issues, add unique comment tags to\n  relevant code generation points (e.g., `/*tom51*/`) in the compiler\n  source. Rebuild and generate C code, then search the generated file for these\n  tags to quickly map generated C code back to the exact compiler source\n  location. This is especially useful when multiple code paths generate\n  similar-looking output and you need to identify which path is actually used.\n  Example:\n  ```v\n  // In vlib/v/gen/c/assign.v:\n  g.write('builtin___option_ok/*tom51*/(&(${styp}[]) { ')\n\n  // After rebuild, search generated C code for \"tom51\":\n  // builtin___option_ok/*tom51*/(&(int[]) { ... });\n  ```\n  Remember to remove these debug tags after fixing the issue.\n\n## Compiler Architecture\nThe V compiler has the following stages, orchestrated by the\n`v.builder` module:\n`v.scanner` -> `v.parser` -> `v.checker` -> `v.transformer` ->\n`v.markused` -> `v.gen.c`\nTheir corresponding folders are: vlib/v/scanner, vlib/v/parser,\nvlib/v/checker, vlib/v/transformer, vlib/v/markused, vlib/v/gen/c .\nThere are additional subsystems (supporting or optional compiler\nmodules) like v.comptime, v.generics, v.pref, v.reflection,\nv.callgraph, etc.\n\n### Key Directories\n* `vlib/`: Standard library (changes here can affect the compiler\n  itself).\n* `cmd/v/v.v`: Compiler entry.\n* `cmd/tools/`: vfmt, vdoc, vup, vquest, etc.\n* `examples/`: Example programs.\n* `thirdparty/`: Bundled C libraries (tcc, mbedtls, sokol, etc.).\n* `vlib/v/`: Compiler modules.\n  * ast/ - AST node definitions\n  * fmt/ - Code formatter\n  * scanner/ - Tokenizer\n  * token/ - Token definitions\n  * parser/ - Produces AST from tokens\n  * checker/ - Type checking and resolution\n  * comptime/ - Compile-time evaluation support\n  * transformer/ - Common optimisations and simplifications, makes the\n    backends simpler\n  * markused/ - Dead code eliminator\n  * gen/c/ - C code generation (primary backend, known as cgen)\n  * gen/js/ - JavaScript backend\n  * gen/native/ - Machine code generation (ELF, Mach-O)\n  * gen/wasm/ - WebAssembly backend\n\n### Test Locations\n* `vlib/v/tests/`: Compiler feature tests (including comptime).\n* `vlib/v/slow_tests/`: Output-matching and slow tests for the\n  compiler.\n* `vlib/v/slow_tests/inout/` - Output comparison tests\n  (.vv + .out pairs)\n* `vlib/v/parser/` - Parser error tests\n* `vlib/v/checker/` - Checker error tests\n* `vlib/v/gen/c/testdata/` - C codegen tests (.vv + .c.must_have)\n* `examples/compiletime/` - Comptime usage examples (including\n  `reflection.v`)\n\n## Error Reporting (checker/parser)\n* Error: `c.error('message', pos)` - hard error, stops compilation.\n* Warning: `c.warn('message', pos)` - warning, allows compilation.\n* Notice: `c.note('message', pos)` - informational only.\n* Pattern: Most checker methods use `fn (mut c Checker)` receiver.\n* Location: `vlib/v/checker/errors.v`.\n\n## Option/Result Types\n* Syntax: `?Type` (optional, can be none) vs `!Type` (result, can\n  error).\n* Common bugs: Unwrapping in if guards, struct init with option fields,\n  ternaries with options.\n* When changing option/result behavior, add a regression test in\n  `vlib/v/tests/`.\n* Tests: Search `vlib/v/tests/` for option/result test files.\n* Pitfall: Options in ternaries, SQL statements, and fixed arrays need\n  special handling in cgen.\n\n## Tools\n* Note: if a rule overlaps with Testing, follow Testing.\n* Format: `./vnew fmt -w <file>` for touched `.v` and `.vsh` files.\n  Format only touched files unless explicitly asked to reformat broader\n  scope.\n* Treat new files as touched for formatting and markdown checks.\n* Check *all* files are formatted: `./vnew -silent test-fmt`.\n  Run only when asked or when validating the full tree.\n* Check markdown: `./vnew check-md file.md` for touched `.md` files\n  (required before commits).\n* Code style checker: `./vnew vet vlib/v`\n  Run only when asked or when making broad checker changes (more than\n  3 files in `vlib/v/checker/`).\n* Module docs: `./vnew doc -readme -all -l module_name`.\n* Search: `rg pattern` (or `git grep`); list files: `rg --files`.\n* Auto-format hook: `./vnew git-fmt-hook install`.\n\n## Commits and PRs\n* See `CONTRIBUTING.md` for full commit message conventions and PR\n  workflow.\n* Keep commits focused: one logical change per commit.\n* If your branch has diverged and a rebase or merge is needed, do not\n  force-push or drop hunks without asking. State the conflict and let\n  the user decide the resolution strategy. When in doubt, prefer\n  `git rebase` over `git merge` for a linear history, but always ask\n  if the situation is ambiguous.\n\n## Environment Variables\n* VFLAGS: Pass flags to all V invocations\n  (e.g., `VFLAGS='-g' ./vnew test-all`).\n* VEXE: Path to V compiler executable (useful in CI/scripts).\n* TMPDIR: Controls where `.tmp.c` files are written (V uses\n  `TMPDIR/v/`).\n* SOURCE_DATE_EPOCH: Override build timestamp for reproducible builds\n  (affects `@BUILD_DATE`, `@BUILD_TIME`, `@BUILD_TIMESTAMP`).\n* V2-specific: `V2CC`, `V2CFLAGS`, `V2VERBOSE` (for v2 development).\n\n## Gotchas\n* Core modules (`builtin`, `strings`, `os`, `strconv`, `time`) can\n  affect the compiler because it is a V program. Rebuild `./vnew` when\n  they change.\n* Module names must match their directory name; mismatches cause silent\n  import failures. See Modules and Imports.\n* Some V programs and tools hardcode `os.execute('v ...')` in their\n  source. The `./vnew` workflow does not protect against these; if you\n  encounter unexpected behavior from such calls, check whether the\n  code is invoking the system `v` instead of `./vnew` and adjust\n  accordingly.\n* Stale `./vnew` can cause confusing failures; rebuild if behavior\n  seems off.\n* Output tests require exact matches; whitespace changes break tests.\n* Formatting reminders: follow Code Style for `fmt` and `check-md`.\n* C compilation errors? Check generated C with `-keepc`\n  (creates `/tmp/*.tmp.c`; see also TMPDIR in Environment Variables).\n* Compile-time code (`$if`, `$for`, `$embed_file`, etc.) is a common\n  source of AI mistakes. See Compile-Time Code and Reflection for\n  correct usage and pitfalls.\n* Broken compiler? See Safety for the recovery sequence.\n* Consult `CONTRIBUTING.md` and `TESTS.md` for:\n  * New tests or test infra changes.\n  * Output tests or `.out` updates.\n  * Broad refactors or compiler-wide changes.\n  * Unsure which slow test runner applies to your change.\n"}}