pudu.md
Grammar — Pudu
type: grammar language: Pudu version: "0.1.3" tags: [grammar] aliases: [Grammar — Pudu, Pudu Grammar]
The Pudu surface this repository is written against, pinned to compiler 0.1.3 as published in its release archive. Where this page and the compiler disagree, the compiler wins and this page is corrected in the same change.
SDK Discovery Map
| Need | Module | Entry points |
|---|---|---|
| Process environment | Std.Env | variables (every name and value, read once per load) |
| Files | Std.Io | exists, readAllBytes |
| Real paths | Std.Fs | canonical |
| Path arithmetic | Std.Path | join, parentOf, directoryOf, isAbsolute |
| Bytes | Std.Bytes | toText, toArray, drop, startsWith, fromArray |
| Characters | Std.Char | isLetter, isDigit, isWhitespace, toLower |
| Text | Std.Text | wholeOf, trimStart, trimEnd, fromChars |
| Exact numbers | Std.Decimal | parse |
| Secrets | Std.App.Secret | secret, reveal, redact |
| Application configuration | Std.App.Config | Config, Setting, declaring, sourceOf, Layering |
| Reflection in derives | Std.Meta | build, collect, nameOf, Field.get, Field.has, Field.attributeOr |
| Child processes | Std.Process | Launch, Launching.withVariable |
| Collections | Std.List, Std.Map | List.sortBy, Map.fromPairs, Map.get, Map.insert, Map.keys |
| Temporary trees | Std.Fs | withTemporaryDirectory (examples and suites) |
| Tests | Std.Test | suite, equals, that, run, failuresOf, report |
Std.Env reads the process environment and offers no way to change it. Loading therefore answers a [[domain/Variables|Variables]] view instead of writing into the process; see [[decisions/ADR-0002-a-view-not-a-mutation]].
Imports / Namespaces
- One module per file; the module name is the path under its source root with
/as.:src/PuduLangEnvironment/Domain/Parser.puduismodule PuduLangEnvironment.Domain.Parser. - Every import is qualified and aliased:
import Std.Io as Io. Nothing is imported implicitly. - Suites under
test/and programs underexamples/import package modules through the manifest's source root. - A trait is implemented for a type another module declares by the module that declares the trait:
LoaderimplementsLoadingforOptions.Options, so the fluent chain ends in.load()withoutOptionsimportingLoader.
Core Primitives
- Records:
export type Point = { x: Int, y: Int }, built asPoint{x: 1, y: 2}, updated asPoint{..p, y: 5}. An imported record is updated with its qualified name:Options.Options{..Options.defaults(), strict: true}. - Sum types:
export type Source = File(Str) | Text(Str, Str), taken apart withmatch. - A trait method takes
self: &Selfand answersSelffor a fluent chain:Options.defaults().withExpansion().withoutOverwrite(). - A function stored in a record field is called as
(record.field)(argument);showrenders it as<fn>, which is why [[src/PuduLangEnvironment/Variables]] keeps its values behind one. Option[T]andResult[T, E]helpers are module functions (Option.unwrapOr(value, fallback)).?propagatesNoneorErrfrom a function whose return type is the same family.- Module scope holds only
const. Lookup tables areconsttables built withsetOf([...])ormapOf([...]). - A type opts into generated implementations with a trailing
derivesclause:type Server = { port: Int } derives Binding.Bind, Binding.Redacted. A strategy is writtenexport derive Trait for T: Record { ... }and reads fields throughStd.Meta:Meta.buildconstructs the record (a closure answeringResultstops at the firstErr),Meta.collectgathers one answer per field, andfield.has(name)/field.attributeOr(name, fallback)read attributes such as@env("PORT"),@default("info"), and@secret. - A static trait method is called on a type:
F.fromVariable(key, text),T.bind(variables). - Borrowing:
&Tparameters are read-only views;*viewcopies a borrowed value into an owned one.
Text
Stris UTF-8.text.chars()answers anArray[Char]indexed in constant time; scanners walk that array, nevercharAt, which counts from the start each call.text.lines()splits on\nonly and keeps a\rthat ends a CRLF line; [[src/PuduLangEnvironment/Domain/Parser]] splits lines itself.Map.entries()andMap.keys()answer in key order." 12 ".toInt()isNone:Str.toIntadmits no surrounding space.Text.wholeOftrims and admits a sign.charFromCode(n)answersOption[Char];convertInteger[Int](byte)answersOption[Int].Str.toFloatanswersOption[Float64]; a trait is implemented forFloat64, notFloat.
Architectural Laws
- Dependency direction is inward: the public modules at
PuduLangEnvironment.*usePuduLangEnvironment.Domain.*, which usesUtilsandConstants.Domainnever imports a public module and performs no effects. - Files, the working directory, and the process environment are touched only by [[src/PuduLangEnvironment/Source]], [[src/PuduLangEnvironment/Discovery]], [[src/PuduLangEnvironment/Loader]], and [[src/PuduLangEnvironment/Variables]] (see [[seams/World]]).
- Failures are values: every refusal is a
Problemvariant. Nothing is thrown, and noProblemcarries a value read from a file ([[decisions/ADR-0001-problems-never-carry-values]]). - Every module the package ships is
PuduLangEnvironmentor lives undersrc/PuduLangEnvironment/, so a program that installs the package keeps every other module name.
Syntax Rules / Naming
- Types, traits, modules, and variants are
PascalCase; valuescamelCase; constantsUPPER_SNAKE_CASE. - Every file header and exported type carries the FMCF anchor, one line:
/** @Namespace.Entity.Role — intent */, five to eight words of intent. - Every
fn,export fn, andconstcarries a///doc comment of one or two lines stating what it answers or holds, in the voice of the standard library's own documentation. It states the contract, not the steps. - Rationale belongs in the mirrored page's Grill Log. No narration, history, or explanation of the obvious in code.
Prohibited Patterns (verified against the 0.1.3 compiler)
- A brace inside a string literal is interpolation. A literal brace is
\{or\}. Array.get(i)anditems[i]stop the program wheniis out of range. Guard the index or useList.getfor anOption.scope,module,where, andtaskare keywords; none can name a binding or a field.- Matching a borrowed value binds its parts as owned values.
- A unit value is matched as
Ok(_), notOk(()). - A static call through a type parameter inside
Meta.collect(F.fromVariablewhoseOption[A]implementation callsA.fromVariable) fails at run time with E7001 on 0.1.3 (pudu-lang#457);Meta.buildis unaffected. Gather inMeta.collectwith a method that does not recurse. showoverStd.App.Secret.Secretprints its raw value; render secrets throughBinding.RedactedorSecret.redact.Env.variableinside a loop scans the whole environment each call; readEnv.variables()once into a map.- A
Problemor description built from a value discloses a secret; build it from keys, line numbers, and paths only. showover a record holding a value from a file prints it; such records keep values behind a function field.
Senior Definition Needed
(none open)
Referenced by
[[00-INDEX]] · [[CHANGELOG]] · [[architecture/_MOC]] · [[handoffs/2026-10-07-initial-package]] · [[src/PuduLangEnvironment]] · [[src/PuduLangEnvironment/Binding]] · [[src/PuduLangEnvironment/Configuration]] · [[src/PuduLangEnvironment/Constants/Messages]] · [[src/PuduLangEnvironment/Constants/Names]] · [[src/PuduLangEnvironment/Discovery]] · [[src/PuduLangEnvironment/Domain/Cascade]] · [[src/PuduLangEnvironment/Domain/Encoding]] · [[src/PuduLangEnvironment/Domain/Expander]] · [[src/PuduLangEnvironment/Domain/Keys]] · [[src/PuduLangEnvironment/Domain/Layers]] · [[src/PuduLangEnvironment/Domain/Parser]] · [[src/PuduLangEnvironment/Domain/Values]] · [[src/PuduLangEnvironment/Loader]] · [[src/PuduLangEnvironment/Options]] · [[src/PuduLangEnvironment/Settings]] · [[src/PuduLangEnvironment/Source]] · [[src/PuduLangEnvironment/Utils/Template]] · [[src/PuduLangEnvironment/Variables]] · [[tools/Mutate]]
