Domain-Specific Languages in Ada SPARK
Method Chaining
The advantage of method chaining in Ada is that it can be implemented using only tagged records. No access types or other means of indirection are needed. It passes SPARK’s gnatprove even without annotations. No Ada2022 is necessary.
The disadvantage of method chaining is that it depends on tagged types which might be unavailable, e.g., in systems lacking a secondary stack.
with Computers; use Computers;
procedure Main
with
SPARK_Mode => On
is
begin
Computer
.Processor
.Cores (2)
.Speed (2500)
.I386
.Disk
.Size (150)
.Disk
.Size (75)
.Speed (7200)
.Sata
.Done;
end Main;
package Computers
with
SPARK_Mode => On
is
type Computer_Context is tagged private;
function Null_Computer_Context
return Computer_Context;
type Processor_Context is tagged private;
function Null_Processor_Context
return Processor_Context;
type Disk_Context is tagged private;
function Null_Disk_Context
return Disk_Context;
------------------------------------------------------------
procedure Done
(CC : Computer_Context);
procedure Done
(PC : Processor_Context);
procedure Done
(DC : Disk_Context);
function Processor
(CC : Computer_Context'Class)
return Processor_Context;
function Processor
(PC : Processor_Context'Class)
return Processor_Context;
function Processor
(DC : Disk_Context'Class)
return Processor_Context;
function Disk
(CC : Computer_Context'Class)
return Disk_Context;
function Disk
(PC : Processor_Context'Class)
return Disk_Context;
function Disk
(DC : Disk_Context'Class)
return Disk_Context;
------------------------------------------------------------
function Cores
(PC : Processor_Context;
N : Positive)
return Processor_Context;
function Speed
(PC : Processor_Context;
N : Natural)
return Processor_Context;
function Speed
(DC : Disk_Context;
N : Natural)
return Disk_Context;
function Size
(DC : Disk_Context;
N : Natural)
return Disk_Context;
function I386
(PC : Processor_Context)
return Processor_Context;
function Sata
(DC : Disk_Context)
return Disk_Context;
function Computer
return Computer_Context;
private
type Processor_Context is tagged
null record;
type Disk_Context is tagged
null record;
type Computer_Context is tagged
null record;
end Computers;
Procedure Sequence and Named Parameters
Procedure sequence and named parameters result in DSLs that are very close to Ada’s native programming model. The composability is established from the sequence and Ada is sequential anyway. In addition, named parameters help to cut back on internal context management.
with Computers; use Computers;
procedure Main
with
SPARK_Mode => On
is
begin
Computer;
Processor (Cores => 2,
Speed => 2500,
Arch => I386);
Disk (Size => 150);
Disk (Size => 75,
Speed => 7200,
Bus => Sata);
Done;
end Main;
Assignment and Overloaded Operators
Overloaded operators allow me to mimick enumeration by leveraging unary and binary overloaded operators. The GNAT Spitbol Patterns library is a nice showcase how a DSL can be constructed from overloaded operators.
They work well as right-hand-sides of variable assignments since operators can appear only in expressions. The disadvantage of handling variables is that we have to use them.
with Computers; use Computers;
procedure Mchain
with
SPARK_Mode => On
is
C : Computer :=
- Processor
* Cores (2)
* Speed (2500)
* I386
- Disk
* Size (150)
- Disk
* Size (75)
* Speed (7200)
* Sata;
begin
Done (C);
end Mchain;
Communication
Advancing DSL-like interfaces from the role of a developer can quickly result in adverse situations. Peers quickly notice the focus on representation. It stands out from the conventional state-manipulation style.
Arguing that an interface needs to promote extensibility falls short: The client pays for the extension, not the extensibility.
Arguing that an interface needs to clearly reflect the domain model falls short: Preference follows habit not clarity.
The situation is aggravated by the fallacy that if AI was unaffected by all that limits human cognition and if software did not need to be read and written by humans anymore, then we could let slip good software design.