On Saturday, September 23, 2017 at 2:45:55 PM UTC-5,
arc...@sacrideo.us wrote:
> Hello All:
>
> I'm sorry for creating such a mess. :-)
>
> My discussion with Bob was really about trying to understand what Forth calls compilation, and what features or approaches it takes to handling more complex issues of abstraction and static analysis.
>
> We were encountering some clear issues of vocabulary and methodology, so to try to limit the scope of the question, I wanted to address the first issue of the degree of "sophistication" of function handling in the language, and whether or not the language contained closures or the like.
I would investigate a new language by making a list of language
features and asking what they would like in the language. You'll get
responses like "it looks like this", "there's no direct support for
that but you could fake it with this", "we would never do that because
we have this other feature, but if you *really wanted to*--", and more
rarely "that's basically impossible, we would do this other stuff
instead in this or that usage of it".
http://rosettacode.org can help you find answers like that.
A question like "how do you do sophisticated abstraction?" is pretty
guaranteed to result in a thread like this, meanwhile.
>
> It is easier to demonstrate the counter program that I wanted to see compiled by writing it in Scheme:
>
> (define (make-counter init)
> (let ([counter init])
> (lambda () (set! counter (+ 1 counter)) counter)))
>
> => (define a (make-counter 0))
> => (define b (make-counter 5))
> => (a)
> 1
> => (a)
> 2
> => (b)
> 6
> => (b)
> 7
> => (a)
> 3
> =>
>
This is Paul Graham's accumulator generator--I referred to it above.
There are three important parts to it:
1. first-class functions (a function assigned to a variable and then
called as a function; a function returned from a function)
2. closures (a first-class function is created with its own copy of
some lexically determined state)
3. (as Paul Graham put it) bignums. The result of the calling the
counter must always be one plus the previous result. It can't be
suddenly less than the previous result, or equal to the previous
result.
Forth has the first. Libraries grant the third to Forth.
The second though is a case of "there's no direct support for that but
you can fake it". Forth doesn't have lexical variables, and functions
don't have hidden copies of state. But there are all several examples
of faking exactly this in the thread.
> The goal after seeing how this was written was to see how it was "compiled." I was interested to see how Forth dealt with the compilation and handling of internal functions and state.
>
> Finally, I was really trying to find a non-trivial enough example for Bob to demonstrate how Forth handles non-linear compilation tasks. All I saw was what looks like a direct node by node translation of each token/id into assembler, which is more like the process of assembly programming with a macro system than it Is a form of static compilation (though that's splitting hairs).
... you're asking about language features so that you can have an
understanding of compiler sophistication?
OK, this closure example, you can do it in eforth which doesn't do
function inlining or constant folding or any of that, and you can do
it in iforth which does do those things. Compiler sophistication
varies without changing the language.
"Isn't this just an assembler?" is a question I can't bring myself to
care about.