tighten the rules about special forms

here be undecidable dragons

git: commit

Special forms are syntactic structures of the language, that evaluate differently than the general application rule (i.e.: resolve the function, evaluate the arguments, apply). And I certainly got them and evapply wrong, at least previously. This commit fixes the behavior. Or at least I think so.

Internally I use evapply to evaluate both regular applications and special forms. One important difference of special forms is that they evaluate on pure syntactic structure: when evapply observes (quote A), it passes the list (A) to the handler of quote special form, but when it sees (myfun A), it resolves myfun and gets the value from the previously bound name A.

But what happens if myfun itself is bound to a special form as in (let ((myfun quote) (A 314)) (myfun A))? I can first resolve myfun to quote, and decide to not evaluate A for the special form, then expression reduces to A. Or I can decide that syntactically myfun is not a special form, and reduce myfun A to quote 314, and then further reduce it to 314.

I find the second option confusing, because biding symbol quote to myfun changed the semantics of the expression. But the first option is also very problematic, for a different reason, explained below.

Since lambdas are values in the language, I must take care to capture all the free variables in a lambda definition when I construct it. Furthermore, I need to take the capture decisions without evaluating the lambda, i.e. based on its purely syntactic structure. Now imagine the following function: (lambda (myfun) (myfun A)). The problem is: I cannot tell whether to capture A until I start evaluating an application of this lambda, because only then would I know whether myfun is a special form (e.g. quote) and the answer is NO, or whether it is a regular function and the answer is YES.

The only reasonable conclusion I draw from all these contradictions is that special forms are, ahem, special, and must not be used as values. In particular, the following expressions should be illegal in the language:

  • (let ((myfun quote)) ())
  • (((lambda () quote)) A)

This then means that the only way to use a special form is by using its true name at the beginning of an S-expression (cond ..., (let ..., and we can always decide based on syntax whether something is a special form or not.