aboutsummaryrefslogtreecommitdiff
path: root/AGENTS/CONVENTIONS/CALLS.md
blob: df3d61d4743248488fb871671f2df1f3d0e90cd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# Conventions: calls, parameters and builtins

Part of [Load-bearing conventions](../CONVENTIONS.md). Templates and operator
overloads, which build on call resolution, are in [TEMPLATES_AND_OPERATORS.md](TEMPLATES_AND_OPERATORS.md).

**Calls share argument marshalling.** `CodeGen::emitCall` handles global expression
calls, CALL statements and bare `name(args)` statements; `emitMemberCall` resolves
member access and adds a hidden receiver address. Both use `marshalCallArgs` and
FunctionGen for user calls; statement calls discard results. Explicit casts may
bridge C void* and nominal pseudocode pointer types.

**User calls dispatch on the declared signature.**

- `FunctionGen::emitPrototype` records every function's pseudocode signature
  (`FuncSig`: return type name + per-param `ParamSig` {type name, mode, array
  rank/bounds}).
- `CodeGen::marshalCallArgs` — the single call-marshalling path for both call-expr
  and call-stmt — requires BYREF arguments to be bare variables of *exactly* the
  declared type (their `symbolAddress` is passed), admits BYVAL arguments through
  `emitOwnedValue`, and dispatches whole-array arguments to
  `ArrayHandler::emitArrayArgument`.
- RETURN also uses `emitOwnedValue` against the declared return type. Class lvalues
  invoke a same-class BYREF OVERLOAD NEW when defined; STRING-bearing aggregates
  clone their owned fields. Other classes without a copy constructor copy bits; class
  rvalues transfer ownership. Other values use `emitCoercedExpr`.
- Top-level prototypes are pre-registered at the start of `compile()` (after the TYPE
  pre-pass) before statement emission, so call-before-definition is fine; a call with
  no registered signature is a compile error (no extern is fabricated). Method
  prototypes are pre-registered too.
- OVERLOAD link names append canonical parameter types, plus `:ReturnKey` for non-VOID
  results (NEW and OPERATOR<- excepted); ordinary names except MAIN get no mangling.
  An expression's expected result type filters overloads when present. Without a result context, a DEFAULT return resolves return-only ambiguity within one name and canonical parameter signature. Overload sets,
  visibility filtering and exact selection:
  [SUBSYSTEMS/FUNCTIONS.md](../SUBSYSTEMS/FUNCTIONS.md#signatures-and-call-resolution).
- `emitPrototype` rejects builtin and enum names. Ordinary non-EXTERN, non-OVERLOAD
  definitions also reject runtime/libc names (`isReservedRuntimeName`); OVERLOAD
  definitions have signature-mangled symbols and cannot replace libc symbols.
  Signatures retain the first declaration spelling for LLVM lookup, independently of call-site casing.
- Methods use `Class.Method` names and a hidden leading receiver address; their
  FuncSig parameters contain only explicit source parameters.

**Parameter modes are sticky and BYREF is procedure-only (guide §8.3).** In
`(BYREF a : T, b : T)` the `b` is BYREF too; unannotated parameters default to BYVAL
(§8.1). A BYREF parameter in a FUNCTION is a parse error.

**Array parameters**: `ARRAY OF T` (rank 1, bounds travel with the argument) or
`ARRAY[l:u,...] OF T` (literal bounds, any rank, a contract checked at compile time
when the caller's bounds are constants, else at run time by throwing an exception).
The LLVM ABI flattens each rank-R array parameter into a data `ptr` plus
`kBoundArgsPerDim` (=2) i64 bounds per dimension; the callee rebuilds its
`ArrayMetadata` from those (`ArrayHandler::bindArrayParameter` via the binder
callback CodeGen injects into FunctionGen). BYVAL arrays copy their buffer at callee
entry and clone STRING-bearing elements; BYREF binds the caller's buffer.

**Builtins are plain identifiers backed by one table.** Builtins
(EOF/INT) parse as ordinary calls — no lexer/parser support, and the
names are not reserved words. The inline constexpr `Builtins` table in the internal
`lib/CodeGen/Builtins.h` ({Name, Arity, ReturnTypeName}) is the single source of
truth: `emitCall` checks arity against it before dispatching to the per-builtin emit
branches (still an if-chain, ahead of the user-function fallback), and
`getExprTypeInfo` reads return types from it. EOF and INT consume the call source
line for runtime diagnostics and can throw.
MALLOC/REALLOC/FREE are ordinary OVERLOAD functions in memory.cps, with no builtin
dispatch or type rules in the compiler.