top | item 43057168

(no title)

tonyg | 1 year ago

> Static analysis can tell what forms are invoking an fexpr and which are function calls. It's not got different from knowing which are macros. That problem can be solved.

I don't think this is the case. Consider Kernel's

  ($lambda (f) (f (+ 3 4)))
Is `f` a fexpr or a closure? We cannot know until runtime.

discuss

order

kazinator|1 year ago

We look it up at compile time. If it has a function binding defined at compile time, we go with that hypothesis. If it is a macro, we expand it. If it is a fexpr, we go with that hypothesis (and then do what? check if the application provides compilation semantics for the fexpr or abort.)

If it's unbound, we assume that it will be function and compile accordingly. We make a note that we did this.

If, by the end of the compilation unit, a definition of f has not been seen, we issue a warning. If a conflicting definition is seen, like a macro or fexpr, we also issue a warning.

(We provide a macro with-compilation-unit that the programmer or their build system can use to clump together multiple files into one compilation unit for the purpose of generating these kinds of diagnostics related to definitions.)

We carefully document all of this in our reference manual, in a section about how compilation semantics can differ from interpretation semantics.

This isn't rocket science. Been there, done that.

Xmd5a|1 year ago

Can you elaborate ? How do you figure it out at runtime ?

kazinator|1 year ago

At run time, you can inspect the current binding of f to see whether it is a macro, function or whatever. In an interpreter with fexprs, it would be late like this. At the time (f ...) is being called, if it was redefined to a fexpr, we go with that. If it is still a function, we call that.