From e44bdc6a2a0cf624b08046ecc7e5c5d5d9d2d66c Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 16 Oct 2026 13:21:05 +0000 Subject: fix(compiler): correct CIE semantics and diagnostic locations Use standard WHILE headers and default-public class fields, resolve pseudocode identifiers without case sensitivity, and check signed i64 literal boundaries before conversion. Preserve source locations across recursive emission and function diagnostics. Add 22 regression cases and update compiler examples and documentation. Validated all 69 CTest entries with the original Linux Actions seed and verified the release package's embedded, native and IR output paths. --- AGENTS/CONVENTIONS.md | 17 +++++++++++++---- AGENTS/PITFALLS.md | 12 ++++++------ AGENTS/SUBSYSTEMS.md | 5 +++-- 3 files changed, 22 insertions(+), 12 deletions(-) (limited to 'AGENTS') diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md index 93c6f24..d1454e6 100644 --- a/AGENTS/CONVENTIONS.md +++ b/AGENTS/CONVENTIONS.md @@ -17,7 +17,12 @@ out-of-band via public `Lexer` fields (`IdentifierStr`, `StringVal`, `NumVal`, **Keywords are UPPERCASE and case-sensitive.** `declare` silently lexes as an identifier. Assignment is `<-` (ASCII only), equality is single `=`, inequality `<>`, -concatenation `&` (reaches the parser as raw ASCII 38 — no token). No escape sequences +concatenation `&` (reaches the parser as raw ASCII 38 — no token). Identifiers use +ASCII case-insensitive lookup/comparison through `IdentifierMap`, `IdentifierSet` +and `sameIdentifier`; retain source spelling in ASTs and diagnostics. This includes +functions, types, enum values, fields and builtins, but not C_TYPE import strings. +Integer tokens carry a checked unsigned magnitude through lookahead; the parser +applies the sign and i64 range check, including the minimum value. No escape sequences in string/char literals. Comments are `//` to end of line. **The lexer reads a caller-owned stream.** Construct it with `Lexer(std::istream &)`; @@ -43,7 +48,7 @@ sizeof. C alias declarations precede casts using their names; the parser tracks declared type names to distinguish `(Type)operand` from `(expression)`. **User-kind typing is nominal, and checked upstream only.** Enum/Record/Pointer -identity is name equality (`P1 = ^INTEGER` and `P2 = ^INTEGER` are incompatible; +identity is case-insensitive name equality (`P1 = ^INTEGER` and `P2 = ^INTEGER` are incompatible; same-layout records too). Their LLVM representations are indistinguishable from builtins, so values of these kinds must NEVER reach `ArithmeticHandler` or `coerceValueToType` without a prior name-level check — `CodeGen::emitCoercedExpr` @@ -113,7 +118,10 @@ silently ignored** — no error. Adding an AST node always means touching these **Compiler error style: print an `error:` line, set the component's error flag, and keep compiling.** No exceptions, no exit mid-compile. `Lexer`/`Parser`/`CodeGen` each -expose `hadError()`; `CodeGen::reportError(fmt, ...)` is the helper for codegen-side +expose `hadError()`; AST expressions/statements share source-line metadata. Parser +entry points record token locations. CodeGen saves/restores its diagnostic line +across recursive emission and coercion; `reportError` appends `at line N`. +`CodeGen::reportError(fmt, ...)` is the helper for codegen-side diagnostics (`ArrayHandler` reaches it through its `CodeGen &` parameter, `FunctionGen`/`ArithmeticHandler` hold a `bool &HadError` reference). The driver exits non-zero when any flag is set, printing `compilation terminated.` once. Errors that @@ -134,7 +142,8 @@ the declared return type. Top-level prototypes are pre-registered (after the TYP pre-pass) before statement emission, so call-before-definition is fine; a call with no registered signature is a compile error. Function names get no mangling, so `emitPrototype` rejects names that collide with runtime/libc symbols -(`isReservedRuntimeName`), builtins, or enum values. +(`isReservedRuntimeName`), builtins, or enum values. Signatures retain the first +declaration spelling for LLVM lookup, independently of call-site casing. **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 diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index 16fa16d..d2a24d4 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -75,9 +75,9 @@ test programs. already-invalid programs can hit it). - **CLASS subset (§10).** `CLASS`/`ENDCLASS`/`PUBLIC`/`PRIVATE` are reserved. - CLASS is a top-level record-derived value type with mandatory per-field access - keywords (no DECLARE). Unlike the guide's default-public rule, omitting access - is an error. TYPE fields cannot specify access and remain public. Private fields + CLASS is a top-level record-derived value type with optional per-field access + keywords (no DECLARE). Omitting access defaults to public, per the guide. + TYPE fields cannot specify access and remain public. Private fields cannot be accessed externally; whole-value initialization/copying is allowed. CLASS inherits record limitations, including no array fields or empty bodies. @@ -110,6 +110,6 @@ DATE, INPUT into array elements, string escape sequences, array-typed record fields, whole-array RETURN, class methods/constructors/destructors, NEW and class inheritance. Compiler fixtures now live in `tests/` (see TESTING.md). Nightly CI runs the compiler suites, packaged EMBEDDED smoke checks and existing -plugin tests. The initial compiler suite intentionally exposes existing standard -conflicts and missing diagnostic locations; see `tests/FAILURES.md` before interpreting -a failing baseline. Keep those failures visible until their implementations are fixed. +plugin tests. The initial standard conflicts and missing diagnostic locations are fixed on +Linux; see `tests/FAILURES.md` for the historical baseline and coverage gaps. +WHILE uses the standard header without DO; old WHILE DO programs must be migrated. diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md index c553f8e..c64e30c 100644 --- a/AGENTS/SUBSYSTEMS.md +++ b/AGENTS/SUBSYSTEMS.md @@ -59,8 +59,9 @@ construction, which is why 0-based ordinals are load-bearing. `ClassTypeDeclAST` inherits `RecordTypeDeclAST`: CLASS declarations use the same two-pass registration, `TypeKind::Record`, `%record.NAME` layout and value semantics. Shared body/field parsing lives in `ParserType.cc`. TYPE fields always have -`IsPublic = true`; CLASS fields require an explicit PUBLIC/PRIVATE keyword and -carry that flag through `defineRecord` into `RecordFieldInfo`. Both the static +`IsPublic = true`; CLASS fields default to public or accept an explicit +PUBLIC/PRIVATE keyword and carry that flag through `defineRecord` into +`RecordFieldInfo`. Both the static designator type walk and `emitLValue` reject private field access, including address-of, array elements and pointer dereferences. There is no class method context or language-level inheritance yet. -- cgit v1.3.1-4-g156e