aboutsummaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-27 14:07:24 +0000
committer_ov4 <ov4@ov4.org>2026-10-27 14:07:24 +0000
commitcaa88a9b36d9e1dfae40ecb31aee05bc2891fa17 (patch)
treed41168dc0799c6f8b033a3d6fdb2c2c72aac2b42 /doc
parent5d37ebcc02f6ca2ce1ced93f803dd1daf634d866 (diff)
docs(preprocessor): document switches and library regions
Add manuals and aliases for all five PP directives, replace the retired #LIB page, and update compiler and shared-editor architecture notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'doc')
-rw-r--r--doc/cpsc.1.md2
-rw-r--r--doc/language/cpsc-language-overview.7.md9
-rw-r--r--doc/language/keyword/cpsc-keyword-lib.7.md31
-rw-r--r--doc/language/keyword/cpsc-keyword-pp_define.7.md45
-rw-r--r--doc/language/keyword/cpsc-keyword-pp_ifdef.7.md45
5 files changed, 98 insertions, 34 deletions
diff --git a/doc/cpsc.1.md b/doc/cpsc.1.md
index e0e92e0..d5a8d72 100644
--- a/doc/cpsc.1.md
+++ b/doc/cpsc.1.md
@@ -16,6 +16,8 @@ Compile one or more pseudocode source files to a native executable, or to textua
Without **-o**, save beside the entry source file, replacing its extension with `.exe` on Windows or `.out` elsewhere for an executable, or `.ll` for IR. With **-r** alone, run without saving a file.
+Each input is independently preprocessed using file-local PP_DEFINE/PP_UNDEF switches and PP_IFDEF/PP_IFNDEF/PP_ENDIF conditions. PP_DEFINE __LIB enables library runtime line reporting for subsequent source positions; PP_UNDEF __LIB restores ordinary behavior. See [cpsc-keyword-pp_define(7)](language/keyword/cpsc-keyword-pp_define.7.md).
+
Each input is a compilation unit. Use top-level `INCLUDE "lib.cps"` to import another input's exported definitions, including its transitive imports. Paths are relative to the including source; every included file must also appear on the command line. Repeated includes and include cycles are harmless. Giving the same input twice, including symbolic or hard links, is an error. Duplicate definitions across files are errors even if the files do not include each other; distinct signatures, differing in parameters or return type, may share a name when every definition specifies OVERLOAD.
Exactly one file may contain top-level executable statements (including top-level DECLARE). Alternatively, define a parameterless `FUNCTION MAIN RETURNS INTEGER` in one file and have no top-level executable statements anywhere. Builds containing only definitions and no MAIN fail with `error: no main program`. GLOBAL blocks declare shared primitive variables. INCLUDE, GLOBAL and MAIN entry points are compiler extensions beyond the Cambridge guide.
diff --git a/doc/language/cpsc-language-overview.7.md b/doc/language/cpsc-language-overview.7.md
index 2c2019c..559a58d 100644
--- a/doc/language/cpsc-language-overview.7.md
+++ b/doc/language/cpsc-language-overview.7.md
@@ -6,7 +6,7 @@ cpsc-language-overview - supported cpsc pseudocode syntax
# DESCRIPTION
-Keywords are uppercase and case-sensitive. Identifiers, including built-in function names, are case insensitive. Indentation is for readability; blocks use explicit closing keywords. Identifiers begin with a letter or underscore and continue with letters, digits, or underscores.
+Keywords are uppercase and case-sensitive. Ordinary identifiers, including built-in function names, are case insensitive. Indentation is for readability; blocks use explicit closing keywords. Identifiers begin with a letter or underscore and continue with letters, digits, or underscores.
Assign with ASCII `<-`: `Count <- Count + 1`. Compare with `=`, `<>`, `<`, `>`, `<=`, and `>=`. Standard-library STRING comparisons compare contents, case-sensitively. Use `+`, `-`, `*`, and `/` for arithmetic; built-in `/` always returns REAL. Use `&` to join strings.
@@ -24,10 +24,13 @@ The compiler extensions TRY/CATCH/ENDTRY and THROW support anonymous exceptions
Multi-file builds use the compiler extensions INCLUDE and GLOBAL. Pass every source file on the command line and include the files whose definitions are needed. The entry file contains the sole top-level executable code, or a parameterless FUNCTION MAIN returning INTEGER; definitions alone do not form a runnable program.
-#LIB marks a library source unit. A line-leading `#` starts a compiler directive, not a comment; unknown directives are errors. Library runtime diagnostics report the first user call site. See [cpsc-keyword-lib(7)](keyword/cpsc-keyword-lib.7.md).
+PP_DEFINE and PP_UNDEF control file-local, case-sensitive preprocessor switches. PP_IFDEF and PP_IFNDEF conditionally include source up to PP_ENDIF; conditions may nest. Directives occupy their own lines, allowing leading whitespace and trailing // comments. Switches have no values and do not replace text. PP_DEFINE __LIB enables library runtime line reporting for subsequent source positions; PP_UNDEF __LIB restores ordinary behavior, including inside functions. See [cpsc-keyword-pp_define(7)](keyword/cpsc-keyword-pp_define.7.md) and [cpsc-keyword-pp_ifdef(7)](keyword/cpsc-keyword-pp_ifdef.7.md).
# KEYWORDS
+- [cpsc-keyword-pp_define(7)](keyword/cpsc-keyword-pp_define.7.md): define or remove preprocessor switches and select library code regions.
+- [cpsc-keyword-pp_ifdef(7)](keyword/cpsc-keyword-pp_ifdef.7.md): conditionally compile source according to switch definitions.
+
- [cpsc-keyword-include(7)](keyword/cpsc-keyword-include.7.md): import definitions from another compilation unit.
- [cpsc-keyword-global(7)](keyword/cpsc-keyword-global.7.md): declare shared primitive variables.
- [cpsc-keyword-constant(7)](keyword/cpsc-keyword-constant.7.md): declare a named literal with block scope.
@@ -62,7 +65,7 @@ Multi-file builds use the compiler extensions INCLUDE and GLOBAL. Pass every sou
- [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; OF/OTHERWISE/ENDCASE with CASE; CATCH/ENDTRY/THROW with TRY; 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; ENDGLOBAL with GLOBAL; ENDTYPE with TYPE; EXTERN_FUNCTION/EXTERN_PROCEDURE with EXTERN; PUBLIC/PRIVATE/ENDCLASS with CLASS. TRUE/FALSE are BOOLEAN literals.
+Closing and auxiliary keywords are documented with their main constructs: PP_UNDEF with PP_DEFINE; PP_IFNDEF/PP_ENDIF with PP_IFDEF; THEN/ELSE/ENDIF with IF; OF/OTHERWISE/ENDCASE with CASE; CATCH/ENDTRY/THROW with TRY; 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; ENDGLOBAL with GLOBAL; ENDTYPE with TYPE; EXTERN_FUNCTION/EXTERN_PROCEDURE with EXTERN; PUBLIC/PRIVATE/ENDCLASS with CLASS. TRUE/FALSE are BOOLEAN literals.
# STRING LIBRARY FUNCTIONS
diff --git a/doc/language/keyword/cpsc-keyword-lib.7.md b/doc/language/keyword/cpsc-keyword-lib.7.md
deleted file mode 100644
index 46af0a4..0000000
--- a/doc/language/keyword/cpsc-keyword-lib.7.md
+++ /dev/null
@@ -1,31 +0,0 @@
-% CPSC-KEYWORD-LIB(7)
-
-# NAME
-
-cpsc-keyword-lib - mark a library compilation unit
-
-# SYNOPSIS
-
-```text
-#LIB
-```
-
-# DESCRIPTION
-
-A line-leading `#` (optionally preceded by whitespace) begins a compiler directive. Only `#LIB` is supported. It marks the entire source file as library code. Compile-time diagnostics retain library locations; runtime checks use the line of the first call from user code into library code, including methods, operators, automatic constructors/destructors and EXTERN calls. Library-to-library calls preserve that line. Directives are not comments.
-
-C++ library objects may read `extern "C" int __cps_user_line`, print `[Fatal] line N: reason` to stderr and throw an anonymous integer exception for pseudocode TRY/CATCH. The global is shared by the program and is not thread-local.
-
-# EXAMPLE
-
-```text
-#LIB
-PROCEDURE Check()
- DECLARE A : ARRAY[1:1] OF INTEGER
- OUTPUT A[2]
-ENDPROCEDURE
-```
-
-# SEE ALSO
-
-[cpsc-keyword-include(7)](cpsc-keyword-include.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md).
diff --git a/doc/language/keyword/cpsc-keyword-pp_define.7.md b/doc/language/keyword/cpsc-keyword-pp_define.7.md
new file mode 100644
index 0000000..f48148c
--- /dev/null
+++ b/doc/language/keyword/cpsc-keyword-pp_define.7.md
@@ -0,0 +1,45 @@
+% CPSC-KEYWORD-PP_DEFINE(7)
+
+# NAME
+
+cpsc-keyword-pp_define, cpsc-keyword-pp_undef - define and remove preprocessor switches
+
+# SYNOPSIS
+
+```text
+PP_DEFINE name
+PP_UNDEF name
+```
+
+# DESCRIPTION
+
+PP_DEFINE and PP_UNDEF are compiler extensions processed before ordinary source code is tokenized. Each directive occupies its own line, optionally preceded by whitespace and followed by a // comment. Names contain ASCII letters, digits and underscores, starting with a letter or underscore. Directive keywords are uppercase; switch names are case-sensitive, unlike ordinary pseudocode identifiers.
+
+PP_DEFINE enables a switch and PP_UNDEF removes it. Defining an already defined switch or removing an undefined switch has no effect. Switches have no values, do not replace source text and use a namespace separate from ordinary identifiers. Extra arguments are errors. There are no command-line switch options.
+
+Each source file starts with no switches defined. Definitions take effect in source order and continue until removed or the file ends, including across function boundaries. INCLUDE imports symbols from independently preprocessed files; switches never pass between files. Definitions in a disabled conditional region have no effect. See [cpsc-keyword-pp_ifdef(7)](cpsc-keyword-pp_ifdef.7.md) for conditional compilation.
+
+The special switch __LIB marks subsequent source positions as library code. PP_UNDEF __LIB restores ordinary code behavior for subsequent positions; both directives may appear inside a function. Runtime checks in ordinary code report their own source line. Checks in library code use the shared user call line: calls from ordinary code update it, while calls from library code preserve it. This also covers methods, operators, EXTERN calls and automatic construction or destruction. Templates retain the modes at their original definition positions. Compile-time diagnostics always retain their original source file and line. The former #LIB syntax is rejected.
+
+C++ library objects may read `extern "C" int __cps_user_line`, print `[Fatal] line N: reason` to stderr and throw an anonymous integer exception for pseudocode TRY/CATCH. The global is shared by the program and is not thread-local.
+
+# EXAMPLE
+
+```text
+PP_DEFINE __LIB
+PROCEDURE Check()
+ DECLARE A : ARRAY[1:1] OF INTEGER
+ OUTPUT A[2]
+ENDPROCEDURE
+PP_UNDEF __LIB
+
+TRY
+ CALL Check() // The library bounds check reports this call's line.
+CATCH
+ OUTPUT "Bounds error caught"
+ENDTRY
+```
+
+# SEE ALSO
+
+[cpsc-keyword-pp_ifdef(7)](cpsc-keyword-pp_ifdef.7.md), [cpsc-keyword-include(7)](cpsc-keyword-include.7.md), [cpsc-keyword-try(7)](cpsc-keyword-try.7.md).
diff --git a/doc/language/keyword/cpsc-keyword-pp_ifdef.7.md b/doc/language/keyword/cpsc-keyword-pp_ifdef.7.md
new file mode 100644
index 0000000..b84645d
--- /dev/null
+++ b/doc/language/keyword/cpsc-keyword-pp_ifdef.7.md
@@ -0,0 +1,45 @@
+% CPSC-KEYWORD-PP_IFDEF(7)
+
+# NAME
+
+cpsc-keyword-pp_ifdef, cpsc-keyword-pp_ifndef, cpsc-keyword-pp_endif - conditionally compile source regions
+
+# SYNOPSIS
+
+```text
+PP_IFDEF name
+ source lines
+PP_ENDIF
+
+PP_IFNDEF name
+ source lines
+PP_ENDIF
+```
+
+# DESCRIPTION
+
+PP_IFDEF, PP_IFNDEF and PP_ENDIF are compiler extensions processed before lexing and parsing. PP_IFDEF includes its region when the named switch is defined; PP_IFNDEF includes it when the switch is undefined. Both require exactly one switch name. Each must have a matching PP_ENDIF, which takes no arguments. Conditions may nest, and a region is included only when all enclosing conditions are enabled. There is no PP_ELSE or condition-expression syntax.
+
+Directives occupy their own lines, optionally preceded by whitespace and followed by // comments. Keywords and switch names are case-sensitive. Switches belong to each file independently and change in source order through [cpsc-keyword-pp_define(7)](cpsc-keyword-pp_define.7.md).
+
+Disabled ordinary source is not lexed, parsed or compiled, and its PP_DEFINE and PP_UNDEF directives have no effect. Conditional nesting is still checked, including inside disabled regions. Directive lines and disabled source preserve original line numbering for diagnostics. Preprocessor conditions do not introduce ordinary scopes or add indentation in the VS Code plugin or Bundle.
+
+# EXAMPLE
+
+```text
+PP_DEFINE Debug
+PP_IFDEF Debug
+OUTPUT "Debug enabled"
+PP_IFNDEF Quiet
+OUTPUT "Verbose debug output"
+PP_ENDIF
+PP_ENDIF
+PP_UNDEF Debug
+PP_IFNDEF Debug
+OUTPUT "Debug disabled"
+PP_ENDIF
+```
+
+# SEE ALSO
+
+[cpsc-keyword-pp_define(7)](cpsc-keyword-pp_define.7.md), [cpsc-language-overview(7)](../cpsc-language-overview.7.md).