OPAL
The Optimized Applicative Language from TU Berlin: a strict, purely functional language that merges algebraic specification with applicative programming, compiled to C by a compiler written in OPAL itself
Created by Peter Pepper and the Compiler Construction and Programming Languages group (Übersetzerbau und Programmiersprachen) at Technische Universität Berlin
OPAL (the OPtimized Applicative Language, usually written Opal) is a strict, purely functional programming language developed at Technische Universität Berlin by the Compiler Construction and Programming Languages group led by Peter Pepper. It combines two traditions: the higher-order, pattern-matching functional languages Hope and ML, and the algebraic specification languages such as CIP-L and OBJ. In Opal a program is a set of algebraic structures. Each one has a signature that declares sorts and functions and an implementation that defines them by equations. The group’s goal was to show that this style of program could be compiled into code fast enough for real work. Their compiler, written in Opal, translated Opal into C.
History and Origins
An algebraic language from Berlin
The project’s own README says the TU Berlin group developed Opal “from 1985 to 2000.” The licence of the Opal Compilation System (OCS) carries a copyright line of 1989-2000. The first dated definition of the language found for this page is Pepper’s The Programming Language OPAL, TU Berlin Technical Report No. 10-91, published in 1991 and revised into a third corrected edition in December 1992.
The encyclopedia’s master list gives Opal’s year as 1995. That is the year of OCS 2.1e, a well-publicized release, rather than the language’s first appearance, so this page uses 1991.
FOLDOC’s entry, last updated in February 1995, describes Opal as designed “as a testbed for the development of functional programs”. It integrates concepts from algebraic specification and functional programming to support the formal development of large, production-quality software written in a purely functional style. It describes the core as “a strongly typed, higher-order, strict applicative language which belongs to the tradition of Hope and ML,” and notes that “the algebraic flavour of OPAL is visible in the syntactical appearance and in the preference of parameterisation to polymorphism.”
Key people and publications
Many people built Opal and its tools over fifteen years. The ones who appear most often in its papers and source history are:
- Peter Pepper, head of the group and author of the language report.
- Wolfgang Grieskamp, who worked on the compiler’s code generation and later on Oasys and the release announcements.
- Wolfram Schulte, Grieskamp’s co-author on the 1992 code-generation paper.
- Klaus Didrich, author of the Bibliotheca Opalica standard library and the most frequent committer in 1998-2001.
- Christian Maeder, author of the 1993 OCS user’s guide.
The standard reference for the language is Didrich, Fett, Gerke, Grieskamp and Pepper, OPAL: Design and Implementation of an Algebraic Programming Language, published in 1994 in Springer’s Programming Languages and System Architectures (LNCS 782).
Design Philosophy
Opal’s designers were working against two views of functional programming that were common at the time:
- That functional programs are slow. The tutorial shipped with OCS says the project set out to disprove this. It claims that the compiler’s generated code runs in “the same magnitude” as hand-written C, and cites Schulte and Grieskamp’s 1992 paper for the measurements. These are the project’s own claims about its own benchmarks. The independent comparison is the Pseudoknot study described below.
- That functional programs do not scale. Opal puts as much weight on “programming in the large” as on expressions. Structures, information hiding, selective import and parameterized modules are part of the language from the start, as they are in algebraic specification languages.
The language is purely functional, with “no imperative relics” in the tutorial’s words. It uses strict (eager) evaluation, like ML and unlike Miranda or Haskell. Input/output and other effects are expressed as values of the type com[...] (commands), which are combined and then run by the runtime.
Key Features
Signatures and implementations
Every Opal structure comes in two files: a .sign file declaring what the structure exports and an .impl file defining it. The Hello World program in the OCS examples directory looks like this:
SIGNATURE HelloWorld
IMPORT Com[void] ONLY com
Void ONLY void
FUN hello : com[void] -- top level command
IMPLEMENTATION HelloWorld
IMPORT BasicIO ONLY writeLine: denotation -> com[void]
DEF hello == writeLine("Hello, World!")
Imports are explicit. ONLY names exactly what is imported, and COMPLETELY imports everything. The string type is called denotation.
Free types (algebraic data types)
Data types are declared as sums of constructors, optionally with named selectors, much like Hope or ML datatypes. This is from the OCS Integrator example:
TYPE expr == binop(op: operator, left: expr, right: expr)
unop (op: operator, arg: expr)
number(theNumber: real)
pi
varx vary
error(msg: denotation)
TYPE operator == add sub mul div pow
sin cos exp log abs neg sqrt
A TYPE declaration also generates constructor functions, discriminators and selector functions, so definitions can use pattern matching or field selection.
Guarded equations
Functions are defined by DEF equations. Conditionals use guarded IF ... THEN branches closed by FI. When several guards hold at once, the tutorial calls the choice a non-deterministic case distinction, and an optional ELSE covers the remaining cases. This is from the Rabbits example:
FUN ordinal: nat -> denotation
DEF ordinal(n) ==
IF n % 10 = 1 THEN "st"
IF n % 10 = 2 THEN "nd"
IF n % 10 = 3 THEN "rd"
ELSE "th"
FI
FUN rabbits : nat -> nat
DEF rabbits(generation) ==
IF generation = 0 THEN 1
IF generation = 1 THEN 1
IF generation > 1 THEN rabbits(generation - 1)
+ rabbits(generation - 2)
FI
Commands and lambda
Effects are composed with combinators such as &, and anonymous functions are written with \\ x .:
DEF main ==
ask("For which generation do you " ++
"want to know the number of rabbits? ") & (\\ generation.
writeLine(result(generation, rabbits(generation)))
)
Overloading and parameterization instead of polymorphism
Opal allows full overloading of names. The same identifier can name several functions, told apart by type, and an annotation syntax such as +'Rational selects one explicitly. Generic code is written as parameterized structures (for example Com[void]), which are instantiated on import, rather than through ML-style implicit polymorphism. Operator precedence is not built into the grammar. Libraries declare how operators associate and bracket using pragmas, as the Rational example does:
/$ BRACKET LEFT [*'Rational,/ : rat ** rat -> rat]
[+'Rational,-'Rational] $/
Compilation to C
The OCS compiler translates Opal into C, which a C compiler then turns into native code. The Pseudoknot benchmark study confirms this. It lists Opal with FCMC and Stoffel as the languages in its set that compile via C. It also names Opal, with Chalmers Haskell and Glasgow Haskell, as compilers that can inline functions across module boundaries.
The Opal Compilation System
OCS was the only implementation of Opal. Over time it grew a set of tools around the compiler:
| Component | What it does |
|---|---|
ocs | Batch compiler and build tool |
| Bibliotheca Opalica | The standard library of reusable structures (Klaus Didrich) |
oasys | From version 2.3a, an interactive alternative to ocs with an interpreter-debugger that evaluates expressions on the fly and monitors function execution. It was developed by Wolfgang Grieskamp and Eckard Lehmann, and Lehmann wrote the interpreter-debugger for his master’s thesis |
| Reactive agents | Added in 2.1e: agents that run monadic commands concurrently and synchronize through service-access-points in a client/server style |
| TkOpal | Added in 2.1e: a GUI library over Tcl/Tk that uses agent communication instead of callbacks, with Tcl interpreters as first-class values |
| DOSFOP | Added in 2.1e: a literate-programming system that generates Texinfo (and from it DVI, Info or HTML) from Opal sources |
The later distribution also includes examples of dynamic linking (storing and reloading a function), reflection, and integrating the Java VM into Opal programs.
The Pseudoknot benchmark
The best independent look at OCS is Pieter Hartel and colleagues’ 1996 Journal of Functional Programming study, Benchmarking Implementations of Functional Languages with “Pseudoknot”, a Float-Intensive Benchmark. It compiled one floating-point-heavy program from molecular biology with more than 25 functional-language implementations. Its findings about Opal were:
- The Opal version was translated by hand from the Haskell and SML versions. Like RUFL, Opal required explicit type signatures on all top-level functions.
- Some compilers that generate C, including Opal and FAST, produced C procedures so large that some C compilers struggled with them. As a result, the study reports, “the Opal compiler has been modified to cope better with extremely large functions.”
- According to the study’s measurements, switching from double- to single-precision floating point made the Opal-compiled program about twice as fast. The same switch gained only 12% for the GNU C version of Pseudoknot and 16% for the Trafola interpreter.
The authors stress that a single program cannot represent “typical” applications. The study’s timing tables should be read with that warning in mind, not as a general ranking.
Evolution
- Opal (1991 report onward): the language described in Pepper’s technical report and the 1994 LNCS paper, implemented by OCS 2.x.
- OCS 2.1e (1995): added agents, TkOpal, DOSFOP and autoconf-based configuration.
- Opal 2α (1997-98): Didrich, Grieskamp, Maeder and Pepper’s Programming in the Large: The Algebraic-Functional Language Opal 2α, from the IFL ‘97 workshop and published in LNCS 1467, describes a successor design focused on more flexible modularization for large programs.
- OCS 2.3 series: introduced
oasys, with bug-fix releases running up to 2.3m. The repository history shows work from 1998 to 2001 by Didrich, Maeder and Grieskamp. - Maintenance revival (2010-2013): after nearly a decade without commits, Florian Lorenzen and colleagues modernized the autoconf build and merged outstanding fixes. They tagged 2.3n (October 2010), 2.4 (October 2011), 2.4a (October 2012) and 2.4b (October 2013).
- End of maintenance: a README added in January 2016 states that maintenance “has been discontinued in 2015.” The GitHub repository has since been archived, and a notice points to a copy on TU Berlin’s GitLab.
Current Relevance
Opal is a historical research language. No new releases have appeared since OCS 2.4b in 2013, the project’s original web pages at TU Berlin are offline, and no Docker image or distribution package is maintained. The full source, including the compiler, libraries, Oasys, DOSFOP and the manuals and tutorial in LaTeX and Texinfo, is still available from the archived TU-Berlin/opal repository. This page makes no claim that it still builds on current systems.
Opal should not be confused with other systems of the same name. These include the language of the GemStone object database, a 1960s simulation language, and the unrelated, more recent Opal static-analysis framework.
Why It Matters
Opal is one of the clearest attempts to bring the algebraic specification tradition, in which programs are sorts, operations and equations organized into parameterized structures, into a practical, compiled functional programming language. It answered the scaling question with modules and the speed question with an optimizing compiler to C, and it was tested independently in the Pseudoknot cross-implementation benchmark. Its compiler was written in the language itself, which showed that a purely functional, strictly evaluated language with heavy overloading and parameterized modules could support a large system. It was also used in teaching at TU Berlin, and Pepper’s textbook presents it alongside ML, Haskell and Gofer.
Timeline
Notable Uses & Legacy
The Opal compiler itself
The OCS compiler is written entirely in Opal and translates Opal into C, so the project's largest program was also its main test of the language for large-scale software
Computer science teaching at TU Berlin
FOLDOC's 1995 entry records Opal being used in TU Berlin CS courses. Pepper's textbook "Funktionale Programmierung in OPAL, ML, HASKELL und GOFER" uses it alongside ML, Haskell and Gofer to teach functional programming
Research on optimizing compilers for applicative languages
FOLDOC also records Opal as a vehicle for research into optimizing compilers. The Pseudoknot study names it among the compilers able to inline functions across module boundaries
Pseudoknot functional-language benchmark
Opal was one of the implementations in Hartel et al.'s 1996 cross-language comparison, which used a float-intensive molecular-biology program; the study reports that the Opal compiler was modified as a result, to cope better with very large functions
TkOpal and DOSFOP
Tools built in and for Opal and shipped with OCS 2.1e: a Tcl/Tk GUI library driven by communicating agents rather than callbacks, and a literate-programming system that turns Opal sources into Texinfo documentation