Elvelt

Standard Library

Header hierarchy and when to include each

Header hierarchy and when to include each

The MPL Standard Library and runtime are split across six headers plus the C++ implementation. This page documents the hierarchy, dependencies, and recommended inclusion patterns.

Header overview

Header Path Size Provides
CppImpl.h MPL_Standard/CppImpl.h 335 lines mpl::System::* stdlib (Console, Math, IO, Path, Process, String, DateTime, Environment)
empl.h MPL_Standard/System/empl.h ~3000 lines (legacy all-in-one) Legacy monolithic runtime; delegates to empl_core.h + JS adapter region
empl_core.h MPL_Standard/System/empl_core.h ~1300 lines mpl_value, mpl_object, mpl_promise<T>, mpl_generator<T>, mpl_error, microtask queue, event loop, callable/object model
empl_stdlib.h MPL_Standard/System/empl_stdlib.h 19 lines Marker file — canonical SoT is MPL_Standard/Specification.json (Phase 4.1+)
empl_runtime.h MPL_Standard/System/empl_runtime.h 164 lines mpl_os, mpl_crypto_random_uuid, mpl_crypto_random_bytes, mpl_iso8601_to_time_t, mpl_process_*
empl_pqc.h MPL_Standard/System/empl_pqc.h 395 lines mpl_pqc::* (ML-KEM, ML-DSA, SLH-DSA via OpenSSL 3.5+)

Dependency graph

                          ┌─────────────────────┐
                          │  CppImpl.h          │   (no internal deps; std only)
                          │  mpl::System::*     │
                          └─────────────────────┘
                                       ▲
                                       │  (used by)
                                       │
   ┌────────────────────────────────────┴────────────────────────────────────┐
   │                                                                         │
   │                                                                         │
┌─────────────────────┐                                          ┌─────────────────────┐
│  empl_core.h        │ ──includes──►  empl_pqc.h                 │  empl_runtime.h     │
│  mpl_value, ...     │                                          │  mpl_os, ...        │
└─────────────────────┘                                          └─────────────────────┘
         ▲                                                                  │
         │                                                                  │
         │  (empl_runtime.h provides mpl_value overload via empl_core.h)   │
         │                                                                  │
         └──────────────────────────┐                                       │
                                    │                                       │
                          ┌─────────────────────┐                            │
                          │  empl_stdlib.h      │                            │
                          │  (marker file)      │                            │
                          └─────────────────────┘                            │
                                    ▲                                        │
                                    │                                        │
                          ┌─────────────────────┐                            │
                          │  empl.h             │ ────includes───────────────┘
                          │  (legacy all-in-one)│
                          └─────────────────────┘

Reading the graph:

  • empl_core.h includes empl_pqc.h (line 64 of empl_core.h).
  • empl_runtime.h does NOT include empl_core.h — its mpl_value overload of mpl_iso8601_to_time_t is defined in empl_runtime.h but only compiles when empl_core.h is also included (otherwise mpl_value is undefined).
  • empl.h includes all of empl_core.h, empl_runtime.h, empl_pqc.h, plus the JS adapter region.
  • empl_stdlib.h is a 19-line marker file containing no actual code — it documents the Phase 4.1 architectural change where the canonical SoT moved from empl_stdlib.h to MPL_Standard/Specification.json.
  • CppImpl.h is standalone — it includes only the C++ standard library headers it needs (lines 14-24), no internal MPL headers.

What each header provides

CppImpl.hmpl::System::*

The C++ implementation of the language-neutral standard library. Every function is inline and lives in the mpl::System namespace:

