Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

This chapter explains how ROUP is organised internally and where to look when modifying the parser or the public bindings.

High level view

source text
   │
   ▼
lexer (`src/lexer.rs`)
   │  ─ token stream with language specific helpers
   ▼
parser (`src/parser/`)
   │  ─ parses directives/clauses and owns post-parse semantic normalization
   ▼
Enum AST / IR (`src/ast/`, `src/ir/`)
   │  ├─ typed directive and clause payloads for Rust callers
   │  └─ converted into the C API data structures
   ▼
C bindings (`src/c_api.rs`, `src/c_api/openacc.rs`)

The lexer normalises whitespace, line continuations, sentinel comments, and language specific keywords before the parser consumes the token stream. The parser modules mirror the OpenMP/OpenACC structure: directives, clauses, helper enumerations, semantic conversion, and validation passes. Rust callers can work with the typed enum AST/IR structures, while C and C++ consumers receive stable C structs exposed through the FFI layer.

Unsafe code boundaries

The parser, AST, IR, lexer, and debugger modules forbid unsafe Rust. The only unsafe blocks live in the FFI modules (src/c_api.rs and src/c_api/openacc.rs) where pointers cross the C boundary. Each function performs explicit null checks and documents its expectations. When modifying or adding FFI functions, keep the following rules in mind:

  • Convert raw pointers to Rust types as late as possible and convert back only when returning values to the caller.
  • Maintain ownership invariants: the caller is responsible for freeing values returned by constructors and must not free borrowed data.
  • Update the generated C constants header whenever the exported structs or enums change.

Generated constants and headers

The build script (build.rs) parses portions of src/c_api.rs and src/c_api/openacc.rs using syn to produce src/roup_constants.h (also emitted to OUT_DIR). This keeps the OpenMP and OpenACC directive/clause tables in sync with the Rust implementation.

Compatibility layers

  • compat/ompparser/ mirrors the original ompparser API, forwarding calls through the ROUP C API and converting the resulting structures back into the expected C++ types. The CMake tests in the ompparser submodule validate parity.
  • compat/accparser/ provides the same drop-in experience for accparser with ROUP_ACC_* constants and the upstream ctest suite.

Testing

Integration tests live under tests/ and cover keyword registration, parser round-trips, language specific behaviour, and helper utilities. Running cargo test executes the Rust suites, while test.sh orchestrates the full project matrix including compatibility tests, documentation builds, warning checks, and the enum/safety audit.