Elvelt

Standard Library

MPL Standard Library — overview

MPL Standard Library — overview

The MPL Standard Library is the language-neutral standard library specification used by MPL_Compiler. It sits between frontends (source languages) and backends (target languages) as the canonical pivot for "do the standard thing" — printing to stdout, reading a file, computing a square root, joining paths, etc.

Design philosophy

  1. Language neutrality. The library is not "JavaScript's stdlib" or "Python's stdlib" — it is a minimal cross-language superset of common operations. Every source language maps its own idiomatic calls to the same StandardLibraryCallNode IR.
  2. Backend neutrality. The library is not "C++ stdlib" — it is described abstractly in MPL_Standard/Specification.json and implemented concretely per backend. The C++ implementation lives in MPL_Standard/CppImpl.h; future backends (JS, Python, Rust) will have their own implementations.
  3. Minimal common set. The library deliberately excludes operations that are not universally available (e.g. no Window.Open, no xml.etree, no numpy.array). When a language lacks an operation, the frontend emits UnsupportedNode.
  4. Single source of truth (SoT). MPL_Standard/Specification.json is the machine-readable canonical definition. C++ headers (CppImpl.h, empl.h, empl_core.h, empl_stdlib.h, empl_runtime.h, empl_pqc.h) are derivations of that spec.

Architecture

Source language code (e.g. console.log, print, Math.sqrt)
    │
    │ Frontend maps to:
    ▼
EMPL IR: StandardLibraryCallNode { moduleName, functionName, arguments, argumentNames }
    │
    │ Backend lowers to:
    ▼
Target language equivalent
    C++: mpl::System::Console::WriteLine(mpl_to_string(...))
    JS: console.log(...)
    Python: print(...)

Specification.json (SoT)

MPL_Standard/Specification.json (referenced in MPL_Standard/README.md line 6) is the canonical machine-readable definition of the standard library. It specifies:

Field Purpose
modules[] The list of stdlib modules (e.g. Console, Math, IO).
functions[] Each module's functions with parameter types, return types, and behavior.
typeMappings How canonical types (string, int, number, bool, List<T>, …) map to each language's type system.
versioning Schema version of the spec (for compatibility tracking).

The JSON file is consumed by:

  • The C++ backend, which generates the MPL_Standard/System/*.h headers (currently pre-generated as CppImpl.h).
  • The validator (EMPLValidator), which checks StandardLibraryCallNode::moduleName and functionName against the spec.
  • The frontend mapper, which reads the spec to build its source-language → stdlib translation table.

Canonical modules

The MPL Standard Library currently ships 8 modules:

Module Purpose Header section
Console Standard input/output CppImpl.h:32-60
Environment Environment variables, platform info CppImpl.h:65-111
IO File system operations CppImpl.h:116-187
Path Path manipulation (nested in IO) CppImpl.h:159-185
Process Process control and info CppImpl.h:192-207
Math Mathematical operations and constants CppImpl.h:212-254
String String manipulation utilities CppImpl.h:259-315
DateTime Date and time operations CppImpl.h:320-332

Each module is documented in detail on its own page:

  • modules.md — every function with full signature, parameters, return type, behavior, and language-mapping notes

C++ implementation reference

The C++ implementation lives in MPL_Standard/CppImpl.h (335 lines). It declares every stdlib function in the mpl::System namespace, with sub-namespaces for each module:

namespace mpl { namespace System {
    namespace Console { /* WriteLine, Write, ErrorWriteLine, ErrorWrite, ReadLine */ }
    namespace Environment { /* GetVariable, SetVariable, GetCurrentDirectory, ... */ }
    namespace IO { /* ReadFileText, WriteFileText, FileExists, ... */
        namespace Path { /* Join, GetDirectoryName, GetFileName, ... */ }
    }
    namespace Process { /* Exit, GetCommandLineArgs, GetRuntimeVersion */ }
    namespace Math { /* Abs, Floor, Ceil, Round, Sqrt, Pow, Max, Min, Pi, E */ }
    namespace String { /* Trim, ToLower, ToUpper, StartsWith, EndsWith, Split, Join */ }
    namespace DateTime { /* NowUnixMs, NowUnixSeconds */ }
}}

All functions are inline and header-only (C++20). The C++ backend emits calls directly to this namespace — see cpp-impl.md for the function-by-function C++ implementation reference.

Header hierarchy

The runtime headers form a layered hierarchy:

empl.h                  ← legacy all-in-one (delegates to empl_core.h)
empl_core.h             ← language-agnostic core (mpl_value, mpl_object, mpl_promise, …)
empl_stdlib.h           ← marker file (canonical SoT is Specification.json as of Phase 4.1)
empl_runtime.h          ← runtime utilities: mpl_process_*, mpl_os, mpl_crypto, mpl_iso8601_to_time_t
empl_pqc.h              ← post-quantum crypto (ML-KEM / ML-DSA / SLH-DSA via OpenSSL 3.5+)
CppImpl.h               ← language-neutral stdlib C++ implementation (mpl::System::*)

See headers.md for the differences, dependencies, and when to include each.

Type-mapping table

The spec defines how canonical types map to each language. Excerpt:

Canonical (JSON) C++ JavaScript Python
string std::string string str
string? std::optional<std::string> string | undefined Optional[str]
int int number int
int64 int64_t bigint int
number double number float
bool bool boolean bool
void void undefined None
never [[noreturn]] never NoReturn
List<T> std::vector<T> Array<T> List[T]
Map<K, V> std::unordered_map<K, V> Map<K, V> Dict[K, V]
any mpl_value (variant) any Any
variadic C-style variadic / template pack ...args *args

Language neutrality guarantees

The MPL Standard Library is contractually neutral on the following axes. Adding a new frontend or backend MUST NOT require modifications to any existing module or function definition.

Guarantee Enforcement
Names are PascalCase (WriteLine, not writeLine or write_line). Validator V4.
Modules are PascalCase singular (Console, Math, IO). Validator V4.
Every function has a stable signature in Specification.json. Spec version pinned.
Every function has a documented language-specific source mapping. This documentation.
No function takes language-specific types (e.g. no JSObject, no PythonList). Spec review.
Return types are concrete and total (no partial functions, no throws without documentation). Spec review + validator warnings.

IR representation

Every stdlib call in source code is emitted by the frontend as a StandardLibraryCallNode:

// core/ir/EMPLNode.h:517
class StandardLibraryCallNode : public EMPLNode {
public:
    std::string moduleName;    // e.g. "Console", "Math", "IO"
    std::string functionName;  // e.g. "WriteLine", "Sqrt", "ReadFileText"
    std::vector<EMPLNodePtr> arguments;
    std::vector<std::string> argumentNames; // for named arguments (optional)
};

The validator (rule V4) checks that moduleName and functionName match the spec. The backend lowers StandardLibraryCallNode to the target-language equivalent.

See ../empl/nodes/calls.md for the full StandardLibraryCallNode reference.

See also

Phase history

The MPL Standard Library has evolved through several phases:

Phase Date Major change
Phase 1 2024 Initial mpl::System::* namespace in CppImpl.h
Phase 2 2024-Q4 Added Environment.GetNewLine, IO.GetDirectoryEntries, Math.Pow
Phase 3 (D-Series) 2025 Split monolithic empl.h into empl_core.h + empl_runtime.h + empl_pqc.h
Phase 4.1 2025-Q3 Promoted MPL_Standard/Specification.json to canonical SoT; empl_stdlib.h becomes a marker file
Phase 5-A 2025-Q4 Added Process.GetCommandLineArgs integration with main(argc, argv)
Phase 5-B 2026-Q1 Added mpl_os, mpl_crypto_random_uuid, mpl_iso8601_to_time_t to empl_runtime.h
Phase A-3 2026-06 Added post-quantum crypto (empl_pqc.h) with ML-KEM / ML-DSA / SLH-DSA
Phase 5-C (planned) Add Map, Set, DateTime.Parse, String.Replace to the spec

The current version is v3.4 (Phase 5-B + A-3).

Cross-language conformance test suite

The MPL_Compiler ships a conformance test suite that verifies each stdlib function produces the same result across all supported source languages. The tests are in tests/conformance/stdlib/:

tests/conformance/stdlib/
├── console.test.js           ← JS source-level test
├── console.test.py           ← Python source-level test
├── console.test.cs           ← C# source-level test
├── console.test.go           ← Go source-level test
├── console.test.rust         ← Rust source-level test
├── console.test.cpp          ← Native C++ test (against CppImpl.h directly)
└── console.test.expected     ← Expected output (cross-language)

Each test runs the same logical operation (e.g. "write 3 lines to stdout, read a file") in all supported languages, then compares outputs. A failure indicates either a frontend mapper bug or a backend lowering bug.

Adding a new function to the spec

To add a new function (e.g. Math.Log):

  1. Update MPL_Standard/Specification.json with the new function signature and behavior.
  2. Update MPL_Standard/CppImpl.h with the C++ implementation.
  3. Update the validator's allowed-functions list (in EMPLValidator.cpp).
  4. Update the frontend mappers (one per source language) to map source-language equivalents to the new function.
  5. Add a conformance test for each source language.
  6. Update modules.md with the new function.
  7. Bump the spec version in Specification.json.

The MPL Standard Library is designed to grow slowly. Most additions are language-specific (e.g. String.Replace, Math.Log) — additions that are not universally available across source languages are documented as "best-effort" and emit UnsupportedNode when the source language lacks an equivalent.

Layered architecture

                    ┌────────────────────────────┐
                    │  Source language code      │
                    │  console.log, print, …     │
                    └────────────────────────────┘
                                  │
                                  │  Frontend maps to:
                                  ▼
                    ┌────────────────────────────┐
                    │  StandardLibraryCallNode   │  ← language-neutral IR
                    │  { module, function, args }│
                    └────────────────────────────┘
                                  │
                                  │  Backend lowers to:
                                  ▼
                    ┌────────────────────────────┐
                    │  Target-language call      │
                    │  mpl::System::Console::…   │  ← C++ implementation
                    │  print(...), …             │  ← Python implementation
                    │  console.log(...)          │  ← JavaScript implementation
                    └────────────────────────────┘

The StandardLibraryCallNode is the canonical pivot. Adding a new source language requires only a frontend mapper (no spec changes); adding a new target language requires only a backend lowerer (no spec changes).