Sub-namespace Functions
mpl::System::Console WriteLine, Write, ErrorWriteLine, ErrorWrite, ReadLine
mpl::System::Environment GetVariable, SetVariable, GetCurrentDirectory, SetCurrentDirectory, GetPlatform, GetNewLine
mpl::System::IO ReadFileText, WriteFileText, FileExists, DeleteFile, CreateDirectory, DeleteDirectory, GetDirectoryEntries
mpl::System::IO::Path Join, GetDirectoryName, GetFileName, GetExtension, GetFullPath
mpl::System::Process Exit, GetCommandLineArgs, GetRuntimeVersion
mpl::System::Math Abs, Floor, Ceil, Round, Sqrt, Pow, Max, Min, Pi, E
mpl::System::String Trim, ToLower, ToUpper, StartsWith, EndsWith, Split, Join
mpl::System::DateTime NowUnixMs, NowUnixSeconds

See cpp-impl.md for the function-by-function C++ reference.

empl_core.h — language-agnostic core

The language-agnostic core runtime that all language adapters build on:

Component Lines (approx.) Description
mpl_value 591 std::variant for JS-style typed values
mpl_object 552 JS-style object with property descriptors
mpl_property_descriptor 540 Writable/enumerable/configurable triple
mpl_promise<T> 270 Promise semantics with then / catch
mpl_promise<void> 371 Specialization for void promises
mpl_generator<T> 428 Generator type
mpl_microtask_queue 173 Microtask queue + mutex + CV
mpl_run_event_loop_until 235 Event loop with done() predicate
mpl_box_value<T> 1075 Type-dispatched box-to-mpl_value
mpl_call, mpl_callv, mpl_call_method 815 Callable invocation helpers
mpl_error 82 Base error class with name + message + source_location
mpl_throw_type_error 115 Throws a TypeError with source-location context
mpl_throw_reference_error 134 Throws a ReferenceError
mpl_strict_mode_flag 138 Thread-local strict-mode flag
mpl_try_dispose, mpl_try_async_dispose 488, 470 Dispose / asyncDispose fallbacks
mpl_to_string (template + overloads) 151, 506, 511, 529, 956, 974, 978, 985, 996 Stringification (all primitive types)
mpl_to_number (forward decl) 704 Numeric coercion
mpl_json_stringify (template + overloads) 1037, 1066, 1076, 1127, 1131, 1135 JSON serialization
mpl_math_runtime 1155 JS-Math-style helper struct
mpl_make_arguments_object 652 Build a JS-style arguments object

Plus forward declarations for the JS-adapter region that lives in empl.h.

empl_runtime.h — runtime utilities

Component Lines Description
mpl_os 44 Platform / arch / hostname / homedir
mpl_crypto_random_uuid 90 RFC 4122 v4 UUID
mpl_crypto_random_bytes 113 Hex random bytes
mpl_iso8601_to_time_t (string overload) 130 ISO 8601 → Unix seconds
mpl_iso8601_to_time_t (mpl_value overload) 155 Variant-arg delegate
mpl_process_exit 160 Process termination
mpl_process_cwd (stub) 161 Returns "/"
mpl_process_chdir (stub) 162 No-op
mpl_process_nextTick 163 Microtask queue

empl_pqc.h — post-quantum crypto

Component Lines Description
mpl_pqc::kem_nid 88 ML-KEM NID lookup
mpl_pqc::sig_nid 98 ML-DSA / SLH-DSA NID lookup
mpl_pqc::primitive_available 122 Algorithm availability check
mpl_pqc::kem_keypair, sig_keypair, kem_encap_result 138-140 Result types
mpl_pqc::kem_keygen 142 ML-KEM keypair generation
mpl_pqc::kem_resolve_public / kem_resolve_private 175, 192 Load raw key → EVP_PKEY
mpl_pqc::sig_resolve_public / sig_resolve_private 209, 226 Load raw signing key
mpl_pqc::kem_encapsulate 243 ML-KEM encapsulate
mpl_pqc::kem_decapsulate 268 ML-KEM decapsulate
mpl_pqc::sig_keygen 294 ML-DSA / SLH-DSA keypair generation
mpl_pqc::sig_sign 326 One-shot sign
mpl_pqc::sig_verify 353 One-shot verify
__mpl_pqc_* aliases 379-393 C-style aliases for JS interop

empl_stdlib.h — marker file

