Hans, > Apparently the string becomes a primitive char* at some point; at > least that's > my guess...
That's right. A "string" in an s-expression represents the address of its primitive contents (just like a string literal in C). To make a String object you can either construct it (as in your example) or quote it, like '"this". Steve Folta hit the nail on the head a few days ago: Jolt is just a (dynamic) C compiler with a Lisp-like syntax. Thinking of it that way might help you in your adventures with lambdas, arguments and environments. In C terms, lambdas are typedef void *(*lambda)(...); (pretend that you don't need a named arg before '...'). There is no explicit collection that contains the arguments; they are constructed (and only exist) transiently on the runtime stack (and/or in argument registers) for the duration of the call -- just like in C. The 'environment's that keep track of local variables are compile-time constructs that relate symbolic variable names to code generator objects representing the physical location (e.g., an offset into the runtime stack frame) where the variable's value will be stored. Again, just like a C compiler would use a symbol table to keep track of local variable names and implementations. So there is no 'current environment'. Variables are stored in stack frames, not in structured objects. By the time code is compiled and running, the 'environment' objects are long gone. There definitely ought to be meta information at run time that allows one to get at information about the frames in the stack but for now we don't have it. Right now the relationship between what you are trying to do and Jolt is the same as the relationship between Pepsi and the C compiler. Pepsi manages to implement (e.g.) blocks with free variables on top of C's runtime model, by using the very primitive facilities provided by C to build the higher-level facilities intrinsic to languages like Lisp and Smalltalk. The Pepsi compiler would have a far easier job if the C compiler made its meta information available to arbitrary user-defined functions that are instantiated and run during compilation. Your job should be far easier because Jolt does expose its meta information and does let you run arbitrary code during compilation. The beginnings of the necessary hooks are there (syntax functions, active variables, environments, etc.) but they are far from properly developed. The situation should improve significantly as I move the Pepsi compiler into Jolt, but for now what you are trying to do is simply very hard. One of the things that is planned and would help you immensely is a kind of 'apply' but it will be a very different thing from Lisp's apply, intended for building low-level calls (setup of arguments in stack/registers and a primitive subroutine 'call') dynamically. (Much closer to GCC's __builtin_apply* family of functions, if you know about those, but dynamic rather than static.) If anyone is up for a huge adventure in metaprogramming then here are a couple of things that are possible with the current (underdeveloped and under-documented) Compiler internals: 1. Syntax can be used to create something like a 'let' form (let's call it 'free-let') but which stores its variables' values in state arrays (much like the Pepsi compiler does for the free variables in blocks). The 'free-let' form could use 'active' to create active variables whose getters and setters operate on the slots in their state array. By keeping track of the nesting of state arrays (maybe one array per lambda, which can be redefined using 'syntax' as required) they can be chained together at runtime to provide access to non-local state. At compile time new active variable declarations would be inserted at the head of each nested lambda, with getters and setters that follow the appropriate number of chained state array indirections before designating the slot storing their value. 2. The Environments in the Compiler just associate variable names with objects that respond to 'translateLvalue:' to create the code needed to designate the location of the stored value at runtime. Free variables can be implemented in Pepsi within the Compiler by creating something like a NonLocalVariable type to populate the Compiler's Environments and then managing the same heap-allocated state arrays as described in (1) above. Neither of these are projects for the timid. (I'd be tempted to start with (2), just because I'm a wimp. ;-) The next step (for extra credits) would be to figure out how to call the resulting closures (lambdas that have to be initialised with the chain of state arrays) as if they were functions; i.e., no difference (to the caller) between lambda (without free state) and closures. Hope that helps rather than confuses. Cheers, Ian _______________________________________________ fonc mailing list [email protected] http://vpri.org/mailman/listinfo/fonc
