From b47c302bbffd668334f307d512b674f804f8f2fc Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sat, 17 Oct 2026 10:35:33 +0000 Subject: docs: document OVERLOAD Co-Authored-By: Claude Opus 5.5 --- AGENTS/ARCH.md | 2 +- AGENTS/CONVENTIONS.md | 5 ++++- AGENTS/PITFALLS.md | 16 +++++++++++++--- AGENTS/SUBSYSTEMS.md | 22 +++++++++++++++------- 4 files changed, 33 insertions(+), 12 deletions(-) (limited to 'AGENTS') diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md index f85364b..cb0bc20 100644 --- a/AGENTS/ARCH.md +++ b/AGENTS/ARCH.md @@ -88,7 +88,7 @@ Driver behavior (`tools/driver/main.cc`): matched against command-line inputs with fs::equivalent. The driver rejects repeated inputs and computes transitive symbol visibility; cycles do not copy statements. CodeGen records owners for signatures, types and exported constants/globals and filters - lookup by the current unit. Cross-file duplicate definitions are always errors. + lookup by the current unit. Cross-file duplicate definitions are errors; distinct explicit OVERLOAD signatures may share a name. The entry file contains the only top-level code, or parameterless FUNCTION MAIN returning INTEGER; MAIN plus top-level code and builds without either entry are errors. SourceUnit borrows parsed statements for compilation. Type names are reserved across diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md index f912e79..5ab7459 100644 --- a/AGENTS/CONVENTIONS.md +++ b/AGENTS/CONVENTIONS.md @@ -142,7 +142,10 @@ arguments through `emitCoercedExpr`, and dispatches whole-array arguments to `ArrayHandler::emitArrayArgument`. RETURN values go through `emitCoercedExpr` against the declared return type. Top-level prototypes are pre-registered (after the TYPE pre-pass) before statement emission, so call-before-definition is fine; a call with -no registered signature is a compile error. Global function names except MAIN get no mangling, so +no registered signature is a compile error. OVERLOAD signatures append canonical +parameter types to the link name; ordinary names except MAIN get no mangling. +`getOverloads` filters by visibility and `resolveCall` selects exact static types/ranks. +Return types, modes and bounds never distinguish overloads. In all cases, `emitPrototype` rejects names that collide with runtime/libc symbols (`isReservedRuntimeName`), builtins, or enum values. Signatures retain the first declaration spelling for LLVM lookup, independently of call-site casing. Methods use diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index 951a2f6..8f35c3d 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -6,7 +6,8 @@ Every bullet below was confirmed against the source, most also by compiling and test programs. - **Multi-file extensions.** INCLUDE imports symbols, never text; every included file - must also be an input. Duplicate exports across files fail even without visibility. + must also be an input. Duplicate exports across files fail even without visibility, except distinct + signatures whose definitions all specify OVERLOAD. Only one file may contain top-level code; top-level DECLARE is a main local, not an export. Definitions-only builds now fail without FUNCTION MAIN returning INTEGER. MAIN cannot coexist with top-level code. GLOBAL accepts only the five primitive @@ -42,8 +43,8 @@ test programs. returns REAL. NUM_TO_STR formats INTEGER with bounded snprintf `"%lld"` (the full signed i64 range) and REAL with `"%f"`. REAL buffers cover the full fixed-point double range. - **`getExprTypeInfo` returns nullptr** for expressions it can't classify (null-check it - at any new call site) and internally defaults to INTEGER for arithmetic binaries and - unknown-function calls; OUTPUT reports an error for a nullptr result. + at any new call site) and internally defaults to INTEGER for unclassified arithmetic expressions; unknown or unmatched calls now diagnose and return nullptr. + OUTPUT reports an error for a nullptr result. - **CONSTANT** accepts only literals (including negative numeric literals), never expressions or other names. Constants have lexical block scope and may shadow outer names; bindings hiding constants are restored on block exit too. Functions inherit previously declared constants from their own unit and all visible imported top-level constants. Constants have no writable storage: assignment, INPUT, READFILE targets, FOR variables, BYREF and address-of are rejected. - **CASE OF** reads its selector once and tests expression labels in source order, with inclusive TO ranges and an optional final OTHERWISE. Label headers occupy their own source line; bodies may begin after the colon or on subsequent lines. Comparisons reuse ordinary operator rules; records and whole arrays are unsupported. - The lexer emits no newline tokens; most grammar is keyword-delimited, while CASE @@ -83,6 +84,15 @@ test programs. followed by `.` is swallowed into a REAL literal, so `1.foo` mislexes (only already-invalid programs can hit it). +- **OVERLOAD extension.** OVERLOAD is reserved and prefixes FUNCTION/PROCEDURE + (after PUBLIC/PRIVATE for methods). Every same-name definition must opt in. + Only count, canonical parameter types and array rank distinguish signatures: + return type, BYREF/BYVAL and array bounds do not. Calls match exact static types, + even for a single OVERLOAD definition; ordinary functions still coerce arguments. + Call visibility filters the set, but duplicate signatures conflict across all + inputs. MAIN and builtins cannot be overloaded. NEW supports overloads; DECLARE, + fields and arrays needing default construction require a matching no-argument NEW. + Private access is checked after selection, never used to select a public fallback. - **CLASS subset (ยง10).** `CLASS`/`ENDCLASS`/`PUBLIC`/`PRIVATE` are reserved. CLASS is a top-level record-derived value type with optional per-member access keywords (no DECLARE). Omitting access defaults to public, per the guide. diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index bb59ebf..dab3146 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -24,15 +24,20 @@ are a compile error there). Arrays keep their per-element newlines and dispatch continues with the next expression; a final array requires no extra newline. **Functions** (`FunctionGen`): plain LLVM functions, external linkage, exact pseudocode -name (MAIN uses internal __cps_main). Params are `ParamDecl{name, typeString, mode, array rank/bounds}`. BYVAL args are +name unless OVERLOAD appends a canonical parameter list (MAIN uses internal __cps_main). Params are `ParamDecl{name, typeString, mode, array rank/bounds}`. BYVAL args are copied into entry-block allocas (whole structs for records); BYREF args bind the incoming pointer directly as the variable's storage; array params are handed to the binder callback CodeGen injects (`setArrayParamBinder`) so FunctionGen never sees ArrayHandler. Missing RETURNS defaults the return type to INTEGER; procedures use "VOID". `emitPrototype` records each function's pseudocode signature in a `FuncSig` -map (`FunctionGen::getSignature`); `CodeGen::marshalCallArgs` dispatches call arguments -on those *declared* `ParamSig`s, and `getExprTypeInfo` reads return types from the same -map. Top-level prototypes are pre-registered at the start of `compile()` (after the +overload-set map (`FunctionGen::getOverloads`, filtered by unit visibility). +`resolveCall` selects exact static parameter types/ranks for OVERLOAD, while a single +ordinary definition keeps implicit conversions. Parameter keys exclude return types, +modes and bounds; equivalent C aliases use CIdentity. Every same-name definition must +be OVERLOAD; duplicate keys fail even across invisible units. FunctionGen tracks +prototype registration separately from source names and indexes signatures by LLVM +link name for RETURN (`getSignatureByLink`). `CodeGen::marshalCallArgs` consumes the +selected FuncSig, and `getExprTypeInfo` resolves the same calls without emitting IR. Top-level prototypes are pre-registered at the start of `compile()` (after the TYPE pre-pass), so calls may precede definitions; calling a name with no signature is a compile error (no extern is fabricated). Functions inherit visible GLOBAL storage and previously declared own top-level CONSTANT values, plus imported constants from the start; local constants use the same Symbols table with lexical binding restoration. Body emission is inverted: CodeGen injects a `StmtEmitter` callback, and must restore its own insert point (and the exchanged @@ -67,9 +72,12 @@ current method's owning class, including address-of, array elements and pointer dereferences. Other instances of the same class are accessible from its methods. Class ASTs also own their `FunctionDefAST` methods. PrototypeAST retains the owner -and access level; `getLinkName()` qualifies method symbols as `Class.Method`, while -global function names remain unmangled. CodeGen registers methods separately in -`ClassMethods` and pre-registers their prototypes after the type pre-pass. +and access level; `getLinkName()` supplies the source key `Class.Method`. +FunctionGen appends `(canonical parameter types)` only for OVERLOAD, leaving ordinary +symbols unchanged. CodeGen registers methods separately in +`ClassMethods` overload vectors and pre-registers their prototypes after the type pre-pass. +`resolveMethod` uses `resolveCall`; access is checked on the selected overload. +Constructor/default-construction paths select NEW through this same resolver. `MemberCallExprAST` keeps an addressable receiver separate from explicit arguments; `MemberCallStmtAST` discards its result. `emitMemberCall` checks access and prepends the receiver address to arguments marshalled by the existing `marshalCallArgs`. -- cgit v1.3.1-4-g156e