Elvelt

Frontends

Known Limitations

Known Limitations

This page catalogues the known limitations of every shipped frontend, with file:line references and the test status where applicable.

Universal limitations (apply to all frontends)

These are intrinsic to the current single-backend C++ implementation, not specific to a source language:

Limitation Workaround
Single backend: C++ only Compile to C++ first, then call another compiler
No link-time optimisation Use compiler-specific LTO flags on the generated C++
No incremental compilation Re-compile all files when source changes
StdLib calls must be in MPL_Standard/Specification.json Add new entries to the spec
UnsupportedNode IR for unknown syntax Lower manually via runtime helper functions

JavaScript / TypeScript

Real-time, concurrency, and Node-specific features

Limitation File / Notes
JSX is emitted as a placeholder FunctionCallNode("jsx") JSFrontend.h:907-930. Real JSX → C++ codegen is not yet shipped.
Decorators: Stage 3 semantics only js_semantics.h (decorators section). Legacy / experimental decorators not supported.
?? and ?. Lowered correctly via BraceFrontendBase; rare corner cases (e.g. chained a?.b?.c) may not bind exactly as JS does.
Proxies Reflected via mpl_get_value(globalThis, "Proxy") but Proxy semantics not deeply lowered.
Web Workers Worker threads emit __mpl_register_es2026_extras hooks but real worker scheduling is not implemented.
SharedArrayBuffer Stored as a singleton, no actual shared-memory backend.
WeakRefs Tracked but finalisation may not match JS exactly.

Module resolution edge cases

Limitation Notes
node:sqlite Lowered to __mpl_sqlite_require__ with stubs (js_es2026.h:702). Real SQLite binding not yet shipped.
undici Heavy HTTP machinery is stubbed via __undici_stub (JSFrontend.h:46-87).
Circular ESM dependencies Module graph expansion handles them but execution order may differ.
package.json#imports Self-references via #name are resolved but #name/... sub-paths may not be.
Conditional exports ("browser") Only "import", "require", "node", "default" are matched.
Subpath imports (exports: { "./foo": ... }) Basic form supported; conditional arrays may not all be resolved.

WILL_FAIL tests

The following tests are expected to fail (the compiler correctly rejects the input — these are intentional negative tests):

Test Reason
js_strict_mode_violation_impl_test Octal escape or duplicate binding in strict mode
js_module_duplicate_lexical_impl_test Same lexical binding twice in ESM
js_module_lexical_var_conflict_impl_test Lexical/var conflict in ESM
js_module_duplicate_params_impl_test Duplicate params in ESM
js_module_implicit_strict_violation_impl_test with or octal escape in implicit-strict ESM
js_strict_binding_violation_impl_test eval / arguments reassignment in strict
js_strict_reserved_binding_violation_impl_test Reserved-word binding in strict
js_strict_duplicate_params_impl_test Duplicate params in strict function
js_strict_arrow_duplicate_params_impl_test Duplicate params in strict arrow
js_class_method_strict_binding_impl_test Strict-binding violation inside class method
js_throw_newline_violation_impl_test throw\n (no semicolon) is illegal in strict
js_with_module_class_nonfunc_impl_test with in module class non-function
js_bare_specifier_exports_null_block_impl_test Bare specifier with null block
js_package_imports_null_block_impl_test #imports block with null

Not supported

  • eval of arbitrary strings (no eval() runtime).
  • with statement (rejected in strict; ignored in sloppy).
  • eval / arguments reassignment (rejected in strict).
  • Direct arguments.callee access (rejected in strict).
  • Non-standard __proto__ set in sloppy mode (consistent with ES2015+).
  • Legacy octal escapes (\077) in strict mode.
  • HTML comments (<!-- -->) at the top of script files.

Python

Type system

