Long before React's hooks and Rust's pattern matching reshaped development, Andreas Schjelderup's work on the BETA compiler laid the groundwork for component‑based architectures with a single unifying abstraction. This article unpacks the technical legacy of a researcher whose optimizations for a little‑known object‑oriented language quietly echo through modern type systems, reactive UI frameworks. And domain‑specific language tooling.

Most developers have never typed a line of BETA. The language, born from the Scandinavian school that gave us Simula, never achieved mainstream adoption. Yet inside its reference implementation, built by a team including Andreas Schjelderup, sits an abstraction so radical that it collapses classes, methods, processes. And coroutines into one construct: the virtual pattern. In production compiler work today-whether we're instrumenting LLVM pipelines or tuning the TypeScript type checker-the problems Schjelderup solved in the early 1990s keep resurfacing. His contributions to compile‑time introspection, dynamic dispatch optimization. And the unification of type and behavior hierarchies offer a surprisingly fresh lens for evaluating the architectures we now take for granted.

I spent part of my early career maintaining a statically‑typed rules engine that had to reconcile hundreds of domain‑specific subtypes. The moment I stumbled on the BETA virtual pattern, I recognized the same tension we face every day: how do you give domain experts a single, expressive construct without drowning the runtime in virtual‑call overhead? Schjelderup didn't just theorize about this; he shipped a production‑grade compiler that statically resolved a large fraction of what looked like unbounded polymorphism. That compiler, part of the Mjølner system, is a masterpiece of attribute‑grammar‑driven code generation that deserves a second look from anyone wrestling with monomorphization, trait solver performance or DSL design,

Abstract visualization of stacked code blocks representing compiler transformation stages

The Genesis of Unified Abstractions in BETA

To understand why Andreas Schjelderup's compiler work was so forward‑looking, you have to grasp the language he was targeting. BETA, designed by Ole Lehrmann Madsen, Birger Møller‑Pedersen, and Kristen Nygaard, replaced the class‑centric model of Simula with the pattern-a single syntactic and semantic unit that could play the role of a class, a procedure, a function, a coroutine. Or an exception handler. The BETA language specification Object‑Oriented Programming in the BETA Programming Language defines a pattern as having an optional input (a set of enterable item declarations), an action part, and an optional output. Virtual patterns, analogous to virtual methods in C++ but far more general, allowed sub‑patterns to refine the action part while inheriting the input/output structure.

For a compiler engineer, this uniformity sounded like a boon-only one kind of node in the AST-but it actually made code generation harder. A pattern invocation couldn't be treated as a simple function call; it might allocate an activation record, wait for a coroutine resume or participate in an inheritance chain that extended across multiple files discovered at link time. Schjelderup's insight was to treat the entire program as a graph of pattern specializations, applying attribute grammars to propagate context information and enable early binding wherever possible. This approach, documented in his PhD dissertation and the Mjølner project reports, allowed the compiler to monomorphize many virtual patterns at compile time, long before Rust popularized the term.

How Virtual Patterns Redefine Polymorphism

A contemporary engineer might ask: why not just use a virtual method table (vtable) and be done with it? The limitation of a vtable is that it only dispatches on the receiver's runtime type for a fixed set of method signatures. In BETA, a virtual pattern can describe anything from a simple mathematical operation to a concurrent behavior that suspends in the middle of execution. Consider a pattern Calculator that takes an int as input, performs an action. And produces an int output. A sub‑pattern AddFive simply adds five. Another sub‑pattern might spin up a worker thread and return a future. The compiler must generate code that handles both cases without knowing which will be plugged in at run time.

Schjelderup's solution was to extend the concept of a pattern descriptor-a runtime object analogous to a vtable but significantly richer. The descriptor carried not only the conventional jump table but also metadata about stack frame layout, co‑routine state. And compile‑time constant folding opportunities. When the compiler could prove that a particular pattern invocation site would always see a concrete sub‑pattern, it would specialize the call inline, eliminating the descriptor overhead entirely. This is precisely the kind of devirtualization that LLVM's speculative devirtualization pass performs today for C++ and Swift. In production environments, I've seen similar transformations using LLVM alias analysis to disambiguate indirect calls. And the conceptual roots trace directly back to those BETA optimization papers.

Diagram of a pattern descriptor linking to various specialized code paths

Andreas Schjelderup's Compiler Optimization Techniques

The Mjølner BETA compiler, in which Andreas Schjelderup played a Central role, is built on a framework that generates compilers from formal descriptions-a technique known as compiler generation. The front end uses an attribute grammar to specify context‑sensitive analysis; the back end employs tree‑rewriting rules to map the attributed AST into frame‑based bytecode for the Mjølner virtual machine. One of Schjelderup's key contributions was a pattern call graph analysis that tracks which virtual pattern closures escape into the heap and which remain stack‑constrained. For stack‑constrained patterns, the compiler can inline the action part directly and even flatten nested patterns into a single procedure, akin to Rust's #inline with monomorphization.

What made this analysis non‑trivial was BETA's support for virtual classes-nested patterns that are themselves overridable. When an outer pattern C contains an inner virtual pattern D, different sub‑patterns of C may provide different implementations of D. Schjelderup recognized that this is structurally equivalent to family polymorphism, a concept later formalized by Erik Ernst. The compiler generated "family descriptors" that bundled the vtable‑like structures for an entire cluster of related patterns, reducing the indirection cost

.

Need a Custom App Built?

Let's discuss your project and bring your ideas to life.

Contact Me Today →

Back to Online Trends