Fjoelnir
Fjölnir, Snorri Agnarsson's Icelandic-keyword language from the University of Iceland, where modules are substitutions combined with algebraic operators and memory is garbage-collected.
Created by Snorri Agnarsson, with Páll Björnsson and Jón Harðarson (University of Iceland)
Fjölnir (also written Fjolnir or Fjoelnir) is a programming language created by Snorri Agnarsson at the University of Iceland (Háskóli Íslands) in the second half of the 1980s. It is written entirely in Icelandic. Every keyword is an Icelandic word, and identifiers can use the whole Icelandic alphabet, so a function can be called hróp and a loop can be closed with lykkjulok. The Icelandic keywords are the first thing people notice, but the more interesting idea is underneath them. Fjölnir treats a module as a substitution, a mapping from names to definitions. Programs are built by combining these substitutions with a small set of algebraic operators. Ordinary procedural code sits inside a module system that was taken directly from Agnarsson’s doctoral research.
The language ran as a native-code compiler for MS-DOS. For years it was used mainly in Agnarsson’s own teaching at the University of Iceland, which is why the encyclopedia lists it under education.
History & Origins
From a thesis on packages
Agnarsson earned a B.S. in mathematics at the University of Iceland in 1978. He then went to Rensselaer Polytechnic Institute (RPI), where he received an M.S. in computer science in 1983 and a Ph.D. in 1985. His June 1985 dissertation was titled Packages as Substitutions. That same year he published two related papers on the same theory. One was “Towards a Theory of Packages”, with M. S. Krishnamoorthy, in the proceedings of the ACM SIGPLAN ‘85 symposium on language issues in programming environments (SIGPLAN Notices 20(7)). The other was “An algebraic theory of packages”, with Krishnamoorthy and B. David Saunders, at EUROCAL ‘85.
The theory represents programs as trees and packages as substitutions on those trees. It draws on Bruno Courcelle’s 1983 work on the mathematics of infinite trees. The afterword of the Fjölnir manual says that these ideas “were the guiding light” in designing the language. They were also invaluable for settling doubtful points in the design. The manual adds that users do not need to know the theory to write programs.
Building the compiler
Back in Iceland, Agnarsson built a compiler for the new language together with students. His 1997 university homepage describes the work this way: he had written, “in collaboration with various computer science students”, a compiler for a new programming language, Fjölnir, that offers both automatic garbage collection and powerful modular programming, and that compiler existed for MS-DOS. The tools name Jón Harðarson and Páll Björnsson as co-authors. Their banner reads:
Fjölnir Íslensk útgáfa 1.00 Raðnúmer 0000001
Copyright (c) 1986, 1987, 1988 Öll réttindi áskilin
Snorri Agnarsson, Jón Harðarson, Páll Björnsson
The copyright years suggest that work began around 1986 and that version 1.00 was finished by 1988. The oldest library and source files in the surviving distribution are dated August 1988. The 1989 year given in the encyclopedia table fits the first public coverage found so far: according to the timarit.is index, the Icelandic computing magazine Tölvumál ran an article on Fjölnir in its March 1989 issue. That article itself has not been read for this page. The compiler executable that survives in the distribution is dated June 1989.
The name is the Icelandic word Fjölnir, which is also a name of Odin in Norse myth and the title of a well-known nineteenth-century Icelandic journal. No source found here explains which of these Agnarsson had in mind.
Design Philosophy
The 1996 user manual opens by naming three ways in which Fjölnir differs from most other programming languages:
- Fjölnir is an Icelandic programming language.
- Fjölnir is a list-processing language.
- Fjölnir is a modular-programming language.
The manual says that the second and third points are what make Fjölnir powerful. It compares the list processing to LISP and Logo. It says the module system is very different from those of Modula-2, Ada and C++, and that it lets the programmer do more, and do it more simply.
Agnarsson’s homepage explains why the two go together. In his view, garbage collection is necessary for modular programming to become truly powerful. Without it, most of the work goes into specifying how memory is used and ensuring that it is handled correctly. Fjölnir therefore pairs a heap with automatic garbage collection with a module system meant for programming in the large.
Key Features
Modules as substitutions
A Fjölnir module is written in braces as a set of bindings from names to definitions. Compiling a file writes each named module to a separate .EIN file. This example from the manual defines a Fibonacci function:
| |
Here stef introduces a function, stofn ... stofnlok encloses its body, and ef ... þá ... annars ... eflok is if/then/else. This module exports f. The manual makes a key point about it: the f called inside the body is not automatically the same f. It is an imported name, and it is bound only when the programmer joins it to something. Recursion is therefore an explicit operation. The iteration operator ! ties a module’s imports to its own exports:
| |
The manual explains that recursion is not the default because the designers wanted every connection under the programmer’s control. Iteration is one of five module operations. The other four are binary operators. The manual gives their precedence, and they are listed here from highest to lowest:
| Operator | Icelandic name | Meaning |
|---|---|---|
! (unary) | ítrun | Iteration: binds a module’s imports to its own exports |
A * B | innflutningur | Import: binds A’s imports to B’s exports, and the result contains only A’s names |
A : B | samsetning | Composition: makes the same connections, and the result contains the names of both A and B |
A + B | hliðsetning | Juxtaposition: puts A and B side by side without connecting anything |
A & B | ítrunarhliðsetning | Iterated juxtaposition, defined as !(A + B): connects everything that can be connected |
The manual notes that & is the operator people coming from languages like C will find easiest. A main module & the base module GRUNNUR simply links everything together.
Generic code through renaming
Since a module is just a mapping from names to definitions, a renaming such as { + -> : } is a module too. This gives Fjölnir generic programming without type parameters. A 2002 course assignment defines insertleft and insertright, which are left and right folds over an imported +. It then derives list copy and list reverse from them by substitution:
| |
Here : is the pair constructor (cons). With + rebound to :, folding to the right rebuilds the list, which is a copy. Folding to the left with the arguments swapped builds it backwards, which is a reverse. The same INSERT module is linked twice with different bindings.
The bundled pascal.fjo example works the same way. It links a polynomial module, marglid, to the arbitrary-precision integer module, storfjol. The polynomial 1+X is then raised to successive powers with ordinary *, and each line it prints is a row of Pascal’s triangle.
Hello, World
The Hello World program shows how an executable program is put together. A module that exports main is joined to the standard base module GRUNNUR. The < operator names the entry point, and skrifastreng (“write string”) is imported from the base module:
| |
Expressions, values and parameters
- Everything is an expression. The manual says Fjölnir makes no distinction between statements and expressions, and every expression returns a value. Even loops return a value: always the empty value.
- One false value. The empty value
[]doubles as false, and every other value counts as true. This means the number0is true. - Values. The values are 16-bit natural numbers (0 to 65535) and signed integers (−32768 to 32767), floating-point numbers, characters (which are equivalent to their character codes), strings, and hlunkar. A hlunkur is a heap array of 1 to 1024 slots whose size is rounded up to a power of two. A two-slot hlunkur is a pair, and lists are built from pairs, with
haus(head),hali(tail) and:(cons). Run-time predicates such aserpar(“is pair”) anderhlunkur(“is hlunkur”) test the kind of a value. - Two kinds of parameters. A parameter list such as
stef(a;b)divides at the semicolon. Names before it are in-out parameters and names after it are input parameters. Calls follow the same pattern, as inskrifastreng(;"text"). - Calling with backslashes. A backslash lets a named function be called in prefix form, as in
\haus x, or used as an infix operator, as inx \hlunksækja 12. - Loops. There are three:
meðan ... lykkja ... lykkjulok(while), a C-stylefyrir(A;B;C) lykkja ... lykkjulok(for), and a barelykkja ... lykkjulok(infinite loop), whichútexits. - Hidden state. Modules can export global variables. Combined with module operations, this produces encapsulated state, such as the manual’s random-number module, which hides its seed variable
sæði.
Comments start with ;;. Keywords must be written in lower case, and the language is case-sensitive.
The toolchain
In the original Fjölnir, the compiler and linker are a single DOS program. FJÖLNIR x1 x2 compiles .FJO source files into .EIN module files and writes an .EXE. The .EIN files keep enough interface information for the linker to reject bad connections, such as binding a one-argument call to a two-argument function. Switches control quiet operation (E), tracing of module connections (T) and the run-time stack size (M0 to MF, from 4 KB to 64 KB). The FJLEIT environment variable sets the search path for modules. The utilities that came with it include Fjalla, which lists a module’s exports, imports and memory use, and Hvarer (“where is”), which finds the modules that export or import a given name.
The later Fjölnir 2 toolchain splits this work into a pipeline. The batch file in the distribution runs FJOLNIR2, then the assembler SMALI2, then the linker TENGIR2, which uses a separate module format (.EI2). The batch files also run GNU recode to convert source text from the Windows-1252 code page to the Icelandic DOS code page 861 before compiling. This is how the system kept its Icelandic letters working in later environments.
Evolution
Fjölnir changed in two main stages. The first-generation system, Icelandic edition 1.00, dates from 1988–89 and is what the manual documents. The surviving library comes in several variants of the base module (grunnur through grunnur6) and the core module (kjarni), with graphics drivers for CGA, EGA, VGA, MCGA and Hercules. The second generation, Fjölnir 2, has library modules dated from early 1991 and a compiler dated 1996. The manual itself is dated 25 February 1996.
The language’s dates for the 1990s and 2000s are hard to pin down. The surviving files show it was still maintained and taught well after its 1980s origins. Several example programs were re-saved in 1996–97, and many of the example executables in the course distribution are dated February 2002. There is no record of a formal release history beyond this.
Current Relevance
Fjölnir is a historical language. Wikipedia calls it a language “mostly used in the 1980s”, but the course materials show it was still being taught around 2002–2003. The university’s original download links are now dead. Copies of the DOS distribution and the manual survive in the Internet Archive, as does the fjolnirdev directory that holds the self-hosted compiler sources for both Fjölnir 1 and Fjölnir 2. The distribution is a 16-bit MS-DOS program. Running it today would need a DOS environment or emulator. That has not been tested for this page.
Agnarsson’s later language, Morpho, continued the central idea in a new form. Morpho is a multi-paradigm scripting language that runs on top of Java, and its documentation describes “a unique module system” in which “module operations support generic programming by viewing modules as substitutions”. Unlike Fjölnir, it does not use Icelandic keywords. The Icelandic Wikipedia describes it as building to some extent on the same ideas as Fjölnir.
Why It Matters
Fjölnir is notable on two counts.
- It is a non-English programming language that was actually used. Many languages with native-language keywords are translations of existing languages or small experiments. Fjölnir was a self-hosting compiler with a sizable standard library and graphics support, and it was used in university teaching. All of it was written in Icelandic, from keywords to library names to error messages.
- It turned a module-theory thesis into a working language. In the module systems the manual compares it with, such as Modula-2 and Ada, recursion and linking follow fixed rules. Fjölnir made them explicit algebraic operations that the programmer applies: iteration ties a module’s own knot, renaming produces generic code, and import and composition wire modules together. Its approach of generic programming by substitution, rather than by type parameters, is unusual, and Agnarsson carried it forward into Morpho.
Timeline
Notable Uses & Legacy
University of Iceland teaching
Agnarsson used Fjölnir in his programming-languages course at the University of Iceland. The 2002 and 2003 course pages include the manual, a DOS distribution, and assignments such as a module that uses substitution to derive list copy and reverse functions from generic left and right folds.
The Fjölnir compiler itself
The manual says the compiler, which also contains the linker, was written entirely in Fjölnir and assembly language. It offers this as evidence that the language could handle substantial projects. The self-hosted sources of both Fjölnir 1 and Fjölnir 2 were later published.
Standard library and example programs
The distribution includes dozens of library modules written in Fjölnir. They cover arbitrary-precision integers, polynomials, sorting, sets and queues, DOS file access, and graphics drivers for CGA, EGA, VGA, MCGA and Hercules displays. There are also example programs for factorials, Pascal's triangle, e to arbitrary precision and the Mandelbrot set.