| Age | Commit message (Collapse) | Author |
|
Route keyword NEW and DELETE through the same library runtime and retain
allocation tracking, runtime diagnostics and exception behavior.
BREAKING CHANGE: -no-std programs using NEW or DELETE must explicitly import memory.cps.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Report the function and its header line, then throw, instead of silently
returning zero. FUNCTION MAIN keeps its implicit result.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
A pseudocode pointer type now counts as a C type, in EXTERN signatures
and as a C-struct field, when it finally points to a non-void C type or a
C struct, as in TYPE PInt = ^C_INT. A pointer cycle such as TYPE P = ^P
and a pointer to a pseudocode type stay rejected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A variadic EXTERN call is now arranged by clang per call, from the fixed
parameter count and the promoted argument types. C-struct records pass
unchanged in variadic positions, as C11 6.5.2.2p6-7 and 7.16.1.1p2
allow; a record that is not a C struct names the offending field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
EXTERN_FUNCTION may now return a C-struct record by value, either through
caller-supplied sret memory or as a coerced value stored back into the
record, as clang arranges it. This removes the last by-value rejection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
EXTERN parameters may now be C-struct records by value. clang's
arrangement decides the passing: coerced through memory, flattened
into elements, or indirect as byval or a pointer to a copy. Returning a
record by value stays rejected for now.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Every EXTERN "C" signature is now arranged by clang's CodeGen
(arrangeFreeFunctionCall) for the host triple and applied by one generic
lowering routine, replacing the hand-written signext/zeroext rule.
clangCodeGen is linked statically into CPSCodeGen. Records still cross
only through pointer types, so generated code is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
A TYPE record whose fields are all C types, C structs or pointer types to
C structs now crosses the EXTERN "C" boundary through a pointer type.
Records by value are rejected for now, and a pointer to a record with a
non-C field names that field.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Move the copy-constructor, operator, MAIN OVERLOAD and reserved, builtin,
enum and type name checks at the start of emitPrototype into a private
validatePrototype helper.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Make getLLVMType and the link-name emitCall overload private, inline the
single-use GenerateCall helper into that overload, and drop the argument
setName calls in createArgumentAllocas that repeat the names emitPrototype
already assigned. The undefined-function diagnostic stays: a link name can
be shadowed by another module global (e.g. FUNCTION stderr).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Drop the never-read StackObject::IsCopy flag and registerStackObject
parameter, the unused NewExprAST forward declaration, the unused Ret
parameter of FunctionGen::emitReturn and CG parameter of
ArrayHandler::loadElement, unused <cstdio> includes, and the
coerceValueToType early returns already covered by the exact LLVM type
check (builtin kinds always map to double/i64/i1/i8).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Lexer, parser, driver and codegen diagnostics now read
"<path>:<line>: error: <message>" instead of "error: <message> at line N
in <path>". The path is always printed as given on the command line.
Call sites pass the bare message to cps::sourceError/sourceWarning, which
carry printf format checking; reportError routes through the same helper.
The suite iii harness parses the new layout and matches the reason
against the message only. iii/template-class-pack-field passed only
because its reason regex matched the case path, so it is now
case-insensitive.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Construct literals as STRING values and route string operations through
ordinary library functions and operators. Preserve value ownership in
records, arrays, constants and file I/O.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Resolve exact operand types and preserve declared operator return types.
Reject implicit STRING to BOOLEAN conversion at typed expression boundaries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Repeated EXTERN declarations with the same signature share one C symbol,
as C declarations do; conflicting signatures are errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Variadic arguments must be C values and receive C default argument
promotions; narrow integer parameters carry sign/zero extension.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Replace snprintf+write(2) with a single fprintf call on the platform's
stderr: the C library's stderr / __stderrp, or __acrt_iob_func(2) on
Windows, which the embedded runner binds to the host shim.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Runtime check messages and the unhandled-exception message were printed
to stdout by the generated program, so `cpsc x.cps -r >out.txt` captured
them. They are now formatted with snprintf and written with write(2).
Test expectations and docs are updated accordingly.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
|
Invoke the internal entry function through the generated exception handler
and truncate its INTEGER result to the process exit status.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Reject builds without an entry program and duplicate cross-file definitions.
Preserve source order for each unit's own constants and import visible exports.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
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.
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Size REAL buffers for the full fixed-point double range and bound writes with snprintf. Register MinGW CRT aliases for embedded execution.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Reject other compiler and LLVM major versions and remove GCC compiler
fallbacks. Adapt string globals, block termination checks and the embedded
target triple to LLVM 23 without changing pseudocode behavior.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Add TRY/CATCH/ENDTRY and anonymous THROW statements. Use LLVM exception
handling and the C++ ABI to propagate exceptions across function calls,
clean up catch state, and handle uncaught exceptions at the program boundary.
Register exception runtime symbols for the statically linked embedded runner.
Verify runtime checks, nested catches, returns, loops, and invalid syntax
with smoke programs; exercise unwinding with MCJIT, lli, and native binaries.
BREAKING CHANGE: Runtime check failures now throw anonymous exceptions and
print only a generic message when uncaught. Native binaries require linking
the C++ runtime.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Review findings (all reproduced, then fixed and re-verified):
- '^x' leaked as a raw address into any builtin context (s <- ^x printed
the variable's bytes as a C string; NOT ^x, '&', and ^x = ^x compiled).
Address-of is now rejected everywhere except a pointer-typed target.
- A whole-array variable passed the nominal gate as a value of its
ELEMENT type (s <- arrayOfSeason stored the raw data pointer; = on it
emitted invalid IR). Whole arrays are now rejected as operands and as
coercion sources; array parameters are unaffected.
- Enum values smuggled into INTEGER through array subscripts and DECLARE
bounds (a[Autumn], ARRAY[Spring:Winter]); both now go through
emitCoercedExpr like every other INTEGER context.
- An array DECLAREd inside an IF/WHILE/REPEAT/FOR body and used after the
block was a wild-pointer write (constant bounds) or a verifier dump
(runtime bounds). Arrays are now block-scoped: control-flow bodies
snapshot and restore the ArrayTable, so escape is a clean compile error.
- Duplicate parameter names silently shadowed (BYREF write-back defeated);
now a parse error. Trailing comma in parameter lists accepted; now a
parse error consistent with every other list.
- A variable/array/parameter/function could reuse a TYPE name; reserved.
- RETURN with a value inside a PROCEDURE was silently discarded (control
did not return); now an error, as is a bare RETURN in a FUNCTION.
- INPUT r.f mis-parsed into a three-error cascade; now one clear error.
- Assigning to an enum constant now says so instead of 'Unknown variable'.
Docs: ARCH/CONVENTIONS/EXTENDING/SUBSYSTEMS/PITFALLS rewritten for the
TYPE system (ABI additions, nominal-typing invariants, admission-gate
doors, array-parameter ABI, new recipes, new sharp edges); README
features/TODO updated — random files are unblocked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
- Parameter syntax lands end-to-end: ARRAY OF T (rank 1, bounds travel
with the argument) and ARRAY[l:u,...] OF T (any rank, literal bounds as
a checked contract). Element type and rank must match exactly.
- Flattened ABI: each rank-R array parameter becomes a data pointer plus
kBoundArgsPerDim i64 bounds per dimension. The callee rebuilds
ArrayMetadata from those bounds (ArrayHandler::bindArrayParameter via a
binder callback injected by CodeGen, so FunctionGen stays ignorant of
the array subsystem); the checked-indexing pipeline is reused unchanged.
- BYVAL (the CIE default) copies the whole buffer at callee entry
(malloc+memcpy, never freed — consistent with the string policy) so
callee writes stay invisible; BYREF binds the caller's buffer.
- Bounded-parameter contract: compile-time comparison when the caller's
bounds are constants, else a runtime [Fatal] check
(RuntimeCheck::emitArrayArgBoundsCheck).
- marshalCallArgs gains the array branch and a call-site line number
(CallStmtAST now carries one); whole-array-to-scalar keeps a clear
error, FUNCTION RETURNS ARRAY is a dedicated parse error.
- Verified: BYREF fill/sort-style mutation, BYVAL copy invisibility,
2-D bounded params, ARRAY OF <record> with field writes through the
parameter, bounds-contract mismatches at compile time and run time.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
- 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 <noreply@anthropic.com>
|
|
- Reserve TYPE/ENDTYPE/SET/DEFINE (-600 token block); SET/DEFINE parse to
dedicated not-implemented errors (RANDOM precedent).
- New TypeAST.h: enum/pointer/record decl nodes, designator chain
(DesignatorExprAST + Index/Field/Deref accessors), AddrOfExprAST,
DesignatorAssignStmtAST. Bare-name and single-index shapes degrade to
their legacy nodes, so existing programs produce identical ASTs.
- ParserType.cc: TYPE declarations (top-level only, enforced via a
ParseBlock depth counter), DECLARE-only record bodies with local
field-level error recovery.
- Postfix [ ] . ^ chain in ParseIdentifierExpr; prefix ^ (address-of,
designator operand only) in ParseUnary; assignment targets rebuilt on
the same suffix parser.
- Parameters: ParamDecl{name, type, mode, array rank/bounds} replaces the
(name, type, byref) tuple. Pass mode is sticky across parameters and
BYREF is rejected in FUNCTIONs, both per guide §8.3 (the old per-param
reset made the guide's own SWAP example pass Y by value). ARRAY OF T /
ARRAY[l:u,...] OF T parameter syntax parses; codegen rejects it until
the parameter-passing phase lands.
- CodeGen stubs report clear not-implemented errors for the new nodes so
nothing is silently ignored.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
(OPENFILE/READFILE/WRITEFILE/CLOSEFILE/EOF)
Front end: OPENFILE/READFILE/WRITEFILE/CLOSEFILE plus reserved mode
keywords READ/WRITE/APPEND (RANDOM reserved with a dedicated
not-implemented error); statement nodes in new FileAST.h, parsing in new
ParserFile.cc; EOF joins the Builtins table as the 12th builtin and
CallExprAST now carries a line number for its runtime diagnostics.
Runtime: new FileHandler (StringHandler-shaped leaf) lazily synthesizes
internal __cps_file_* helper functions and a 16-slot open-file table
keyed by filename content (strcmp — STRING '=' is pointer identity).
EOF is an fgetc/ungetc peek; READFILE grows a malloc/realloc line buffer
and strips a trailing CR; fopen uses text modes so mingw-w64 line
translation works. File-free programs get byte-identical IR. All misuse
(not open, wrong mode, reopen, fopen failure, read past EOF, table full)
dies with the existing "[Fatal] line N:" pattern via a new
RuntimeCheck::emitErrorAndExit overload taking runtime printf args.
Also fixes a pre-existing ArithmeticHandler hole surfaced by adversarial
review: mixed-width integer operands (i1 BOOLEAN / i8 CHAR vs i64) now
widen via ZExt instead of emitting invalid IR, and remaining type
mismatches get a clean diagnostic; -EOF(f) and -IS_NUM(x) compile.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Confirmed by a 17-agent review pass over the refactor diff (12 findings
verified against the code and reproduced end-to-end):
- marshalCallArgs: BYREF arguments must match the declared parameter
type exactly (was: silent bit-reinterpretation, e.g. REAL passed to
BYREF INTEGER printed garbage with exit 0); whole-array arguments are
rejected (was: callee assignment smashed the array data pointer ->
runtime SIGSEGV)
- Null guards for CHR/LCASE/UCASE/IS_NUM/NUM_TO_STR/STR_TO_NUM/ASC
argument emission (was: compiler SIGSEGV on e.g. CHR(undeclared)),
matching the guards MID/RIGHT/LEFT already had
- ParseReturnStmt: propagate expression-parse failure (was: diagnostic
printed but exit 0) and recognize bare RETURN before
ENDWHILE/UNTIL/NEXT (was: bogus diagnostic on legal early return)
- emitPrototype rejects FUNCTION/PROCEDURE names that collide with
runtime/libc symbols (was: FUNCTION strlen silently hijacked the
string runtime; arity mismatch crashed createArgumentAllocas) or with
builtins (was: silently shadowed); conflicting redefinitions keep the
first signature
- FOR STEP is evaluated exactly once, before the loop (was: once per
iteration; the runtime-direction refactor had moved it to N+1)
- RETURN values are coerced to the declared return type via the
signature table (RETURN n in a RETURNS REAL function now compiles)
- '&' coerces its operands to STRING (CHAR/number operands work);
OUTPUT of a PROCEDURE call reports a clean error
AGENTS docs updated to match. All positive samples remain byte-identical
to the pre-refactor baseline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
Integer/Real/Boolean/CharHandler carried only five one-line LLVM API
wrappers (now inlined at their call sites in CodeGen.cc) plus dead
emitDeclare methods that violated the documented two-table lock-step
invariant. StringHandler::emitDeclare (also dead) and its NamedValues
reference go too.
With the dead writers gone, NamedValues held no information not already
in Symbols[].Storage, so the parallel map is removed: getNamedValue
reads Symbols, ArrayHandler/FunctionGen take one table, and function
bodies save/restore a single map. Behavior unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
emitPrototype now records each FUNCTION/PROCEDURE's pseudocode signature
(FuncSig: return type + per-param type/BYREF flag). CodeGen::
marshalCallArgs replaces the two verbatim-duplicated marshalling blocks
and dispatches on the declared signature instead of inferring BYREF from
pointer-typed LLVM params: BYVAL STRING params now receive the string
data pointer (no more runtime garbage), and BYVAL args are coerced to
the declared type (INTEGER->REAL args no longer emit invalid IR).
Top-level prototypes are pre-registered in compile(), so calls may
precede definitions; GenerateCall no longer fabricates i64 externs for
unknown names - an unregistered callee is a compile error. OUTPUT
reports an error when it cannot infer the expression type instead of
printing with the INTEGER format.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|