Thinking some more about my own proposal:
[ .. ]
What I think needs to happen to get this designed:
Well, I found that it will probably all work, with one exception - to which I'd love to hear your comments:
Currently, all functions are class instances. For normal functions we don't require that, because the class itself doesn't store more than the parsed function arglist. I have an idea how to handle that situation though. Anyway, that's really globally applicable data and doesn't require instance allocation in case of compiled classes.
The problem arises when a compiled class wants to allocate instance data: i.e. when it wants to be a closure. Closures store a 'context' record in their instance. Since my idea revolves around creating static functions which call each other, this is an issue.
One thing I can come up with is: make the outer-most entry point a static function, make it allocate the context record (an array of ClosureBindings) and pass that around between the static functions as the first argument. This solves the common case for closures, like this one:
(defun foo (a-list) (mapcar #'(lambda (x) (member x a-list)) '(value-1 value-2 ...)))
The closure above can't be entered through any function which requires a context record to exist on the first call. However, there are cases (even in our own code base) where there are no entry points without a context record:
(let (something) (defun foo () (setf something 'a))
(defun goo () something))
(defun moo () (goo))
Compiling a direct call from moo to goo can't be a plain static call - it'll need the context record created at function definition time. Anybody who has any ideas how to solve this case?
Thanks for your comments!
Bye,
Erik.