Nocter AI Guide
This file is a compact guide for AI tools that read, write, review, or repair Nocter code. The normative language specification starts at ../README.md. When this guide conflicts with the specification, the specification wins.
Goal
Nocter should be readable and writable by humans first, and predictable for AI tools second. The language should not add alternate syntax only to satisfy AI tools. Instead, AI support comes from one canonical style, clear examples, machine-readable diagnostics, source formatting, and compiler-owned structure dumps.
Canonical Style
Use the formatter's output as the only canonical source style.
Important spellings:
use std/io.print
func main(): i32! {
print("Hello")?
return 0
}
Rules for generated code:
- Use 4 spaces for indentation.
- Do not write semicolons.
- Prefer
func main(): i32!for executable roots. - Treat
mainas an ordinary function name that v0 fixes as the executable entry point, not as a keyword or built-in. - Write fallible types as
T!. - Write fallible optional success values as
T?!. - Use
letfor immutable bindings andvarfor mutable bindings. - Use
&Tfor readonly borrow and&+Tfor readwrite borrow. - Use postfix
expr?to propagate fallible failure or optional absence. - Use postfix
expr!only for unrecoverable assumptions, tests, and prototypes. - Use
expr catch error { ... }for local handling ofT!failure. - Use
expr otherwise { ... }for optional fallback values and optional-side early exits. - Use
matchfor enum pattern handling. - Do not use
matchto unwrapT!orT?.
Imports
Nocter does not use a module declaration. A file's module identity comes from its path.
use std/io.print
use ./config.Config
Rules:
- User project modules receive a compiler-managed synthetic standard prelude.
- Do not write
use std/preludein generated user code; source-level prelude imports are invalid in v0. - Files inside the active Nocter home
std/tree do not receive the synthetic prelude. use pathimports a module namespace using the path's default name.use path.Nameimports selected public names.use path as nameimports a namespace alias.- Paths starting with
./or../are resolved relative to the current file. - Non-relative paths such as
std/ioare resolved from the source root first and the active Nocter home second. - Do not invent wildcard imports, textual includes, explicit
.nctimport suffixes, ormoduledeclarations.
Errors And Optionals
Fallible values use T!. The failure payload is always the built-in error type.
use std/io.print
func announce(text: &str): void! {
print(text)?
return
}
Handle a failure locally with catch.
run() catch error {
return Error.new("app.run_failed", error.message)
}
Rules:
expr?onT!extractsTon success and propagates the sameerroron failure.expr catch error { ... }extractsTon success and runs thecatchblock on failure.- The
catchbinding name is ordinary.erroris conventional, buterris valid. - A
catchblock must not fall through in v0. - In a function returning
T!,return expris a failure return whenexprhas typeerror. try,throw,Result<T, E>,ok, and failure patterns are not part of fallible handling.
Optional values use T?.
func lookup(name: &str): &str? {
if missing {
return none
}
return value
}
Use optional values through explicit forms:
let home = lookup("HOME") otherwise { return none }
let user = lookup("USER") otherwise { "unknown" }
Fallible optional success values use T?!.
use std/process.env
func user_name(): &str! {
return env("USER")? otherwise { "unknown" }
}
env("USER")? unwraps the fallible layer and leaves &str?; otherwise chooses a fallback when the optional success is none.
Enums And Match
Use match and if expr is Pattern for enum values.
match error {
AppError.missing_path {
report_missing_path()
}
AppError.open_failed(path) {
report_open_failed(path)
}
_ {
report_unknown(error)
}
}
Use match expressions when enum pattern handling must produce a value.
return match error {
AppError.missing_path { missing_code() }
AppError.open_failed(path) { code_for(path) }
_ { unknown_code() }
}
Rules:
- Use qualified variants such as
AppError.open_failed(path). - Use
_as the fallback arm. - Use
return match ...or a body-resultmatchwhen the branches produce values. - Write
matchvalue arms asPattern { result }. - Do not write
switch; enum pattern handling usesmatchin current Nocter. - Do not use enum pattern syntax for
T!orT?.
Documentation Comments
Use doc comments when generated APIs should be useful in future hover, LSP, and generated documentation.
//! File-level documentation.
/// Opens a file.
func open(path: &str): File! {
...
}
Rules:
///and/** ... */document the next documentable declaration, member, field, variant, or local binding.//!and/*! ... */document the source file/module.- Empty lines break attachment between a doc comment and the following construct.
//and/* ... */are normal implementation comments and must not be treated as hover text.nocter ast app.nct --format jsonmay expose attached doc text through AST nodedocumentationfields.
Common Mistakes
Avoid these obsolete or invalid patterns:
// invalid: `try` is not Nocter fallible propagation
let file = try File.open(path)
// invalid: fallible types do not write a custom error type
func read(): String!IOError
// invalid: spaced fallible type syntax is obsolete
func read(): String ! IOError
// invalid: Nocter does not use a module declaration
module app/main
// invalid: enum pattern handling uses `match`, not `switch`
switch error {
AppError.missing_path {
return 1
}
}
// invalid: do not treat print as a compiler builtin
print("Hello")
Prefer:
use std/io.print
func main(): i32! {
print("Hello")?
return 0
}
Machine-Readable Tooling
AI tools should interact with the compiler instead of reimplementing Nocter semantics.
Reserved and planned commands:
nocter check app.nct --format json
nocter tokens app.nct --format json
nocter ast app.nct --format json
nocter fmt app.nct
Expected AI loop:
write Nocter code
run nocter fmt
run nocter check --format json
run nocter build or nocter run when runtime buildability matters
use diagnostics spans and fix hints
repeat
Rules:
fmtis the source of canonical formatting.check --format jsonis the source of semantic diagnostics.checkcan accept explicitly check-only surfaces; usebuildorrunwhen the generated program must be runtime-buildable today.tokens --format jsonis the source of lexer output.ast --format jsonis the source of parser structure and attached documentation text.- AI tools must not maintain a separate interpretation of import resolution, type checking, ownership, borrowing, optional handling, fallible handling, or the fixed root
mainentry rule.
Example Corpus
Use examples as training and repair references:
spec/examples/valid/
spec/examples/invalid/
Valid examples should be formatter-ready Nocter code. Invalid examples should contain one intended error pattern and a short comment explaining it.