diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-13 14:57:17 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-13 14:57:17 +0000 |
| commit | 0e83581ed907aee1f6e59524c7d28b6f9c016f8e (patch) | |
| tree | e7d12834f24e2db53953eff552ff3a1e0e5c23c9 /doc | |
| parent | a484f314b719aec5ed7bdc6f08403342b2125561 (diff) | |
docs(language): document exception handling and runtime behavior
Add the TRY manual for CATCH, ENDTRY, and anonymous THROW. Update runtime
error descriptions, language links, and native linking examples; document
catch cleanup and embedded runtime integration in the architecture notes.
Verify manual generation, rendered output, relative links, and the TRY
example. Record Linux LLVM 18 validation and unverified Windows/macOS support.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/cpsc.1.md | 12 | ||||
| -rw-r--r-- | doc/language/cpsc-language-overview.7.md | 5 | ||||
| -rw-r--r-- | doc/language/function/cpsc-function-eof.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-closefile.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-declare.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-div.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-mod.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-openfile.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-readfile.7.md | 4 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-try.7.md | 48 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-type.7.md | 6 | ||||
| -rw-r--r-- | doc/language/keyword/cpsc-keyword-writefile.7.md | 4 |
12 files changed, 83 insertions, 20 deletions
diff --git a/doc/cpsc.1.md b/doc/cpsc.1.md index 228fd66..b6b7ad0 100644 --- a/doc/cpsc.1.md +++ b/doc/cpsc.1.md @@ -66,6 +66,14 @@ Save IR and run it: cpsc test.cps -r -o result.ir ``` +Build a native program with a C++ linker so the exception runtime is linked: + +```sh +cpsc test.cps -o test.ll +clang++-18 test.ll -o test +./test +``` + # EXIT STATUS **0** @@ -76,12 +84,16 @@ cpsc test.cps -r -o result.ir With **-r**, return the executed program's exit status. In PATH mode, failure to launch `lli` or a child-process crash returns 1. +An uncaught program exception returns 1 after printing `Unhandled exception. Program terminated.` to standard output. Runtime check failures are exceptions and can be handled with TRY/CATCH/ENDTRY. + # NOTES Compiler diagnostics go to stderr. Failed compilation does not write IR. Successful compilation overwrites an existing output file, but an output path that refers to the source file (including a symbolic or hard link) is rejected. Missing input, including invoking `cpsc` without arguments, reports `cpsc: fatal error: no input files`. Ordinary lexical, syntax and semantic errors use `error:`; failures that prevent compilation, such as file I/O errors, use `fatal error:`. Compilation and argument failures end with one `compilation terminated.` line. Execution-stage failures do not print that line. +Generated IR uses the C++ exception ABI. Native binaries need the C++ runtime; EMBEDDED includes it, while PATH uses the runtime available to `lli`. Exception execution is verified on Linux with LLVM 18; Windows and macOS remain unverified. + # SEE ALSO [cpsc-language-overview(7)](language/cpsc-language-overview.7.md) describes supported syntax and links to the keyword and built-in function manuals. diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md index a471854..5c327b0 100644 --- a/doc/language/cpsc-language-overview.7.md +++ b/doc/language/cpsc-language-overview.7.md @@ -16,12 +16,15 @@ Literals include integers, decimal real numbers, TRUE/FALSE, strings in double q Declare variables before use. See DECLARE for built-in types and arrays, TYPE for records/enumerations/pointers, and CLASS for public/private fields. +The compiler extensions TRY/CATCH/ENDTRY and THROW support anonymous exceptions with stack unwinding. Runtime check failures can be caught; an uncaught exception prints a generic message and returns status 1. There is no error object or what() support. + # KEYWORDS - [cpsc-keyword-declare(7)](keyword/cpsc-keyword-declare.7.md): declare variables and arrays. - [cpsc-keyword-input(7)](keyword/cpsc-keyword-input.7.md): read a value from standard input. - [cpsc-keyword-output(7)](keyword/cpsc-keyword-output.7.md): print values to standard output. - [cpsc-keyword-if(7)](keyword/cpsc-keyword-if.7.md): choose between branches. +- [cpsc-keyword-try(7)](keyword/cpsc-keyword-try.7.md): catch or throw exceptions. - [cpsc-keyword-while(7)](keyword/cpsc-keyword-while.7.md): repeat while a condition is true. - [cpsc-keyword-repeat(7)](keyword/cpsc-keyword-repeat.7.md): repeat until a condition is true. - [cpsc-keyword-for(7)](keyword/cpsc-keyword-for.7.md): iterate over an integer range. @@ -40,7 +43,7 @@ Declare variables before use. See DECLARE for built-in types and arrays, TYPE fo - [cpsc-keyword-div(7)](keyword/cpsc-keyword-div.7.md): perform integer division. - [cpsc-keyword-mod(7)](keyword/cpsc-keyword-mod.7.md): find the integer division remainder. -Closing and auxiliary keywords are documented with their main constructs: THEN/ELSE/ENDIF with IF; DO/ENDWHILE with WHILE; UNTIL with REPEAT; TO/STEP/NEXT with FOR; RETURN/RETURNS/BYVAL/BYREF and function/procedure closing keywords with FUNCTION/PROCEDURE; READ/WRITE/APPEND with OPENFILE; ARRAY/OF and INTEGER/REAL/BOOLEAN/CHAR/STRING with DECLARE; ENDTYPE with TYPE; PUBLIC/PRIVATE/ENDCLASS with CLASS. TRUE/FALSE are BOOLEAN literals. +Closing and auxiliary keywords are documented with their main constructs: THEN/ELSE/ENDIF with IF; CATCH/ENDTRY/THROW with TRY; DO/ENDWHILE with WHILE; UNTIL with REPEAT; TO/STEP/NEXT with FOR; RETURN/RETURNS/BYVAL/BYREF and function/procedure closing keywords with FUNCTION/PROCEDURE; READ/WRITE/APPEND with OPENFILE; ARRAY/OF and INTEGER/REAL/BOOLEAN/CHAR/STRING with DECLARE; ENDTYPE with TYPE; PUBLIC/PRIVATE/ENDCLASS with CLASS. TRUE/FALSE are BOOLEAN literals. # BUILT-IN FUNCTIONS diff --git a/doc/language/function/cpsc-function-eof.7.md b/doc/language/function/cpsc-function-eof.7.md index 397c713..2f7e271 100644 --- a/doc/language/function/cpsc-function-eof.7.md +++ b/doc/language/function/cpsc-function-eof.7.md @@ -12,7 +12,7 @@ EOF(filename : STRING) RETURNS BOOLEAN # DESCRIPTION -Return true when no further characters remain in a file opened FOR READ. The test does not consume the next character. Testing an unopened file or a file in the wrong mode terminates execution. +Return true when no further characters remain in a file opened FOR READ. The test does not consume the next character. Testing an unopened file or a file in the wrong mode throws an exception that TRY/CATCH can handle. # EXAMPLE @@ -28,4 +28,4 @@ CLOSEFILE "notes.txt" # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](../keyword/cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](../keyword/cpsc-keyword-readfile.7.md), [cpsc-keyword-closefile(7)](../keyword/cpsc-keyword-closefile.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](../keyword/cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](../keyword/cpsc-keyword-readfile.7.md), [cpsc-keyword-closefile(7)](../keyword/cpsc-keyword-closefile.7.md), [cpsc-keyword-try(7)](../keyword/cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-closefile.7.md b/doc/language/keyword/cpsc-keyword-closefile.7.md index 2359b82..45d321e 100644 --- a/doc/language/keyword/cpsc-keyword-closefile.7.md +++ b/doc/language/keyword/cpsc-keyword-closefile.7.md @@ -12,7 +12,7 @@ CLOSEFILE filename # DESCRIPTION -Close the file associated with this filename string and release its open-file slot. Closing a filename that is not open terminates execution. +Close the file associated with this filename string and release its open-file slot. Closing a filename that is not open throws an exception that TRY/CATCH can handle. # EXAMPLE @@ -24,4 +24,4 @@ CLOSEFILE "notes.txt" # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-declare.7.md b/doc/language/keyword/cpsc-keyword-declare.7.md index 0c4ea28..dcaa8ce 100644 --- a/doc/language/keyword/cpsc-keyword-declare.7.md +++ b/doc/language/keyword/cpsc-keyword-declare.7.md @@ -15,7 +15,7 @@ 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. -ARRAY bounds are inclusive and may be expressions; multiple ranges create multiple dimensions. Access elements with `name[index, ...]`. Bounds are checked at run time. Whole-array assignment is unsupported. Declare arrays before using them; arrays declared inside a control-flow block stay in that block. +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 @@ -29,4 +29,4 @@ OUTPUT Names[Count] # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-output(7)](cpsc-keyword-output.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-type(7)](cpsc-keyword-type.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-output(7)](cpsc-keyword-output.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-div.7.md b/doc/language/keyword/cpsc-keyword-div.7.md index f033633..af2443d 100644 --- a/doc/language/keyword/cpsc-keyword-div.7.md +++ b/doc/language/keyword/cpsc-keyword-div.7.md @@ -12,7 +12,7 @@ left DIV right # DESCRIPTION -Both operands must be INTEGER. Return the quotient truncated toward zero. A zero divisor terminates execution. DIV has the same precedence as multiplication. Use `/` for division returning REAL. +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. # EXAMPLE @@ -22,4 +22,4 @@ OUTPUT 7 DIV 2 # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-mod(7)](cpsc-keyword-mod.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-mod(7)](cpsc-keyword-mod.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-mod.7.md b/doc/language/keyword/cpsc-keyword-mod.7.md index ea1b431..45267e2 100644 --- a/doc/language/keyword/cpsc-keyword-mod.7.md +++ b/doc/language/keyword/cpsc-keyword-mod.7.md @@ -12,7 +12,7 @@ left MOD right # DESCRIPTION -Both operands must be INTEGER. Return the remainder after division truncated toward zero; a nonzero remainder has the dividend's sign. A zero divisor terminates execution. MOD has the same precedence as multiplication. +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. # EXAMPLE @@ -22,4 +22,4 @@ OUTPUT 7 MOD 2 # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-div(7)](cpsc-keyword-div.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-div(7)](cpsc-keyword-div.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-openfile.7.md b/doc/language/keyword/cpsc-keyword-openfile.7.md index c2c3743..6df521f 100644 --- a/doc/language/keyword/cpsc-keyword-openfile.7.md +++ b/doc/language/keyword/cpsc-keyword-openfile.7.md @@ -16,7 +16,7 @@ OPENFILE filename FOR APPEND The filename is a STRING expression. READ opens an existing file for reading; WRITE creates or truncates a file; APPEND writes at the end, creating the file if needed. READ, WRITE, APPEND, and this use of FOR belong here. -At most 16 files may be open at once. Use the same filename string for subsequent operations. Reopening an open filename, failed opens, and wrong-mode operations terminate execution with a fatal diagnostic. RANDOM is reserved but unsupported. +At most 16 files may be open at once. Use the same filename string for subsequent operations. Reopening an open filename, failed opens, exceeding the open-file limit, and wrong-mode operations throw exceptions that TRY/CATCH can handle. RANDOM is reserved but unsupported. # EXAMPLE @@ -28,4 +28,4 @@ CLOSEFILE "notes.txt" # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-readfile(7)](cpsc-keyword-readfile.7.md), [cpsc-keyword-writefile(7)](cpsc-keyword-writefile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-readfile.7.md b/doc/language/keyword/cpsc-keyword-readfile.7.md index de0e849..200fc68 100644 --- a/doc/language/keyword/cpsc-keyword-readfile.7.md +++ b/doc/language/keyword/cpsc-keyword-readfile.7.md @@ -12,7 +12,7 @@ READFILE filename, variable # DESCRIPTION -Read one line from a file opened FOR READ, removing the line ending. The target must be a plain, previously declared STRING variable. Guard reads with EOF; reading past the end terminates execution. +Read one line from a file opened FOR READ, removing the line ending. The target must be a plain, previously declared STRING variable. Guard reads with EOF; reading past the end, using an unopened file, or using the wrong mode throws an exception that TRY/CATCH can handle. # EXAMPLE @@ -28,4 +28,4 @@ CLOSEFILE "notes.txt" # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-eof(7)](../function/cpsc-function-eof.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-eof(7)](../function/cpsc-function-eof.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-try.7.md b/doc/language/keyword/cpsc-keyword-try.7.md new file mode 100644 index 0000000..3b48dc4 --- /dev/null +++ b/doc/language/keyword/cpsc-keyword-try.7.md @@ -0,0 +1,48 @@ +% CPSC-KEYWORD-TRY(7) + +# NAME + +cpsc-keyword-try - catch exceptions with stack unwinding + +# SYNOPSIS + +```text +TRY + statements +CATCH + handler statements +ENDTRY + +THROW +``` + +# DESCRIPTION + +TRY, CATCH, ENDTRY, and THROW are compiler extensions to Cambridge pseudocode. Each TRY requires exactly one CATCH and an ENDTRY. CATCH takes no type or error variable; there is no error object or what() support. + +Normal execution skips CATCH. An exception stops the current operation, unwinds function and procedure calls, and enters the nearest active CATCH. After the handler completes, execution continues after ENDTRY. Blocks may nest and may appear inside functions, procedures, and loops. + +THROW takes no argument and always raises a new anonymous exception. An exception raised inside CATCH propagates to an enclosing TRY or a caller's handler; the same CATCH cannot catch it again. RETURN may leave either body, and leaving a handler finishes its catch state. + +Runtime checks throw the same anonymous exceptions for division by zero, array index errors, null pointer dereferences, invalid enumeration values, array-parameter bounds mismatches, and file misuse. Compiler errors cannot be caught. A caught exception prints nothing automatically. If no handler catches an exception, the program prints `Unhandled exception. Program terminated.` to standard output and returns status 1. + +Arrays declared inside either body remain local to that block. Stack unwinding does not automatically free heap strings or arrays, close files, or run user-defined destructors. Exception execution is verified on Linux with LLVM 18; Windows and macOS remain unverified. + +# EXAMPLE + +```text +PROCEDURE Fail() + THROW +ENDPROCEDURE + +TRY + CALL Fail() +CATCH + OUTPUT "Caught an exception" +ENDTRY +OUTPUT "Continuing" +``` + +# SEE ALSO + +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-function(7)](cpsc-keyword-function.7.md), [cpsc-keyword-procedure(7)](cpsc-keyword-procedure.7.md), [cpsc(1)](../../cpsc.1.md). diff --git a/doc/language/keyword/cpsc-keyword-type.7.md b/doc/language/keyword/cpsc-keyword-type.7.md index 5159dd5..cdc41ff 100644 --- a/doc/language/keyword/cpsc-keyword-type.7.md +++ b/doc/language/keyword/cpsc-keyword-type.7.md @@ -16,9 +16,9 @@ ENDTYPE # DESCRIPTION -Define types at top level. Enumeration values have globally reserved names; OUTPUT prints their zero-based ordinals. Enumerations support comparisons with the same type and addition/subtraction of INTEGER offsets; invalid ordinals terminate execution. +Define types at top level. Enumeration values have globally reserved names; OUTPUT prints their zero-based ordinals. Enumerations support comparisons with the same type and addition/subtraction of INTEGER offsets; invalid ordinals throw exceptions that TRY/CATCH can handle. -A prefix caret takes an address (`^variable`); a suffix caret dereferences a pointer (`pointer^`). Pointee types must match exactly, even where guide section 4.2's example mixes types. Pointers start null; dereferencing null terminates execution. There is no NULL literal. Avoid pointers to local variables after the function returns. +A prefix caret takes an address (`^variable`); a suffix caret dereferences a pointer (`pointer^`). Pointee types must match exactly, even where guide section 4.2's example mixes types. Pointers start null; dereferencing null throws an exception. There is no NULL literal. Avoid pointers to local variables after the function returns. 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. @@ -39,4 +39,4 @@ OUTPUT Position.X # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-declare(7)](cpsc-keyword-declare.7.md), [cpsc-keyword-class(7)](cpsc-keyword-class.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). diff --git a/doc/language/keyword/cpsc-keyword-writefile.7.md b/doc/language/keyword/cpsc-keyword-writefile.7.md index d3ce2c4..ae0f7e6 100644 --- a/doc/language/keyword/cpsc-keyword-writefile.7.md +++ b/doc/language/keyword/cpsc-keyword-writefile.7.md @@ -12,7 +12,7 @@ WRITEFILE filename, expression # DESCRIPTION -Write one value as text followed by a newline. Open the file FOR WRITE or APPEND first. Exactly one data expression is accepted; join strings with `&` when needed. Records, classes, and pointers are unsupported as data. +Write one value as text followed by a newline. Open the file FOR WRITE or APPEND first. Exactly one data expression is accepted; join strings with `&` when needed. Records, classes, and pointers are unsupported as data. An unopened file or a file opened FOR READ throws an exception that TRY/CATCH can handle. # EXAMPLE @@ -24,4 +24,4 @@ CLOSEFILE "notes.txt" # SEE ALSO -[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-num_to_str(7)](../function/cpsc-function-num_to_str.7.md). +[cpsc-language-overview(7)](../cpsc-language-overview.7.md), [cpsc-keyword-openfile(7)](cpsc-keyword-openfile.7.md), [cpsc-keyword-closefile(7)](cpsc-keyword-closefile.7.md), [cpsc-function-num_to_str(7)](../function/cpsc-function-num_to_str.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md). |