19 lines. As of Phase 4.1, the canonical SoT for stdlib is MPL_Standard/Specification.json. This header is intentionally a marker; concrete stdlib callables are still attached to mpl_* symbols in empl_core.h.

empl.h — legacy all-in-one

The pre-Phase-3 monolithic runtime. Approximately 3000 lines. It includes:

  • All of empl_core.h (transitively, via direct #include).
  • The empl_pqc.h content (transitively, since empl_core.h includes it).
  • Boost headers (Asio, Beast, JSON, multiprecision, UUID).
  • OpenSSL headers.
  • Brotli, zlib.
  • The JS adapter region (Symbol implementation, JSON, Math, Date, Reflect, Promise adapter, microtask plumbing).
  • The Node-runtime builtin materialization (modules like fs, path, crypto, http, net, stream, worker_threads, os, url, events, util, buffer, child_process, cluster, tls, dgram, dns).
  • Phase 4+ node-runtime additions (node:perf_hooks, node:async_hooks, node:worker_threads).

empl.h is kept for backward compatibility with existing code that includes it directly. New code should prefer the granular headers (empl_core.h, empl_runtime.h, empl_pqc.h) plus CppImpl.h for stdlib.

When to include which header

You are writing a C++ program that uses MPL stdlib

#include "MPL_Standard/CppImpl.h"   // mpl::System::*

That's it. CppImpl.h is standalone — no other MPL headers required.

You are writing a runtime helper that needs mpl_value

#include "MPL_Standard/System/empl_core.h"   // mpl_value, mpl_object, mpl_promise, ...

Provides the boxed-value system and Promise semantics. No stdlib here — add CppImpl.h separately if needed.

You are writing a runtime helper that needs OS info / ISO 8601 / random UUID

#include "MPL_Standard/System/empl_runtime.h"   // mpl_os, mpl_iso8601_to_time_t, ...

Note: empl_runtime.h does NOT bring in mpl_value. If you also need mpl_value, include empl_core.h too.

You are writing code that uses post-quantum crypto

#include "MPL_Standard/System/empl_pqc.h"   // mpl_pqc::*

Provides the mpl_pqc namespace with ML-KEM / ML-DSA / SLH-DSA primitives. Requires OpenSSL 3.5+ at runtime.

You are writing a frontend (parser) or a runtime adapter

#include "MPL_Standard/System/empl.h"   // everything

The legacy all-in-one. Convenient but heavy (pulls in Boost, OpenSSL, Brotli, zlib).

For new frontends, prefer the granular headers:

#include "MPL_Standard/CppImpl.h"                  // stdlib
#include "MPL_Standard/System/empl_core.h"         // mpl_value, mpl_promise
#include "MPL_Standard/System/empl_runtime.h"       // mpl_os, mpl_iso8601_to_time_t
#include "MPL_Standard/System/empl_pqc.h"           // mpl_pqc

You are writing a unit test

// PQC-only test
#include "MPL_Standard/System/empl_pqc.h"

// Stdlib-only test
#include "MPL_Standard/CppImpl.h"

// Runtime-only test
#include "MPL_Standard/System/empl_runtime.h"

Avoid empl.h in tests — its 3000 lines will slow compilation.

Cross-cutting concerns

Thread-local state

Header Thread-local state
empl_core.h mpl_strict_mode_flag, mpl_fn_props, mpl_callable_object_cache, mpl_callable_object_owners, mpl_new_this_ptr, mpl_current_arguments_slot
empl_runtime.h std::mt19937_64 inside mpl_crypto_random_uuid and mpl_crypto_random_bytes
CppImpl.h None (pure functions)
empl_pqc.h None

Compile-time guards

Header Guards
empl_pqc.h MPL_PQC_H (header guard) + OpenSSL version checks (OPENSSL_VERSION_NUMBER < 0x30200000L) for compatibility shims
empl_runtime.h MPL_PLATFORM_WINDOWS, MPL_PLATFORM_POSIX, MPL_PLATFORM_DARWIN
empl_core.h None
CppImpl.h None
empl.h None
empl_stdlib.h None

See also