Limitation File:line
Type annotations are type-erased PythonFrontend.h ignores all : T annotations
TypedDict, Protocol, Generic[T], Optional[T], Union[A, B] Silently dropped
Type aliases (type X = ..., PEP 695) Not supported
Generic classes (class Foo[T]: ...) Not supported
Type narrowing (TypeGuard, TypeIs) Not supported
match patterns Only literal patterns and wildcard _; dict / class / capture patterns are not supported (PythonFrontend.h:1867-1903)

Async / generators

Limitation Notes
async def lowers correctly but real async semantics depend on the C++ backend metadata["async"]="true"
await requires async context (compile-time check not enforced)
yield from Lowered as ordinary yield
Generator state Not modelled — generators run as ordinary functions

Context managers (with)

Limitation Notes
with expr as var: … becomes a TryCatchNode but __enter__ / __exit__ are not auto-emitted PythonFrontend.h:1844-1865
contextlib.contextmanager decorator Not recognised

Other gaps

Limitation Notes
__slots__, descriptors, metaclasses Not modelled
Star expressions inside patterns (*x) Not supported in match patterns
Exception groups (except*) Not supported
f-string conversion (!r, !s) Format specs captured but conversion flags ignored
@override, @final Accepted, ignored
super() with class and self arguments Lowered as ordinary call
Class decorators with arguments Treated as ordinary calls

C# (CSharpFrontend.cpp)

Real-time / type system

Limitation File:line
Nullable types (int?) are type-erased No Nullable<T> emission. The ? is dropped.
fixed buffer — emitted as __mpl_fixed__ but no codegen CSharpFrontend.cpp:1215-1237
volatile, readonly field modifiers Recognised, ignored
extern alias declarations Not supported
Operator overloads (operator +) Detected (metadata["operator"]="true") but no lowering
Conversion operators (implicit/explicit) Detected, no lowering
Indexer (this[...]) Flagged in metadata, no lowering
record primary constructor parameter binding Class is created but parameters are not auto-promoted to properties
Source generators / partial methods Not modelled
nameof constant evaluation Emitted as a runtime call
dynamic type Not supported
unsafe blocks BlockNode(metadata["unsafe"]="true") — no actual unsafe semantics
stackalloc Detected but no special lowering
Native interop (DllImport) Stored as metadata only

Pattern matching

Limitation Notes
case Type y (declaration pattern) Emitted as __mpl_pattern_match__ runtime call
Relational patterns (> 0 and < 100) Converted to &&
Or-patterns (1 or 2) Converted to ||
case var y when cond: Pattern + when clause; __mpl_when__ runtime hook
Property patterns (case { Prop: val }) Not yet supported
List patterns (case [1, 2, ..]) Not yet supported

LINQ

Limitation Notes
All 50+ LINQ extension methods are mapped CSharpStdLib.cpp methodMap
IQueryable providers Not supported — only IEnumerable
Expression trees Not preserved
AsQueryable() Not supported

Go

MVP synchronous semantics

Limitation File:line Notes
go f() runs inline (no goroutine) GoFrontend.h:361-373 MVP — no thread pool
defer f() runs at defer site (no LIFO) GoFrontend.h:347-359 MVP — no deferred semantics
select { case … } runs cases in order GoFrontend.h:1054-1197 MVP — no readiness check
for-range body executes once (synchronous iteration) GoFrontend.h:1208+ MVP — __go_range_* runtime hooks
Channel direction (chan<- T, <-chan T) direction is dropped

Type system

