From f19f1c956780f41f1440b372187770ce0be8efed Mon Sep 17 00:00:00 2001 From: _ov4 Date: Sun, 26 Jul 2026 17:32:24 +0000 Subject: feat: user type registry and enumerated types (CIE 4.1/4.2) - TypeSystem: TypeKinds Enum/Record/Pointer with per-kind payloads and checked accessors; two-pass registration (names first, then definitions in source order) so pointer TYPEs may forward-reference; enum-constant table owned by TypeSystem so constants stay visible inside function bodies across the Symbols save/clear/restore. Dead surface removed (Custom kind, Printable/Builtin/ReferenceLike, ElementSize, hasType, CodeGen::getNamedValue/getLLVMType). - Enums are i64 with 0-based ordinals (constexpr kEnumOrdinalBase); all type identity is by NAME. New emitCoercedExpr is the single admission gate, replacing raw coercion at assignments, array stores, BYVAL args, RETURN, IF/WHILE/REPEAT/FOR operands, file operands and builtin args; coerceValueToType now hard-errors if a user-kind target reaches it. - Binary ops with user-kind operands are intercepted ahead of ArithmeticHandler ('&'-intercept precedent): same-enum comparisons, enum +/- INTEGER (with a runtime range check, [Fatal] on overflow, the only site that can manufacture an invalid ordinal), same-name pointer =/<>; everything else is a compile error naming the operator. - OUTPUT is an exhaustive switch over TypeKind (enum prints its ordinal; record/pointer are compile errors, also covering whole-array OUTPUT); INPUT's silent %lld fallback for unknown kinds is now an explicit error. - Enum value names are globally reserved: collisions with DECLARE, array names, parameters and function names are compile errors. - RuntimeCheck: emitEnumRangeCheck + emitNullDerefCheck (used by the pointer phase) following the emitIndexCheck recipe. Co-Authored-By: Claude Fable 5 --- include/cps/RuntimeCheck.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include/cps/RuntimeCheck.h') diff --git a/include/cps/RuntimeCheck.h b/include/cps/RuntimeCheck.h index 97f4765..5996409 100644 --- a/include/cps/RuntimeCheck.h +++ b/include/cps/RuntimeCheck.h @@ -2,6 +2,8 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include +#include namespace cps { @@ -14,6 +16,8 @@ class RuntimeCheck { llvm::FunctionCallee ExitFunc; llvm::Value *DivZeroMsg; llvm::Value *OutOfBoundsMsg; + llvm::Value *EnumRangeMsg; + llvm::Value *NullDerefMsg; void setupExternalFunctions(); void emitErrorAndExit(llvm::Value *Condition, llvm::Value *Msg, int Line); @@ -24,6 +28,13 @@ public: void emitDivZeroCheck(llvm::Value *Divisor, int Line); void emitIndexCheck(llvm::Value *Index, llvm::Value *Lower, llvm::Value *Upper, int Line); + // Enum +/- INTEGER results must stay inside the enum's value range. + void emitEnumRangeCheck(llvm::Value *Ordinal, uint64_t ValueCount, + const std::string &TypeName, int Line); + + // Dereferencing an unset (null) pointer dies instead of segfaulting. + void emitNullDerefCheck(llvm::Value *Ptr, int Line); + // Runtime-computed variant: FmtArgs are the printf varargs after Msg // (e.g. {i32 line, ptr filename}). Needed when the failure site is inside // a synthesized helper function, where the line number is an argument -- cgit v1.3.1-4-g156e