XL Programming Language
Encyclopedia
XL stands for eXtensible Language. It is a computer
programming language
designed to support concept programming
.
XL features programmer-reconfigurable syntax and semantics. Compiler plug-ins can be used to add new features to the language. A base set of plug-ins implements a relatively standard imperative language
. Programmers can write their own plug-ins to implement application-specific notations, such as symbolic differentiation
, which can then be used similarly to built-in language features.
XL has no primitive types nor keywords. All useful operators and data types, like integers or addition, are defined in the standard library (XL2). XL1 is portable
between different execution environments. There is no such guarantee for XL2: if a particular CPU
does not implement floating-point multiplication, the corresponding operator definition may be missing from the standard library, and using a floating-point multiply may result in a compile-time error.
The Hello World program in XL looks like the following:
use XL.TEXT_IO
WriteLn "Hello World"
An alternative form in a style more suitable for large-scale programs would be:
import IO = XL.TEXT_IO
IO.WriteLn "Hello World"
A recursive implementation of factorial
in XLR looks like the following:
0! -> 1
N! -> N * (N-1)!
.
The parse tree consists of 7 node types, 4 leaf node types (integer, real, text and symbol) and 3 internal node types (infix, prefix and block).
With the default syntax file, the following is valid XL0, irrespective of any semantics.
A = B + "Hello"
It parses as:
infix("=",
symbol("A"),
infix("+",
symbol("B"), text("Hello")))
Special constructs,
translation ZeroRemoval
when
'X' + 0
then
return X
when
'X' * 0
then
return parse_tree(0)
A plug-in can be invoked on a whole file from the command line, or more locally in the source code using the pragma notation, as follows:
X := {Differentiate} d(sin(omega * T) * exp(-T/T0)) / dT
The XL1 phase contains a large set of plug-ins, notably
, data type
and variable
declaration
and definition
, as well as basic structured programming
statements, like conditionals or loops.
, with generic programming
abilities that are beyond those of languages like Ada or C++. Types like arrays or pointers, which are primitive in languages like C++, are declared in the library in XL. For instance, a one-dimensional array type could be defined as follows:
generic [Item : type; Size : integer] type array
A validated generic type is a generic type where a condition indicates how the type can be used. Such types need not have generic parameters. For instance, one can declare that a type is
// A type is ordered if it has a less-than relationship
generic type ordered if
A, B : ordered
Test : boolean := A < B
It is then possible to declare a function that is implicitly generic because the type
// Generic function for the minimum of one item
function Min(X : ordered) return ordered is
return X
This also applies to generic types that have parameters, such as
function Sum(A : array) return array.Item is
for I in 0..array.Size-1 loop
result += A[I]
:
// Generic function for the minimum of N item
function Min(X : ordered; ...) return ordered is
result := Min(...)
if X < result then
result := X
When such a function is called, the compiler recursively instantiates functions to match the parameter list:
// Examples of use of the Min just declared
X : real := Min(1.3, 2.56, 7.21)
Y : integer := Min(1, 3, 6, 7, 1, 2)
function Add(X, Y: integer) return integer written X+Y
Such written forms can have more than two parameters. For instance, a matrix linear transform can be written as:
function Linear(A, B, C : matrix) return matrix written A+B*C
A written form can use constants, and such a form is more specialized than a form without constants. For example:
function Equal(A, B : matrix) return boolean written A=B
function IsNull(A : matrix) return boolean written A=0
function IsUnity(A : matrix) return boolean written A=1
The mechanism is used to implement all basic operators. An expression is progressively reduced to function calls using written forms. For that reason, the mechanism is referred to as expression reduction rather than operator overloading.
and iterators.
Historically, the XL compiler was written in C++. It had achieved a point where most of the features described above worked correctly, but writing plug-ins was a nightmare, because C++ itself is not extensible, so implementing
Abandoning the cross-language objectives and complex parse-tree structure, a complete rewrite
of the compiler was started in 2003. The parse tree was vastly simplified down to the 7 XL0 nodes types now in use. This new compiler bootstrapped
in 2004, and all new development is now written in XL. However, this new compiler still has somewhat incomplete XL1 support, although its abilities already exceed C++ in a few areas.
This mechanism is used to implement standard notations:
if true then TrueBody else FalseBody -> TrueBody
if false then TrueBody else FalseBody -> FalseBody
Computer
A computer is a programmable machine designed to sequentially and automatically carry out a sequence of arithmetic or logical operations. The particular sequence of operations can be changed readily, allowing the computer to solve more than one kind of problem...
programming language
Programming language
A programming language is an artificial language designed to communicate instructions to a machine, particularly a computer. Programming languages can be used to create programs that control the behavior of a machine and/or to express algorithms precisely....
designed to support concept programming
Concept programming
Concept programming is a programming paradigm focusing on how concepts, that live in the programmer's head, translate into representations that are found in the code space. This approach was introduced in 2001 by Christophe de Dinechin with the XL Programming Language.- Pseudo-metrics :Concept...
.
XL features programmer-reconfigurable syntax and semantics. Compiler plug-ins can be used to add new features to the language. A base set of plug-ins implements a relatively standard imperative language
Imperative programming
In computer science, imperative programming is a programming paradigm that describes computation in terms of statements that change a program state...
. Programmers can write their own plug-ins to implement application-specific notations, such as symbolic differentiation
Derivative
In calculus, a branch of mathematics, the derivative is a measure of how a function changes as its input changes. Loosely speaking, a derivative can be thought of as how much one quantity is changing in response to changes in some other quantity; for example, the derivative of the position of a...
, which can then be used similarly to built-in language features.
Language
XL is defined at four different levels:- XL0 defines how an input text is transformed into a parse treeParse treeA concrete syntax tree or parse tree or parsing treeis an ordered, rooted tree that represents the syntactic structure of a string according to some formal grammar. In a parse tree, the interior nodes are labeled by non-terminals of the grammar, while the leaf nodes are labeled by terminals of the...
. - XL1 defines a base language with features comparable to C++C++C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
- XL2 defines the standard library, which includes common data types and operators.
- XLR defines a dynamic runtime for XL based on XL0
XL has no primitive types nor keywords. All useful operators and data types, like integers or addition, are defined in the standard library (XL2). XL1 is portable
Porting
In computer science, porting is the process of adapting software so that an executable program can be created for a computing environment that is different from the one for which it was originally designed...
between different execution environments. There is no such guarantee for XL2: if a particular CPU
Central processing unit
The central processing unit is the portion of a computer system that carries out the instructions of a computer program, to perform the basic arithmetical, logical, and input/output operations of the system. The CPU plays a role somewhat analogous to the brain in the computer. The term has been in...
does not implement floating-point multiplication, the corresponding operator definition may be missing from the standard library, and using a floating-point multiply may result in a compile-time error.
The Hello World program in XL looks like the following:
use XL.TEXT_IO
WriteLn "Hello World"
An alternative form in a style more suitable for large-scale programs would be:
import IO = XL.TEXT_IO
IO.WriteLn "Hello World"
A recursive implementation of factorial
Factorial
In mathematics, the factorial of a non-negative integer n, denoted by n!, is the product of all positive integers less than or equal to n...
in XLR looks like the following:
0! -> 1
N! -> N * (N-1)!
Syntax
Syntax is defined at the XL0 level. The XL0 phase of the compiler can be configured using a syntax description file, where properties like the text representation and precedence of operators are defined. A basic syntax file defines common mathematical notations, like + for addition, with the usually accepted order of operationsOrder of operations
In mathematics and computer programming, the order of operations is a rule used to clarify unambiguously which procedures should be performed first in a given mathematical expression....
.
The parse tree consists of 7 node types, 4 leaf node types (integer, real, text and symbol) and 3 internal node types (infix, prefix and block).
- integer nodes represent an integer literal, such as
2
. The#
sign can be used to specify a base other than 10, as in (2#1001
). A separating underscore can be used to improve readability, as in1_000_000
. - real nodes represent non-integral numbers, such as
2.5
. Based-notations and separators can be used, as for integer nodes, for example16#F.FFF#E-10
is a valid real literal. - text nodes represent textual contents. They are normally surrounded by simple or double quotes, like
"Hello"
or'a'
, but the syntax file can be used to add other separators, including for multi-line textual contents. - symbol nodes represent names or operators. Names are sequence of alphanumeric characters beginning with a letter, like
Hello
. XL0 preserves case, but XL1 ignores case and underscores, so thatJohnDoe
andjohn_doe
are the same name. Symbols are sequence of non-alphanumeric characters, like*
or=/=
. - infix nodes represent two nodes related by an infix symbol, like
A+1
or2 and 3
. Infix nodes are in particular used to separate lines, with an infix "new-line" symbol. - prefix nodes represent two consecutive nodes, like
Write "Hello"
. It is also used for postfix notations, like3!
orOpen?
. - block nodes represent a node surrounded by grouping symbols, like
(A)
,[Index]
. Indentation is internally represented by a block node.
With the default syntax file, the following is valid XL0, irrespective of any semantics.
A = B + "Hello"
It parses as:
infix("=",
symbol("A"),
infix("+",
symbol("B"), text("Hello")))
Semantics of XL1
The XL1 phase is defined as a sequence of operations on the XL0 parse tree. These operations are provided by various compiler plug-ins, that are triggered based on the shape of the parse tree.Special constructs,
translate
and translation
, are provided by a plug-in designed to facilitate the writing of other plug-ins. The quote
construct generates a parse tree. Here is how these notations can be used to implement a plug-in called ZeroRemoval
that eliminates superfluous additions and multiplications by zero.translation ZeroRemoval
when
'X' + 0
then
return X
when
'X' * 0
then
return parse_tree(0)
A plug-in can be invoked on a whole file from the command line, or more locally in the source code using the pragma notation, as follows:
X := {Differentiate} d(sin(omega * T) * exp(-T/T0)) / dT
The XL1 phase contains a large set of plug-ins, notably
XLSemantics
, that provide common abstractions like subroutineSubroutine
In computer science, a subroutine is a portion of code within a larger program that performs a specific task and is relatively independent of the remaining code....
, data type
Data type
In computer programming, a data type is a classification identifying one of various types of data, such as floating-point, integer, or Boolean, that determines the possible values for that type; the operations that can be done on values of that type; the meaning of the data; and the way values of...
and variable
Variable (programming)
In computer programming, a variable is a symbolic name given to some known or unknown quantity or information, for the purpose of allowing the name to be used independently of the information it represents...
declaration
Declaration (computer science)
In programming languages, a declaration specifies the identifier, type, and other aspects of language elements such as variables and functions. It is used to announce the existence of the element to the compiler; this is important in many strongly-typed languages that require variables and their...
and definition
Definition
A definition is a passage that explains the meaning of a term , or a type of thing. The term to be defined is the definiendum. A term may have many different senses or meanings...
, as well as basic structured programming
Structured programming
Structured programming is a programming paradigm aimed on improving the clarity, quality, and development time of a computer program by making extensive use of subroutines, block structures and for and while loops - in contrast to using simple tests and jumps such as the goto statement which could...
statements, like conditionals or loops.
Type system
XL1 type checking is staticData type
In computer programming, a data type is a classification identifying one of various types of data, such as floating-point, integer, or Boolean, that determines the possible values for that type; the operations that can be done on values of that type; the meaning of the data; and the way values of...
, with generic programming
Generic programming
In a broad definition, generic programming is a style of computer programming in which algorithms are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters...
abilities that are beyond those of languages like Ada or C++. Types like arrays or pointers, which are primitive in languages like C++, are declared in the library in XL. For instance, a one-dimensional array type could be defined as follows:
generic [Item : type; Size : integer] type array
A validated generic type is a generic type where a condition indicates how the type can be used. Such types need not have generic parameters. For instance, one can declare that a type is
ordered
if it has a less-than operator as follows:// A type is ordered if it has a less-than relationship
generic type ordered if
A, B : ordered
Test : boolean := A < B
It is then possible to declare a function that is implicitly generic because the type
ordered
itself is generic.// Generic function for the minimum of one item
function Min(X : ordered) return ordered is
return X
This also applies to generic types that have parameters, such as
array
. A function computing the sum of the elements in any array can be written as follows:function Sum(A : array) return array.Item is
for I in 0..array.Size-1 loop
result += A[I]
Type-safe variable argument lists
Functions can be overloaded. A function can be declared to use a variable number of arguments by using...
in the parameter list (historically, the keyword other
was used for that purpose). In such a function, ...
can be used to pass the variable number of arguments to another subroutine, a feature now called Variadic templatesVariadic Templates
In computer programming, variadic templates are templates that take a variable number of arguments.Variadic templates are supported by the D programming language, and the newest version of C++, formalized in the C++11 standard.-C++11:...
:
// Generic function for the minimum of N item
function Min(X : ordered; ...) return ordered is
result := Min(...)
if X < result then
result := X
When such a function is called, the compiler recursively instantiates functions to match the parameter list:
// Examples of use of the Min just declared
X : real := Min(1.3, 2.56, 7.21)
Y : integer := Min(1, 3, 6, 7, 1, 2)
Expression reduction: operator overloading
Operators can be defined using thewritten
form of function declarations. Below is the code that would declare the addition of integers:function Add(X, Y: integer) return integer written X+Y
Such written forms can have more than two parameters. For instance, a matrix linear transform can be written as:
function Linear(A, B, C : matrix) return matrix written A+B*C
A written form can use constants, and such a form is more specialized than a form without constants. For example:
function Equal(A, B : matrix) return boolean written A=B
function IsNull(A : matrix) return boolean written A=0
function IsUnity(A : matrix) return boolean written A=1
The mechanism is used to implement all basic operators. An expression is progressively reduced to function calls using written forms. For that reason, the mechanism is referred to as expression reduction rather than operator overloading.
Iterators
XL iterators allow programmers to implement both generatorsGenerator (computer science)
In computer science, a generator is a special routine that can be used to control the iteration behaviour of a loop. A generator is very similar to a function that returns an array, in that a generator has parameters, can be called, and generates a sequence of values...
and iterators.
Development status and history
XL is the result of a long language design work that began around 1992. The language was designed and implemented primarily by Christophe de Dinechin.Historically, the XL compiler was written in C++. It had achieved a point where most of the features described above worked correctly, but writing plug-ins was a nightmare, because C++ itself is not extensible, so implementing
translate
-like statements was impossible. The parse tree was more complicated, with dozens of node types, because it was designed for cross-language support. Moka was a Java-to-Java extensible compiler using the same infrastructure.Abandoning the cross-language objectives and complex parse-tree structure, a complete rewrite
Rewrite (programming)
A rewrite in computer programming is the act or result of re-implementing a large portion of existing functionality without re-use of its source code. When the rewrite is not using existing code at all, it is common to speak of a rewrite from scratch...
of the compiler was started in 2003. The parse tree was vastly simplified down to the 7 XL0 nodes types now in use. This new compiler bootstrapped
Bootstrapping (compilers)
In computer science, bootstrapping is the process of writing a compiler in the target programming language which it is intended to compile...
in 2004, and all new development is now written in XL. However, this new compiler still has somewhat incomplete XL1 support, although its abilities already exceed C++ in a few areas.
Ancestry
XL1 was inspired by a large number of other languages. In alphabetical order:- AdaAda (programming language)Ada is a structured, statically typed, imperative, wide-spectrum, and object-oriented high-level computer programming language, extended from Pascal and other languages...
inspired some of large-scale program support, exception handling, tasking, and supportability aspects. - BASICBASICBASIC is a family of general-purpose, high-level programming languages whose design philosophy emphasizes ease of use - the name is an acronym from Beginner's All-purpose Symbolic Instruction Code....
, notably in the more modern variants that dispense of line numbers and support structured programming, showed how simple the syntax of a programming language could be. - CC (programming language)C is a general-purpose computer programming language developed between 1969 and 1973 by Dennis Ritchie at the Bell Telephone Laboratories for use with the Unix operating system....
was used as the standard to expect in terms of runtime and machine-level support. XL will not require a virtual machine to run. - C++C++C++ is a statically typed, free-form, multi-paradigm, compiled, general-purpose programming language. It is regarded as an intermediate-level language, as it comprises a combination of both high-level and low-level language features. It was developed by Bjarne Stroustrup starting in 1979 at Bell...
and the standard template libraryStandard Template LibraryThe Standard Template Library is a C++ software library which later evolved into the C++ Standard Library. It provides four components called algorithms, containers, functors, and iterators. More specifically, the C++ Standard Library is based on the STL published by SGI. Both include some...
demonstrated the need for good support of generic types, including implicit instantiation of generics (which Ada lacks). - FortranFortranFortran is a general-purpose, procedural, imperative programming language that is especially suited to numeric computation and scientific computing...
's continued performance lead over C and C++ for numerical-intensive applications helped identify which language constructs would prevent useful optimizations. - JavaJava (programming language)Java is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language derives much of its syntax from C and C++ but has a simpler object model and fewer low-level facilities...
demonstrated the importance of a large, portable support library. Java containers also showed the limitations of an approach not based on generic programming. Interfacing with Java code remains an interesting challenge for XL. - Lisp extensibility was considered as a key factor in its survival and relevance to this day. Lisp was the first language to normalize object-oriented features, despite having been designed years before object-oriented ideas were invented.
- PrologPrologProlog is a general purpose logic programming language associated with artificial intelligence and computational linguistics.Prolog has its roots in first-order logic, a formal logic, and unlike many other programming languages, Prolog is declarative: the program logic is expressed in terms of...
demonstrated that alternative programming models are sometimes useful and highly productive. Every effort was made to ensure that a Prolog-style plug-in could be written for XL. - Visual BasicVisual BasicVisual Basic is the third-generation event-driven programming language and integrated development environment from Microsoft for its COM programming model...
showed how the parse tree representation can be dissociated from its visual presentation. Few people edit VB Forms textually. It is expected that XL edit-time plug-ins will one day provide similar abilities, by directly manipulating the parse tree.
Semantics
XLR is a dynamic language, originally intended as a back-end for the XL1 compiler, hence the name, which stands for XL runtime. It shares the basic XL0 syntax with XL1, but its behavior is much closer to a functional language, whereas XL1 is intended to look mostly like an imperative language. XLR has practically only one built-in operator, "->", which denotes a rewrite. The notation on the left of the rewrite is transformed into the notation on the right of the rewrite.This mechanism is used to implement standard notations:
if true then TrueBody else FalseBody -> TrueBody
if false then TrueBody else FalseBody -> FalseBody