Limitation Notes
Generic type parameters (func F[T any](x T)) Passed through as raw identifier
type switch (switch v := x.(type)) Emitted as a regular switch
Embedding with promoted methods Only the embedded field is emitted; promotion is a backend concern
iota in const blocks Not yet supported
Build constraints (//go:build linux) Not honoured
unsafe.Pointer Detected but no special lowering

Not supported

  • Real concurrency primitives
  • Context propagation (context.WithCancel etc.)
  • Reflection (reflect.TypeOf, etc.) — only basic type-of is available
  • Goroutine stacks, panic recovery across goroutines
  • init() ordering across packages
  • Build tags

Rust

Type system and ownership

Limitation File:line
Borrow checker is not implemented Lifetimes (<'a>) are stored in metadata["rust_lifetimes"] but not validated
Generic type parameters (<T: Bound>) Stripped to the type identifier
where clauses (where T: Bound) Dropped
Trait object dispatch (dyn Trait) Passes through but not lowered to virtual table
impl Trait return types Stripped
Const generics (<const N: usize>) Stripped
Visibility modifiers (pub(crate), pub(super)) Stripped to pub
GAT (Generic Associated Types) Not supported

Pattern matching

Limitation File:line
let-else diverge body is dropped RustFrontend.h:421-425 (destructuring patterns lose divergence)
if let chain destructuring with complex patterns May lower incorrectly

Async / generators

Limitation Notes
async fn in traits Not modelled
gen blocks (gen {}) Not yet supported beyond yield expr
async blocks (async {}) Recognised but no lowering
? operator Not yet lowered to a Try-step call

Macros

Limitation Notes
macro_rules! Detected and lowered to FunctionDeclNode(metadata["macro_rules"]="true") — body is not processed
Procedural macros (#[derive(...)]) derive is ignored; the trait impls are not synthesised
include!, concat!, etc. Detected as ordinary calls, no special handling

PHP

Real-time / runtime

Limitation Notes
Real enum runtime Lowered to class with const values (transformEnumAccess, line 913)
Fibers Fiber::suspend() / Fiber::resume() are ordinary method calls — no coroutine semantics
Generators with yield from Lowered as ordinary statements
First-class callable (strlen(...)) Emitted as a runtime call, not a closure
match without default The frontend does NOT throw UnhandledMatchError (PHP would)
readonly enforcement Modifier is metadata only

Attributes & type system

Limitation Notes
Attributes (#[Attr]) Single-line forms are skipped via isIgnoredLine (line 369) — they're type-erased
Property hooks (PHP 8.4 RFC) Not yet supported
Asymmetric visibility (public private set) Not supported
Type juggling (string ↔ int in ==) The lowered C++ backend uses strict === always
Intersection types (A&B) Not supported
readonly class Modifier stored but not enforced
enum backed values Handled via transformEnumAccess constant substitution
match expression arms with side effects Only first matching arm fires (correct)

PSR / composer

Limitation Notes
PSR-4 autoloading Not honoured — files are loaded individually
composer.json resolution Not implemented
Namespaces map to file paths Convention not enforced

Ruby

Object system

Limitation Notes
Refinements (refine String do … end) No refinement scoping
Singleton methods (def obj.method; end) Not recognised outside class body
Method missing / respond_to_missing? Not synthesised
Struct.new(:x) accessors Auto-generated getters/setters may not match Ruby's []/[]= semantics
Symbol vs string :"foo" and ':foo' are stored as the same identifier
Frozen string literals (frozen_string_literal: true) Ignored
Lazy enumerator (Enumerator::Lazy) Not detected
Pattern matching (case … in pattern) Not yet supported
Numbered parameters (_1, _2, …) Not yet recognised
Safe navigation (obj&.method) Converted to obj != null ? obj.method() : nil only in obvious cases

Block / Proc semantics

Limitation Notes
Proc vs lambda difference (arity) Both lower to LambdaNode; strict-arity check not modelled
&block parameter The implicit __ruby_block_param is added but explicit &block is dropped
Block-local variables (; separator) Not modelled

Other

Limitation Notes
BEGIN / END blocks Not supported
require_relative Lowered as require
autoload Not supported
__method__, __FILE__, __LINE__ Not yet special-cased
prepend Stored as mixin metadata; no MRO enforcement

Java

Type system & modern features

Limitation Notes
Real sealed class enforcement permits parsed but not used to validate subclasses
Virtual threads Thread.startVirtualThread(...) is an ordinary call — no coroutine semantics
Scoped values (Java 21+ preview) Not supported
Structured concurrency (Java 21+ incubator) Not supported
String templates (STR."Hello \{name}") Parsed as ordinary string concatenation
Implicitly declared classes / instance main methods (Java 21+ preview) void main() parsed as regular method
FFM API (java.lang.foreign) References pass through; no FFM bindings emitted
record compact constructor (public Point { … }) Not specially recognised
record explicit canonical constructor override Auto-generated, may differ from explicit

Pattern matching for switch

Limitation Notes
Type patterns (case Integer i) Supported — binding extracted
Guarded patterns (case Integer i when i > 0) Not yet modelled
Record patterns (case Point(int x, int y) p) Not yet supported
Array patterns (case int[] arr when arr.length == 3) Not yet supported
Null case (Java 21+ preview) Parsed but lowered as ordinary case

EMPLS

Limitation Notes
Generic type parameters beyond List<T> Parsed as plain identifiers
Async / await Not yet modelled
Traits / interfaces Body not specialised
Multi-file module split (module math { … } in one file, used by import "math" in another) Flat file paths under source root, no real module system
Async lambdas Not yet recognised
Operator overloading Not supported
Compile-time function evaluation Not yet modelled
Pattern matching Not supported

Cross-language limitations

StdLib coverage

Module Status
Console.* (WriteLine, Write, ErrorWriteLine, ErrorWrite, ReadLine) All frontends
Math.* (Abs, Floor, Ceil, Round, Sqrt, Pow, Max, Min, Random, Trunc, Sign, Log, Log2, Log10, Sin, Cos, Tan, Atan2, sumPrecise) All frontends
String.* (Length, ToLower, ToUpper, Trim, Split, Join, StartsWith, EndsWith, Format) All frontends
IO.* (ReadFileText, WriteFileText, FileExists, CreateDirectory, Path.Join, Path.GetDirectoryName, Path.GetFileName) All frontends
Process.* (Exit) All frontends
Environment.* (GetVariable, SetVariable, GetCurrentDirectory) All frontends
DateTime.* (NowUnixMs, NowUnixSeconds) Not yet mapped from any source language
Json.* (Parse, Stringify) JS, Python, Go, Java, Rust, Ruby (partial), PHP
Convert.* (ToInt, ToFloat, ToString) Python, Java
Collection.* (Length) Python (len)
Crypto.*, OS.*, PQC.* JS only (via runtime headers)

Runtime semantics

Aspect Status
Type-erasure All source types become auto/any in the IR unless explicitly typed (EMPLS only)
Reference equality vs value equality == always lowers to value equality on the C++ side
Garbage collection Reference-counted mpl_object with cycles broken by mpl_gc_collect
Async runtime JS uses mpl_promise<T>; other languages use ad-hoc approaches
Error model throw / try-catch lowers to __mpl_throw__ / C++ exceptions
Operator precedence Mirrors the source language as closely as possible; rare JS ?? / ?. cases may differ

Adding a new language to the supported set

See registration.md for the full procedure. The process is:

  1. Create frontends/<lang>/<Lang>Frontend.h.
  2. Inherit BraceFrontendBase (or FrontendBase for line-based, or ILanguageFrontend for bespoke parsers like Python / Ruby).
  3. Optionally add frontends/<lang>/<Lang>StdLib.h.
  4. Register in MPL_Compiler.cpp:registerPlugins().
  5. Add to CMakeLists.txt.
  6. Add tests in tests/.
  7. Document in this docs/frontends/ directory.

Tracking limitations

Every limitation documented here should have a corresponding issue or test. To track progress:

cd MPL_Compiler/build
ctest -L known_issue --output-on-failure

Tests labelled known_issue are expected to fail until the corresponding limitation is addressed.