This development served as the basis for some assignment in the Course on Metaprogramming, University of Cambridge, UK Michaelmas Term 2018. It will now be extended to further experimentations.
The MOP example is to decide after the fact to change the execution strategy and tactics for how dynamic instances are represented while running -- e.g, can you decide that some objects should better use hash tables rather than arrays to represent them?”
Similarly, the MOP example is really interesting if the new behaviors added via reflective access are automatically compiled to be part of the base languages machinery (rather than being an interpreted add-on).
Running ./ex.sh
will produce folders and zip files for exercise ex1
.
For exercise ex2
, see the LMS branch.
-
The LMS branch has some variations that use Lightweight Modular Staging (LMS).
-
lispi.scala
is the basic interpreter. -
lispb.scala
turns all the interpreter structures into object structures (primitives, environment, continuations), so we can later do reification/reflection. -
lispc.scala
addsFSUBR
and exposes the interpreter functions, addsFEXPR
and implements aset!
with history tracking. -
lispd.scala
addscall/cc
as a built-in or user-defined form.
-
How much of Purple's infrastructure do we want to re-use? What is the intellectual contribution wrt to Purple?
-
Thinking by-hand about the compilation FEXPRs. What should happen for
(foo (+ 1 2))
? or(lambda (foo) (foo (+ 1 2)))
? -
Consider a Just-in-Time model of guarded optimizations.
-
Consider open implementations. How can the system provide compilation / implementation directives?
-
Consider restrictions to the semantics so that compilation is more reasonable. (How, without losing the spirit?)
-
Contrast FEXPRs implemented as a user-level concept in Black / Purple with the built-in FEXPRs here. Explore compilation and "bugs" (does compilation change the semantics? maybe not, because not optimizing compiler?) in FEXPRs in Purple.
-
Try modifying
base-eval
so that it records the calls to it as they happen. Should notice that base operations are not affected, only explicit calls tobase-eval
. How couldbase-eval
be truly modifiable? Would it cause an infinite recursion, unlike in the tower model? -
Try making
base-apply
more flexible, adding new custom calling conventions. -
Consider making environment functions like in Brown'84 to support custom behaviors during lookup? Or add a lookup function?
-
Add compilation to
lispc.scala
. How do we achieve that? We have to compile wrt to the current semantics. We need a way to distinguish environment entries that are stable. We put compilation under user control, with functions as a unit. What do we do withFEXPR
? Impose restrictions? Perhaps, follow the Purple model. -
Support macros in macros naturally? Do we need a macro calling convention? Do we need to define new calling convention at the user level?
-
Support macroexpansion separate from evaluation at the user level.
-
Implement quasiquotes in the reader, and then as a user-level macro.
-
How could one implement vectors at the user level?
-
Implement structs at the user level (using a macro), possibly following Matt Might's blogpost.
-
Implement a file loader.
-
Support variadic arguments.
-
Functions are opaque. Open them?