:sig UCE source preprocessing :desc UCE runs a small custom source-to-source preprocessor before Clang sees a `.uce` or `.ws.uce` file. The implementation lives in `src/lib/compiler.cpp`. It does not try to parse all of C++. Instead, it performs a narrow character-wise rewrite that understands UCE literal blocks, inline code islands, `#load`, and `EXPORT` harvesting, then writes a generated `.cpp` file and compiles that file into a shared object. :Syntax - `<> ... ` enters literal-output mode. - Inside a literal block, `` emits raw C++. - Inside a literal block, `` emits `print(html_escape(expression));`. - Inside a literal block, `` emits `print(expression);` without HTML escaping. - `#load "other.uce"` injects another UCE unit at compile time. - `RENDER(Request& context)`, `COMPONENT(Request& context)`, and `WS(Request& context)` are normal C++ macros from `src/lib/compiler.h`. - `COMPONENT:NAME(Request& context)` is rewritten by the custom pass into an exported named component handler. - `EXPORT` is also a normal C++ macro, but the custom pass additionally records exported declarations for metadata. :Pipeline - The generated file starts by including `COMPILER_SYS_PATH/src/lib/uce_lib.h`. - It then inlines the configured setup template from `SETUP_TEMPLATE` (by default `scripts/setup.h.template`), which defines the internal hook `__uce_set_current_request(Request*)`. - It inserts `#line 1` before page code so compiler diagnostics point back to the original `.uce` file. - Each literal block is rewritten into one or more `print(R"( ... )");` calls. - `` temporarily breaks out of literal printing, emits the enclosed C++ unchanged, then resumes literal output. - `` becomes `print(html_escape(...));`. The runtime currently provides `html_escape()` overloads for `String`, `u64`, and `f64`. - `` becomes `print(...);` and is intended for trusted markup or already-escaped content. - `#load "file.uce"` is replaced with a generated C++ `#include` that points at the loaded unit's preprocessed `.cpp` file under `BIN_DIRECTORY`. - Lines beginning with `EXPORT` are scanned so their declarations can be written to a sibling `.exports.txt` file. - Lines beginning with `RENDER:NAME(...)` are rewritten into exported `__uce_render_NAME(...)` functions. - Lines beginning with `COMPONENT:NAME(...)` are rewritten into exported `__uce_component_NAME(...)` functions for the component helpers. - The final generated source is written to `BIN_DIRECTORY + src_path + "/" + source_file + ".cpp"`. - `scripts/compile` then compiles that generated `.cpp` into `source_file + ".so"` with `clang++ -shared -std=c++20 ...`. :GeneratedFiles - Source file: `/some/path/page.uce` - Generated C++: `BIN_DIRECTORY/some/path/page.uce.cpp` - Shared object: `BIN_DIRECTORY/some/path/page.uce.so` - Export list: `BIN_DIRECTORY/some/path/page.uce.exports.txt` :Example Example 1: literal output with escaped data `RENDER(Request& context)` `{` ` <><h1><?= context.params["DOCUMENT_URI"] ?></h1></>` `}` Roughly becomes: `print(R"(<h1>)");` `print(html_escape(context.params["DOCUMENT_URI"]));` `print(R"(</h1>)");` Example 1b: literal output with trusted unescaped markup `RENDER(Request& context)` `{` ` <><div class="panel"><?: component("components/card", context.call, context) ?></div></>` `}` Roughly becomes: `print(R"(<div class="panel">)");` `print(component("components/card", context.call, context));` `print(R"(</div>)");` Example 2: compile-time composition `#load "partials/nav.uce"` `RENDER(Request& context)` `{` ` <><body>...</body></>` `}` The loaded file is resolved relative to the current source file unless the path is already absolute. :Rules - Literal mode starts only on the exact token `<>`. - Literal mode ends only on the exact token ``. - `#load` is recognized only when the current line starts with `#load ` at column 1. - `EXPORT` harvesting likewise only triggers when the current line starts with `EXPORT` at column 1 and is followed by whitespace. - Relative `#load` paths are expanded against the including unit's source directory. - `unit_render()` and `unit_call()` are runtime APIs; `#load` is a compile-time include/composition feature. :Limitations - This pass is character-wise, not a full parser. - Outside literal blocks it only tracks double-quoted C++ strings while deciding whether `<>` should open literal mode. - It does not understand comments, raw string literals, templates, or general C++ token structure. - Inside literal blocks it tracks single and double quotes while scanning a `` island so quoted `?>` text does not close the island early. - Literal blocks are not nested. - Because literal output is emitted as a C++ raw string literal `R"( ... )"`, literal content must not contain the exact terminator sequence `)"` or the generated C++ will break. - `#load` depends on the target unit's generated `.cpp` existing and being compilable. If the target cannot be preprocessed or compiled correctly, the including file will fail to compile as well. :Debugging - When a page is compiled, inspect the generated file under `BIN_DIRECTORY` first. That file shows the exact C++ produced by the UCE preprocessor. - Compiler errors usually point back to the `.uce` source because the preprocessor inserts `#line 1`, but the generated `.cpp` is still the best place to inspect expansion problems. - If a `#load` include looks wrong, check the current file's directory, the configured `BIN_DIRECTORY`, and whether the loaded page already produced its own generated `.cpp`. :see load unit_render unit_call 0_context 1_COMPONENT :related **PHP:** Template tags like ``, ``, output buffering, and compile-time include patterns **JavaScript / Node.js:** JSX transforms, tagged templates, server-side rendering pipelines, and build-time HTML generation