aboutsummaryrefslogtreecommitdiff
path: root/AGENTS
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 10:35:33 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 10:35:33 +0000
commitb47c302bbffd668334f307d512b674f804f8f2fc (patch)
tree4dfdecb510789114618545b4d8d3a03a5b52e511 /AGENTS
parente572d278a44d286c8713d0ee4af9c72a3d1ca73c (diff)
docs: document OVERLOAD
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'AGENTS')
-rw-r--r--AGENTS/ARCH.md2
-rw-r--r--AGENTS/CONVENTIONS.md5
-rw-r--r--AGENTS/PITFALLS.md16
-rw-r--r--AGENTS/SUBSYSTEMS.md22
4 files changed, 33 insertions, 12 deletions
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`.