Est. 1991 Advanced

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

Paradigm Functional (strict, purely functional, algebraic)
Typing Static, Strong
First Appeared 1991
Latest Version OCS 2.4b (October 2013)

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:

  1. 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.
  2. 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:

ComponentWhat it does
ocsBatch compiler and build tool
Bibliotheca OpalicaThe standard library of reusable structures (Klaus Didrich)
oasysFrom 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 agentsAdded in 2.1e: agents that run monadic commands concurrently and synchronize through service-access-points in a client/server style
TkOpalAdded in 2.1e: a GUI library over Tcl/Tk that uses agent communication instead of callbacks, with Tcl interpreters as first-class values
DOSFOPAdded 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

1985
Peter Pepper's group at TU Berlin begins the work that becomes Opal, according to the project's own README ("developed ... from 1985 to 2000")
1991
Pepper publishes "The Programming Language OPAL" as TU Berlin Technical Report No. 10-91; a third corrected edition follows in December 1992
1992
Wolfram Schulte and Wolfgang Grieskamp describe the compiler's back end in "Generating Efficient Portable Code for a Strict Applicative Language", published by Springer in the Phoenix Seminar and Workshop on Declarative Programming proceedings
1994
Didrich, Fett, Gerke, Grieskamp and Pepper publish "OPAL: Design and Implementation of an Algebraic Programming Language" in Programming Languages and System Architectures (LNCS 782, pp. 228-244)
1995
OCS 2.1e is released on 1 July, with patch level 1 announced on comp.compilers on 1 August. It adds concurrent reactive agents, the Tcl/Tk-based TkOpal GUI library, the DOSFOP literate-programming system and GNU autoconf configuration
1996
Opal is one of more than 25 functional-language implementations compared in Hartel et al., "Benchmarking Implementations of Functional Languages with 'Pseudoknot'" (Journal of Functional Programming 6(4))
1998
Didrich, Grieskamp, Maeder and Pepper's "Programming in the Large: The Algebraic-Functional Language Opal 2α", from the IFL '97 workshop, appears in LNCS 1467. The OCS source tree is imported into CVS the same year (16 June)
1999
Springer publishes Pepper's German textbook "Funktionale Programmierung in OPAL, ML, HASKELL und GOFER"; a second edition followed
2010
Florian Lorenzen revives maintenance, merges the 2.3h-2.3m bug fixes and tags OCS 2.3n (October 2010)
2013
OCS 2.4b, the last tagged release, is published on 10 October 2013. The README later records that maintenance was discontinued in 2015

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

Language Influence

Influenced By

Hope ML CIP-L OBJ

Running Today

Run examples using the official Docker image:

docker pull
Last updated: