# Domain-Specific Languages for Algorithmic Graph Processing: A Systematic Literature Review
## 3 Results
### Result Synthesis
#### 3.2.3 RQ3. Approaches for DSL Implementation  
Implementing a DSL requires implementing a processor (generally a compiler or an interpreter) to execute programs in this language. All of the DSLs we review are compiled DSLs. Manually building a DSL and its compiler gives the developer full control over the implementation. Then, a secure and efficient implementation depends only on the developer's skill. However, this approach can be costly and involves a lot of boilerplate work. DSLs are often developed in small teams with limited resources, which makes it all the more important to have cost-effective tooling that supports both the developers (parser, type checker, and code generator) and the users of a DSL (IDE and debugger). The term language workbench (popularized by [PERSON] [55]) refers to a category of such tools, which typically provide an IDE environment for the meta-development of a DSL and its compiler, and for the DSL itself. Language workbenches promise an accessible, efficient, and affordable approach to DSL implementation. Several case studies in the literature attest to a positive return on investment and an increase in productivity with the language workbench approach [56; 57; 58; 59; 60; 61; 62]. Notable language workbench examples include MPS [63], Xtext [64], Rascal [65], and Spoofax [66].  
An alternative to developing DSL processors from scratch using language workbenches is to hook a DSL's frontend into an existing compiler architecture and reuse the compiler components it provides. One widely used example is LLVM [67], which offers a toolchain of modular and reusable components and technologies for building compilers. LLVM defines at its center a low-level, assembly-like IR in Static Single Assignment (SSA) form [68], allowing for a unified code representation of high-level languages. DSLs can map their frontends to LLVM IR to benefit from its source- and target-independent optimizer, as well as its code generation support for many popular CPUs. Many programming languages rely on LLVM for various compilation tasks, namely Ruby, Python, Haskell, Rust, D, PHP, Pure, Lua, Julia, and Swift. However, the low-level abstractions of LLVM IR make it potentially unsuitable for high-level compilers, whose target platforms typically require higher-level paradigms than what LLVM offers. MLIR [69] (multi-level intermediate representation) is another project under the LLVM umbrella. Recognizing the restrictivity of LLVM IR's low-level abstractions, MLIR provides a customizable IR that allows its users to define the right level of abstraction for their programs. By allowing for multiple levels of abstraction to freely coexist, MLIR makes it possible to lower part of the representation and maintain another in a higher-level abstraction more suitable for specific transformations.  
The DSL compiler presented by [PERSON] et al. [33] is based on MLIR. Of the graph DSLs we review, two are implemented using a language workbench: namely Green-Marl and the PGX Algorithm, which rely on Spoofax. GraphIt, Falcon, and an early version of the Green-Marl compiler are implemented in C++. [PERSON] et al. introduce their own solution, BuilDSL [48], an end-to-end framework for building DSLs using multistage programming in C++, which they use to implement a GraphIt to CUDA compiler. PyGB is implemented in Python, and it integrates with the NumPy, SciPy, and NetworkX libraries, for arrays, sparse matrices, and graphs, respectively. PyGB is dynamically compiled to C++.