rebol/rebol — pull request #189 by hostilefork (2014-02-21 02:26:50+00:00)
Title: Non-copying FUNC-BOOT for all mezzanines + explicitly distinct from FUNC

In order to speed load times, the Mezzanine code (mostly) used a non-copying variant of FUNC, [simply defined](https://github.com/rebol/rebol/blob/4c32cc73b4641f8f6831b3ac549b5f5084c9e159/src/mezz/base-funcs.r#L19) as this:

func: make function! [[
; !!! This is a special minimal FUNC for more efficient boot. Gets replaced later in boot.
{Non-copying function constructor (optimized for boot).}
spec [block!] {Help string (opt) followed by arg words (and opt type and string)}
body [block!] {The body block of the function}
][
make function! reduce [spec body]
]]

When the mezzanine was done with its loading, it would switch over to an implementation of FUNC that deep copied... [saving this old version into FUNCO](https://github.com/rebol/rebol/blob/08eb7e84cdadf450727501bb8ec02fad45696959/src/mezz/mezz-tail.r#L14)

There are a few problems with the way things were done:

* It was not easy to know by looking at code which variant of FUNC was in effect. This made the usage of some mezzanines from within the mezzanine dangerous (such as COLLECT). They would only be safe to use at the point where the changeover to a copying FUNC happened.

* Not all mezzanines followed the convention, and there were FUNCTION instances being used in various places... even ones with no set-words in them. Given that it is hand-maintained system code, the time to scan the bodies for locals is probably not well spent. *(There are also "word not bound to a context" errors to help catch any missed LOCALs.)*

* Most users would not be able to use FUNCO safely so exporting it is probably a bad idea.

So instead of changing the definition of FUNC in midstream, it seems much better to be explicit about which one the code is using. FUNC-BOOT seemed like a more informative name than FUNCO.

FUNC is defined up front to give it an "early slot" (still not sure why that matters). However it gives an error message if you use it too early, and returns #[unset!]

I changed it to not to define FUNCTION until `%mezz-func.r`, which is currently the last thing that runs before `%mezz-tail.r`. Any mezzanine functions that need to invoke FUNCTION at boot time would have to thus be put between those two files. I turned all the existing FUNCTION instances into FUNC-BOOT with appropriate LOCALs. Extra eyeballs to see what I might have missed are helpful; though I've done enough to keep the test suite from complaining.

The copying FUNC is also defined in `%mezz-func.r`

In `%mezz-tail.r`, the FUNC-BOOT is defined to an error message, to prevent its use by users while still giving a meaningful message for any code taken out of the mezzanine that is not adapted to use FUNC instead of FUNC-BOOT.

This work was done as a preamble to research on the consequences of having PROTECT/DEEP run on the bodies of functions. Outside of needing a couple of COPY operations on help strings that were trimmed (which probably should have only been done once anyway) it mostly seems to work. Haven't gotten into looking at the general applications of it, but it seems to work for FUNC-BOOT...which makes it an interesting test.