5 Embedded domain-specific languages

This chapter covers

  • Modeling the domain
  • Designing embedded domain-specific languages with ADTs
  • Building multiple related languages organized properly
  • Interpreting languages and making them work

Software development is a difficult job. Developers do make wrong decisions, and this happens more often than it should. Developers do write incorrect code, and most likely, it happens against their will. Developers do feel lost in complex business domains, broad and contradictory requirements, and mind-bending technologies, each of which is able to make anyone depressed when something goes wrong. Nothing is perfect; nobody is superhuman.

While it’s certainly fine to demand software correctness, it’s not so obvious why unnecessary complex abstractions lead to bugs. One of the major reasons is that we lose the focus of the domain we’re implementing. If we treat an abstraction as a universal hammer that can solve all our problems at once, we risk straying far from the actual task, which is creating working code that solves a business problem. Many abstractions and approaches are intended to make our code more correct, but correctness is mostly about meaning (the domain) rather than technique (an abstraction).

5.1 Approaching embedded DSLs

5.1.1 Everything is an eDSL

5.1.2 Domain specific vs. domain centric

5.2 Modeling eDSLs with algebraic data types

5.2.1 Clarifying the requirements

5.2.2 Modeling eDSLs with ADTs

5.2.3 Modeling multiple interacting eDSLs

5.2.4 Decoupling languages with parameterized ADTs

5.3 Implementation of eDSLs

5.3.1 Runtime objects and lifetimes

5.3.2 Impure stateful interpreters

Summary