aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-14 03:40:20 +0000
committer_ov4 <ov4@ov4.org>2026-10-14 03:40:20 +0000
commit97a7614bf16c27ac0f7c22340f9a0ba0ba716ade (patch)
tree28c48f4aa6f43817f851741ea61fd395b76d63c5
parentfebb9e4ac239a15ad8c46575643b53ca66e3f4ac (diff)
docs(language): document native C types and explicit casts
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
-rw-r--r--AGENTS/ARCH.md15
-rw-r--r--AGENTS/CONVENTIONS.md12
-rw-r--r--AGENTS/EXTENDING.md8
-rw-r--r--AGENTS/PITFALLS.md9
-rw-r--r--AGENTS/SUBSYSTEMS.md2
-rw-r--r--doc/language/cpsc-language-overview.7.md3
-rw-r--r--doc/language/keyword/cpsc-keyword-c_type.7.md46
-rw-r--r--doc/language/keyword/cpsc-keyword-declare.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-div.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-input.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-mod.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-output.7.md2
-rw-r--r--doc/language/keyword/cpsc-keyword-type.7.md3
13 files changed, 105 insertions, 3 deletions
diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md
index 2551161..be98732 100644
--- a/AGENTS/ARCH.md
+++ b/AGENTS/ARCH.md
@@ -15,10 +15,20 @@ INTEGER = `i64`, REAL = `double`, BOOLEAN = `i1`, CHAR = `i8`, STRING = opaque `
to a NUL-terminated buffer. User-defined types (ยง4): enum = `i64` (0-based ordinal),
pointer = opaque `ptr`, record = named struct `%record.NAME`. Enum/pointer are
LLVM-identical to INTEGER/STRING **by design** โ€” their identity lives in the type
-*name*, enforced upstream (see CONVENTIONS.md). Byte sizes are never computed
-host-side: the module has no DataLayout string, so every size is a null-GEP
+*name*, enforced upstream (see CONVENTIONS.md). Allocation byte sizes are never computed
+host-side: the module has no DataLayout string, so every allocation size is a null-GEP
`sizeof` constant (`TypeSystem::getSizeOfConstant`) folded by the backend.
+C_INT/C_CHAR/C_STRING/C_DOUBLE alias native int/char/char*/double. C_TYPE string
+imports cover standard C integer/real types, _Bool, void and object pointers.
+CScalar/CPointer identities are canonical C types, not pseudocode alias names;
+native widths and signedness come from sizeof/type traits, while floating formats
+come from numeric_limits (long double size alone is insufficient). Programs use
+the compiler's build ABI; cross-target emission and EXTERN are not implemented.
+CTypeGen handles typed numeric conversions, casts, native arithmetic and I/O.
+Crossing C/pseudocode domains requires a cast, including literals. C arithmetic
+uses C++ promotions, except that / always returns pseudocode REAL.
+
## Build & run
The compiler emits textual IR. Initial configuration must explicitly select
@@ -167,6 +177,7 @@ untested.)
| `lib/Parser/ParserType.cc` | TYPE/ENDTYPE and CLASS/ENDCLASS declarations, shared field parsing, SET/DEFINE reserved stubs |
| `lib/CodeGen/CodeGen.cc` | Hub: dispatch, coercion, control flow, INPUT/OUTPUT, main() |
| `lib/CodeGen/Designator.cc` | CodeGen methods for the TYPE system: type pre-pass, `emitLValue`/`loadFromLValue`, `emitCoercedExpr` gate, user-kind binary-op interception |
+| `lib/CodeGen/CTypeGen.cc` | CodeGen methods for native C scalar conversions, casts, arithmetic and input/output |
| `lib/CodeGen/*Handler.cc`, `FunctionGen.cc`, `RuntimeCheck.cc`, `TypeSystem.cc` | Helpers owned by CodeGen (including exception emission) |
| `CMakeLists.txt` | 3 static libs (CPSLexer, CPSParser, CPSCodeGen) + `cpsc`. **New .cc files must be added to the source lists here** |
| `tools/driver/EmbeddedRunner.cc`, `cmake/EmbeddedLLVM.cmake` | EMBEDDED-only MCJIT runner and static support-library selection |
diff --git a/AGENTS/CONVENTIONS.md b/AGENTS/CONVENTIONS.md
index b38b73c..01d4ab2 100644
--- a/AGENTS/CONVENTIONS.md
+++ b/AGENTS/CONVENTIONS.md
@@ -30,6 +30,18 @@ user-defined names) โ€” never an enum. `TypeSystem` resolves the string to
identifier as a type name except `VOID` (rejected outside a RETURNS clause via its
`AllowVoid` flag); other unknown types only fail (softly) in CodeGen.
+**C aliases are structural within the C domain.** `CIdentity` retains the canonical
+C base type and pointer levels independently of the alias `Name`. Use `sameType`
+for storage compatibility (including BYREF and array arguments); never equate C
+types just because their LLVM types or widths match. CScalar/CPointer values are
+handled by CTypeGen, not the legacy representation coercions. Cross-domain
+assignments, arguments and operators require explicit casts, including literals.
+Plain C char uses native signedness; pseudocode CHAR stays unsigned. Numeric
+conversions use source signedness, and native floating formats use numeric_limits.
+Allocation sizes still use LLVM sizeof; native C type widths use build-compiler
+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;
same-layout records too). Their LLVM representations are indistinguishable from
diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md
index 43af5e0..ac9f50e 100644
--- a/AGENTS/EXTENDING.md
+++ b/AGENTS/EXTENDING.md
@@ -45,6 +45,14 @@ OUTPUT/INPUT/WRITEFILE/file-name operands, FOR variables, builtin args,
`getExprTypeInfo` classification. Everything not explicitly admitted must be a
compile error.
+**Native C types:** add representation/format metadata in TypeSystem's native
+registration, using compiler-derived facts rather than fixed widths. Preserve
+canonical CIdentity and alias compatibility. Update CTypeGen conversions,
+promotions and I/O together; never let native C operands fall through to the
+legacy ArithmeticHandler or representation-only coercions. C_TYPE parses a
+string import, not an ordinary function call. Casts are CastExprAST values;
+their type must be recognized by both emission and getExprTypeInfo.
+
**New designator access form:** `AccessKind` case in `TypeAST.h` +
`ParseDesignatorSuffix` + the walk in `CodeGen::emitLValue` **and** the static
walk in `getExprTypeInfo`'s designator branch (they must agree) โ€” plus the
diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md
index ce72de8..6e0202e 100644
--- a/AGENTS/PITFALLS.md
+++ b/AGENTS/PITFALLS.md
@@ -86,6 +86,15 @@ test programs.
Unwinding does not free heap strings/arrays or close files. Linux LLVM 18 is
verified; Windows and macOS exception execution is not.
+- **C type extensions.** C_STRING is a raw char pointer, not a STRING: explicitly
+ cast to STRING for printing or builtins. C aliases share canonical CIdentity;
+ do not use LLVM widths to recover signedness or nominal type identity. Plain
+ char's signedness is native, unlike pseudocode CHAR. C/pseudocode conversions
+ require casts even for literals. C scalar arithmetic uses native promotions,
+ but / always returns REAL. Cast aliases must precede their use. long double
+ may have padding; sizeof does not identify its floating-point format. Native
+ C support is verified on Linux LLVM 18; cross-target and EXTERN are unsupported.
+
## Not implemented (9618 features)
CASE OF, CONSTANT, SET types (`SET`/`DEFINE` are reserved with dedicated errors),
diff --git a/AGENTS/SUBSYSTEMS.md b/AGENTS/SUBSYSTEMS.md
index 95e1abb..7d1ea5c 100644
--- a/AGENTS/SUBSYSTEMS.md
+++ b/AGENTS/SUBSYSTEMS.md
@@ -64,7 +64,7 @@ context or language-level inheritance yet.
**Runtime checks** (`RuntimeCheck`): array bounds, file misuse, enum ranges, null
dereferences and array-parameter bounds contracts are checked at their emit sites.
`ArithmeticHandler` calls `emitDivZeroCheck` before `/`, DIV and MOD; the check accepts
-i64 and double divisors, including both floating-point signed zeros.
+integer and floating-point divisors, including both floating-point signed zeros.
`emitCheck(Cond)` splits the block and calls `ExceptionHandler::emitThrow` on failure.
No check prints an error; source-line parameters remain reserved for future diagnostics.
diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md
index 5c327b0..e729a6b 100644
--- a/doc/language/cpsc-language-overview.7.md
+++ b/doc/language/cpsc-language-overview.7.md
@@ -12,6 +12,8 @@ Assign with ASCII `<-`: `Count <- Count + 1`. Compare with `=`, `<>`, `<`, `>`,
Precedence, from highest to lowest: unary operators, `* / DIV MOD`, `+ - &`, comparisons, AND, OR. Parentheses override precedence.
+Parenthesized type casts, such as (C_INT)Number, have unary precedence. C_INT, C_CHAR, C_STRING and C_DOUBLE are native C aliases; TYPE name = C_TYPE("...") imports other supported C base types and pointers. Conversions between C and pseudocode types must be explicit. These are compiler extensions; see [cpsc-keyword-c_type(7)](keyword/cpsc-keyword-c_type.7.md).
+
Literals include integers, decimal real numbers, TRUE/FALSE, strings in double quotes, and single-byte characters in single quotes. Negative numbers use unary minus. There are no string or character escape sequences. Comments begin with `//` and continue to the end of the line.
Declare variables before use. See DECLARE for built-in types and arrays, TYPE for records/enumerations/pointers, and CLASS for public/private fields.
@@ -36,6 +38,7 @@ The compiler extensions TRY/CATCH/ENDTRY and THROW support anonymous exceptions
- [cpsc-keyword-writefile(7)](keyword/cpsc-keyword-writefile.7.md): write a line to a text file.
- [cpsc-keyword-closefile(7)](keyword/cpsc-keyword-closefile.7.md): close a text file.
- [cpsc-keyword-type(7)](keyword/cpsc-keyword-type.7.md): define enumerations, pointers, and records.
+- [cpsc-keyword-c_type(7)](keyword/cpsc-keyword-c_type.7.md): import native C types and explicitly cast values.
- [cpsc-keyword-class(7)](keyword/cpsc-keyword-class.7.md): define a class with public and private fields.
- [cpsc-keyword-and(7)](keyword/cpsc-keyword-and.7.md): combine conditions with logical AND.
- [cpsc-keyword-or(7)](keyword/cpsc-keyword-or.7.md): combine conditions with logical OR.
diff --git a/doc/language/keyword/cpsc-keyword-c_type.7.md b/doc/language/keyword/cpsc-keyword-c_type.7.md
new file mode 100644
index 0000000..5b8ebd3
--- /dev/null
+++ b/doc/language/keyword/cpsc-keyword-c_type.7.md
@@ -0,0 +1,46 @@
+% CPSC-KEYWORD-C_TYPE(7)
+
+# NAME
+
+cpsc-keyword-c_type - import a native C type as a pseudocode alias
+
+# SYNOPSIS
+
+```text
+TYPE name = C_TYPE("C type expression")
+(type) expression
+```
+
+# DESCRIPTION
+
+C_TYPE and parenthesized casts are compiler extensions. C_TYPE requires a string literal and appears only on the right side of a top-level TYPE declaration. C_INT, C_CHAR, C_STRING and C_DOUBLE are predefined aliases for int, char, char* and double. Imported aliases for the same C type are interchangeable, including BYREF arguments and array parameters; the original pseudocode TYPE rules remain nominal.
+
+Supported base types are _Bool; char, signed char and unsigned char; signed and unsigned short, int, long and long long; and float, double and long double. Legal C combinations such as unsigned, signed int and unsigned long int are accepted. Type spelling is case-sensitive. void is allowed for pointer pointees and function return types, but not variables, fields or parameters. Multiple pointer stars may precede or follow the base type: `"**char"` and `"char**"` are equivalent. Whitespace is allowed. Mixed star placement, const/volatile, structs, unions, C typedef names, array types, function pointers, complex types and compiler-specific types are unsupported.
+
+C widths, char signedness and floating-point formats come from the compiler's build platform. Generated programs must use the same platform ABI; cross-target compilation and EXTERN declarations are not implemented. INTEGER remains signed 64-bit, CHAR remains an unsigned byte, and REAL remains double precision. In particular, C_CHAR need not have CHAR's signedness.
+
+A cast has unary precedence and converts its following operand. Declare a type alias before using its name in a cast. Numeric, character and boolean values can be explicitly converted between pseudocode and C types. STRING can be cast to char* and back, and C pointer types can be cast to other C pointer types. Pointer/integer casts and casts involving the original pseudocode enums, records or pointer types are unsupported. Casts are values, not assignable locations.
+
+C/pseudocode assignment, argument passing and mixed arithmetic require an explicit cast, including ordinary literals: use n <- (C_INT)1 and n + (C_INT)1. Different C scalar types use C++ numeric conversions, integer promotions and usual arithmetic conversions. BYREF requires the same type and performs no conversion. Comparisons and logical operations return BOOLEAN. The / operator always performs real division and returns REAL, including with two C integer operands; DIV and MOD accept C integers after promotion. C values used directly as IF/WHILE conditions need a cast to BOOLEAN.
+
+C scalar values support INPUT and OUTPUT. Plain char prints and reads a character; signed char and unsigned char use numeric input/output. _Bool uses the existing TRUE/FALSE output and numeric input. C pointers start null and support prefix ^ for address-of, suffix ^ for dereference, and = or <> between the same C pointer type. Dereferencing null throws; void pointers cannot be dereferenced. Pointer arithmetic and direct pointer INPUT/OUTPUT are unsupported. To print a C string, cast it to STRING. STRING/char* casts share the original buffer without allocation; a null char* becomes an empty STRING. Pointer validity and writable storage remain the caller's responsibility.
+
+# EXAMPLE
+
+```text
+TYPE NativeInt = C_TYPE("int")
+TYPE NativeIntPtr = C_TYPE("*int")
+DECLARE Number : NativeInt
+DECLARE Pointer : NativeIntPtr
+DECLARE Text : C_STRING
+Number <- (C_INT)42
+Pointer <- ^Number
+Pointer^ <- Number + (C_INT)1
+Text <- (C_STRING)"Result"
+OUTPUT (STRING)Text, ": ", Number
+OUTPUT Number / (C_INT)2
+```
+
+# SEE ALSO
+
+[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-input(7)](cpsc-keyword-input.7.md), [cpsc-keyword-output(7)](cpsc-keyword-output.7.md).
diff --git a/doc/language/keyword/cpsc-keyword-declare.7.md b/doc/language/keyword/cpsc-keyword-declare.7.md
index dcaa8ce..f92471e 100644
--- a/doc/language/keyword/cpsc-keyword-declare.7.md
+++ b/doc/language/keyword/cpsc-keyword-declare.7.md
@@ -15,6 +15,8 @@ DECLARE name : ARRAY[lower:upper, ...] OF type
Declare one variable per statement. Built-in types are INTEGER (signed 64-bit), REAL, BOOLEAN, CHAR (one byte), and STRING. User-defined TYPE and CLASS names are also accepted. Variables start with zero, FALSE, an empty string, or a zero-initialized user-defined value.
+C_INT, C_CHAR, C_STRING and C_DOUBLE are native C aliases for int, char, char* and double. C_TYPE can introduce aliases for other supported C base types and pointers. C values start with zero or null; assignment from pseudocode types requires an explicit cast. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
+
ARRAY bounds are inclusive and may be expressions; multiple ranges create multiple dimensions. Access elements with `name[index, ...]`. Bounds are checked at run time; an invalid index throws an exception that TRY/CATCH can handle. Whole-array assignment is unsupported. Declare arrays before using them; arrays declared inside a control-flow block stay in that block.
# EXAMPLE
diff --git a/doc/language/keyword/cpsc-keyword-div.7.md b/doc/language/keyword/cpsc-keyword-div.7.md
index af2443d..4ff774e 100644
--- a/doc/language/keyword/cpsc-keyword-div.7.md
+++ b/doc/language/keyword/cpsc-keyword-div.7.md
@@ -14,6 +14,8 @@ left DIV right
Both operands must be INTEGER. Return the quotient truncated toward zero. A zero divisor throws an exception that TRY/CATCH can handle. DIV has the same precedence as multiplication. Use `/` for division returning REAL.
+Two C integer operands are also accepted, using C++ integer promotions and signed/unsigned conversion rules. Mixing C and pseudocode operands requires an explicit cast. The / operator still returns REAL for C operands. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
+
# EXAMPLE
```text
diff --git a/doc/language/keyword/cpsc-keyword-input.7.md b/doc/language/keyword/cpsc-keyword-input.7.md
index 7bc1c73..c1ec905 100644
--- a/doc/language/keyword/cpsc-keyword-input.7.md
+++ b/doc/language/keyword/cpsc-keyword-input.7.md
@@ -14,6 +14,8 @@ INPUT variable
Read into a previously declared INTEGER, REAL, BOOLEAN, CHAR, or STRING variable. STRING input reads one whitespace-delimited word. The target must be a plain variable; array elements and record/class fields are unsupported, unlike the wider INPUT syntax in guide section 5.1.
+Native C scalar variables are also supported, using their actual widths and signedness. Plain C char reads a character; signed/unsigned char read numbers. C _Bool reads a number and stores whether it is nonzero. C pointers, including C_STRING, cannot be INPUT targets. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
+
# EXAMPLE
```text
diff --git a/doc/language/keyword/cpsc-keyword-mod.7.md b/doc/language/keyword/cpsc-keyword-mod.7.md
index 45267e2..0fa3e04 100644
--- a/doc/language/keyword/cpsc-keyword-mod.7.md
+++ b/doc/language/keyword/cpsc-keyword-mod.7.md
@@ -14,6 +14,8 @@ left MOD right
Both operands must be INTEGER. Return the remainder after division truncated toward zero; a nonzero remainder has the dividend's sign. A zero divisor throws an exception that TRY/CATCH can handle. MOD has the same precedence as multiplication.
+Two C integer operands are also accepted, using C++ integer promotions and signed/unsigned conversion rules. A signed result follows truncation toward zero; an unsigned result uses unsigned division. Mixing C and pseudocode operands requires an explicit cast. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
+
# EXAMPLE
```text
diff --git a/doc/language/keyword/cpsc-keyword-output.7.md b/doc/language/keyword/cpsc-keyword-output.7.md
index 90d4e82..3f90959 100644
--- a/doc/language/keyword/cpsc-keyword-output.7.md
+++ b/doc/language/keyword/cpsc-keyword-output.7.md
@@ -14,6 +14,8 @@ OUTPUT expression, ...
Print expressions from left to right without automatic separators, then add a newline. Strings print their contents; BOOLEAN prints TRUE or FALSE. Whole arrays and partially indexed arrays print their elements one per line; a final array adds no extra newline. Records, classes, and pointers cannot be printed directly.
+C scalars print with their native type's format and C argument promotions. Plain char prints a character, other C integers print numbers, and _Bool prints TRUE or FALSE. C_STRING is a pointer: cast it to STRING to print its contents. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md).
+
# EXAMPLE
```text
diff --git a/doc/language/keyword/cpsc-keyword-type.7.md b/doc/language/keyword/cpsc-keyword-type.7.md
index cdc41ff..ea9e098 100644
--- a/doc/language/keyword/cpsc-keyword-type.7.md
+++ b/doc/language/keyword/cpsc-keyword-type.7.md
@@ -9,6 +9,7 @@ cpsc-keyword-type - define enumerations, pointers, and records
```text
TYPE name = (value, ...)
TYPE name = ^type
+TYPE name = C_TYPE("C type expression")
TYPE name
DECLARE field : type
ENDTYPE
@@ -22,6 +23,8 @@ A prefix caret takes an address (`^variable`); a suffix caret dereferences a poi
Records contain one or more DECLARE fields and end with ENDTYPE. Access fields with a dot. Whole records copy by value; array fields are unsupported. Distinct user-defined type names remain distinct types. SET/DEFINE are reserved but unsupported.
+C_TYPE imports a native C type as an alias. Unlike the original enumerations, records and pointer declarations, C aliases with the same underlying C type are interchangeable. See [cpsc-keyword-c_type(7)](cpsc-keyword-c_type.7.md) for supported types and explicit casts.
+
# EXAMPLE
```text