Figure 12.12 illustrates the dependencies between the versions of Camille developed in this chapter. Table 12.6 and Figure 12.13 present the dependencies between the versions of Camille developed in this text. Table 12.7 summarizes the versions of the Camille interpreter developed in this text. The presence of downward arrows in some of the cells in Table 12.7 indicates that the concept indicated by the cell is supported through its implementation in the defining language. Notice that reusing the implementation of concepts in the defining or implementation language limits what is possible in the language being interpreted. “Thus, for example, if the control frame structure in the implementation language is constrained to be stack-like, then modeling more general control structures in the interpreted language will be very difficult unless we divorce ourselves from the constrained structures at the outset” (Sussman and Steele 1975, p. 28).
Table 12.6 Complete Suite of Camille Languages and Interpreters (Key: ASR = abstract-syntax representation; CLS = closure; LOLR = list-of-lists representation.)
Data from Perugini, Saverio, and Jack L. Watkin. 2018. “ChAmElEoN: A customizable language for teaching programming languages.” Journal of Computing Sciences in Colleges (USA) 34(1): 44–51.
Table 12.7 Concepts and Features Implemented in Progressive Versions of Camille. The symbol ↓ indicates that the concept is supported through its implementation in the defining language (here, Python). The Python keyword included in each cell, where applicable, indicates which Python construct is used to implement the feature in Camille. The symbol ↑ indicates that the concept is implemented manually. The Camille keyword included in each cell, where applicable, indicates the syntactic construct through which the concept is operationalized. (Key: ASR = abstract-syntax representation; CLS = closure; LOLR = list-of-lists representation. Cells in boldface font highlight the enhancements across the versions.)
Table 12.8 outlines the configuration options available in Camille for aspects of the design of the interpreter (e.g., choice of representation of referencing environment), as well as for the semantics of implemented concepts (e.g., choice of parameter-passing mechanism). As we vary the latter, we get a different version of the language (Table 12.7). (Note that the nameless environments are available for use with neither the interpreter supporting dynamic scoping nor any of the interpreters in this chapter. Furthermore, not all environment representations are available with all implementation options. For instance, all of the interpreters in this chapter use exclusively the named ASR environment.)
Table 12.8 Complete Set of Configuration Options in Camille
Conceptual and Programming Exercises for Section 12.8
Exercise 12.8.1 Compiled programs run faster than interpreted ones. Reflect on the Camille interpreters you have built in this text. What is the bottleneck in an interpreter that causes an interpreted program to run orders of magnitude slower than a compiled program?
Exercise 12.8.2 Write a Camille program using any valid combination of the features and concepts covered in Chapters 10–12 and use it to stress test—in other words, spin the wheels of—the Camille interpreter. Your program must be at least 30 lines of code and original (i.e., not an example from the text). You are welcome to rewrite a program you wrote in the past and use it to flex the muscles of your interpreter. For instance, you can use Camille to build a closure representation of a stack or queue or a converter from decimal to binary numbers. If you like, you can add new primitives to the language and interpreter. Your program will be evaluated based on the use of novel language concepts implemented in the Camille interpreter (e.g., dynamic scoping, recursion, lazy evaluation) and the creativity of the program to solve a problem.
3.133.123.34