April 30th, 2010

Dynamic features, part 4

My previous post about dynamic features was about the new DynamicFunc object, which lets you create new code on the fly out of source code strings.  This time I'm going to expand on that a little.

First, you might wonder where macros fit in.  It's important that they do fit in somehow, since they're a big part of the adv3 library as well as the base system library.  The DynamicFunc class handles macros in a fairly straightforward way, by letting you specify them.  You simply provide a LookupTable in a particular format: each key is a macro name, and each value is a specially formatted list by contains the details of the macro's definition - basically a digested version of a #define directive.  Now, you can construct one of these macro tables yourself, which lets you not only compile code on the fly, but also create your own macro definitions on the fly for the code you compile.  But most of the time all you want is the original global macros for the main program, and happily, that's now available via reflection.  The Compiler object makes this completely transparent by plugging in the global macros as the default macro table for each compilation.  But it's worth knowing that  you can override this and create your own macros if you want.

Second, you might recall from an earlier posting that the system's reflection services now give you access to local variables in the active call stack..  A very cool feature of DynamicFunc is that it can take one or more of these local variable tables as a parameter when compiling new source code, and put those locals in scope for the new code.  The effect is a dynamic-code analogy to the lexical scope access that anonymous functions have.  A static anonymous function can access locals from lexically enclosing scopes - that is, from the source text that surrounds the anonymous function's definition.  The parallel for dynamic functions is that they can access locals from enclosing stack scopes - i.e., the current function and callers of the current function.  The parallel continues: this kind of access effectively "detaches" locals from their stack frames, so that the dynamic function can continue to access enclosing locals even after the calling functions have returned, just as anonymous functions can continue accessing lexically enclosing locals after those callers have returned.  As with many of these dynamic abilities, this is especially of interest to library utility writers, because it opens lots of interesting possibilities for library functions that interpret expressions written in string form. 

That mostly wraps it up for the new dynamic coding features.  I'm pretty excited about them; I think they're going to open up a whole new range of possibilities for extensions.  DynamicFunc is the big news, but I think once the system is out people will come up with lots of interesting ideas for combining it with the other new and existing dynamic features.