Beautiful, nex3. Works exactly like I had been thinking about. But I'm not sure that making the table live in Arc is the best idea... it relies on a table of a certain name, which I think is slightly odd. Nevertheless, excellent--including the move of everything but functions into arc.arc. Exactly how it should work. Thank you.
Now, if I could only understand defset, I'd be all set... :)
I put the table in Arc because I was trying to make it work as closely as possible to stuff like defset and help. Although it is a little weird to have the core code relying on stuff going on in Arc-land, I think that's going to be necessary to give Arc as much power as possible.
Also, the core code only relies on call to be defined when it's actually trying to resolve a functional-position object. Doing something like (= call nil) will only fail when you actually try to use a non-function object as a function.
I've been thinking that the Scheme code (ac.scm) should be split in two parts: an "axiomatic" part that defines car, cdr, set, annotate, etc; and a "library" part. The "library" part would define OS stuff like current-gc-milliseconds, open-socket, probably atomic-invoke, etc. There would probably be a "math" library that defines exp, sqrt, and all the missing math functions.
This structure would make it clear what parts of the language are really axioms, and what parts are in Scheme for performance, convenience, or because they are OS things that require low-level hooks.
Here "scheme-fn" is a macro that returns an Arc function that calls the named Scheme function, but still expects to be passed Scheme values and returns a Scheme value. Then various functions such as "scheme-istrue" can be used to convert Arc values to Scheme values and back again.