[HN Gopher] The First Lisp Compiler
___________________________________________________________________
The First Lisp Compiler
Author : texdraft
Score : 142 points
Date : 2022-06-01 14:43 UTC (8 hours ago)
(HTM) web link (texdraft.github.io)
(TXT) w3m dump (texdraft.github.io)
| fulafel wrote:
| What does the prog form with parameters do? I only know about
| progn in CL.
| texdraft wrote:
| The "classic" prog still exists in Common Lisp. You probably
| haven't heard of it because it's almost never used. Here is the
| description in the HyperSpec:
| http://clhs.lisp.se/Body/m_prog_.htm#prog In Common Lisp terms,
| it's a combination of LET, BLOCK, and TAGBODY.
| aidenn0 wrote:
| There's also progv which, off the top of my head, is the only
| thing in the CL standard that lets you establish bindings
| (dynamic only for obvious reasons) on a non-constant list of
| symbols.
| larsbrinkhoff wrote:
| "Bernard S. Greenburg"
|
| It's Greenberg.
| texdraft wrote:
| Fixed, thanks.
| nemoniac wrote:
| Tail call elimination!!!
|
| I had no idea that this was in LISP 1.5. If you had asked me, I
| would have sworn it was Steele, 1977. Wikipedia supports that[1],
| albeit one might not consider it the most reliable source.
|
| So apparently (partial) TCE has been around since at least 1961.
| In that light, it's baffling that it's not supported more
| universally.
|
| [1] https://en.wikipedia.org/wiki/Tail_call
| pflanze wrote:
| The OP describes the support in HLC for TCO as limited (only
| for self-recursion, if I get it right, possibly more limited
| than that). Steele may still have been first to describe
| general TCO.
| dmux wrote:
| > In LISP 1.5, function definitions were stored on the property
| list of the function's name...
|
| The fact that this was once the norm but has since been done away
| with saddens me. I've always been fascinated with "live
| environments" but felt they only went half way if they didn't
| include the source code itself. If I'm going to be updating
| something in a running system, I want to know what source code
| was used to get the system to the state its currently in, and
| preferably be able to query that source code as data. Of course,
| that code could be kept within source control, but then it's a
| shadow of the running system -- a map of the territory and not
| the territory.
|
| As far as I know, the only languages/environments where this
| functionality is still available are Tcl, Smalltalk, and to some
| extent stored procedures within an RDBMS.
| boygobbo wrote:
| And Emacs
| spc476 wrote:
| Forth as well. ANS Forth defines the word SEE <https://forth-
| standard.org/standard/tools/SEE> that shows the current source
| of a given word.
| lispm wrote:
| many Lisp systems record the source location and/or the source
| itself (especially a source level interpreter needs that)
| dmux wrote:
| Do you mind enumerating what those systems are? I've only
| played around with Allegro CL and SBCL myself.
| rscho wrote:
| Doesn't SBCL have this functionality?
| mananaysiempre wrote:
| This is not the norm in Forth due to the very spartan
| environments it originated in, but most mature implementations
| include a pretty comprehensive decompiler as SEE. (Ironically,
| this is where the Forth claim of having a modular compiler
| comes apart, because SEE is always monolithic and
| nonextensible, or at least I haven't seen it done any other
| way.)
| pjmlp wrote:
| Note the date (1961), and the target hardware (IBM 7090 series),
| when considering whatever came after and existing hardware
| capabilities.
| aidenn0 wrote:
| Funny enough I was talking with someone who wanted to make a
| lisp run on a very small ARM SoC and we discovered that the
| 7090 Lisp 1.5 was developed on likely had more core+drum than
| the SoC had ram.
| [deleted]
| pjmlp wrote:
| Not even uLisp? That looks like a PIC like CPU to me.
| aidenn0 wrote:
| This might have been before uLisp (definitely prior to my
| knowledge of uLisp), and they wanted to write the
| interpreter for it themselves. IIRC it had 16k of RAM, so
| it definitely could have run uLisp.
|
| [edit]
|
| I should also point out that just storing the names of all
| of the symbols in the common lisp specification exceeds the
| RAM requirements of uLisp. Obviously builtins can go in
| ROM, but it gives you an idea of the sizes involved.
| exdsq wrote:
| uLisp was too large for a small flight computer I made for
| a hobbyist rocket - I wanted to use it but had such little
| RAM I had to go down to C. I think I could have ran lisp-
| to-c to generate from uLisp which I'll try on my next
| project.
| [deleted]
| bsder wrote:
| People _really_ underestimate how much RAM a Lisp /Scheme
| needs.
|
| Building lists out of pairs and then using them as your
| intermediate format creates a lot of garbage.
| aidenn0 wrote:
| Well 1MB is more than enough; that was the maximum virtual
| address space size of a PDP-10 where many of the precursors
| to common lisp were developed. You can do a fair amount
| with 100kB as well. uLisp runs with 34k minimum (32k ROM +
| 2k RAM).
| kazinator wrote:
| The RAM usage is tied to the size of the reachable set,
| plus some slack filled with garbage that depends on how you
| tune the garbage collection thresholds.
|
| By today's standards, the RAM usage isn't necessarily huge.
|
| Here is the TXR Lisp compiler recompiling
| stdlib/compiler.tl -> stdlib/compiler.tlo, as seen in top:
| PID USER PR NI VIRT RES SHR S %CPU %MEM
| TIME+ COMMAND 11488 kaz 20 0 17800
| 14804 2964 R 98.1 0.7 0:07.07 txr
| ^^^^^ ^^^^^
|
| On the order of a bash session. It's a lot of RAM by 1982
| standards at the institution level, and even 1992 standards
| at the consumer level, but today it means nothing.
|
| You can easily see a Bash process a footprint on that
| order.
|
| It could be reduced by tuning the garbage collector. One
| way to do that is to build for less memory use (useful for
| embedded). Here it is with txr rebuilt using #define
| CONFIG_SMALL_MEM 1 in config.h: PID USER
| PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
| 12838 kaz 20 0 11964 9768 3140 R 99.0 0.5
| 0:10.39 txr
|
| Bash footprints for comparison: $ ps aux |
| head -1 ; ps aux | grep bash USER PID %CPU %MEM
| VSZ RSS TTY STAT START TIME COMMAND kaz
| 1093 0.0 0.1 9288 2132 pts/2 Ss+ May15 0:01
| -bash kaz 2833 0.0 0.0 8904 1992 pts/0
| Ss May15 0:00 -bash kaz 3509 0.0 0.2
| 10532 4988 pts/1 Ss+ May15 0:28 -bash kaz
| 7898 0.0 0.1 8968 2212 pts/3 Ss+ May20 0:00
| -bash
|
| Lists are used for everything: the compiler produces a
| list-based assembly code which is used from then through
| assembly. There is an optimizer which divides it into basic
| blocks, which are objects put into a graph, but the
| instructions still being lists. The peephole pattern
| matching is done on lists. The compiler does not bother
| using destructive append (nconc) for stitching together
| fragments of code; just straight garbage-generating
| appends. Same with most of the other rewriting that happens
| later.
|
| In a computer in 1960, your compiler would be capped to the
| physical memory available. That would be the RAM use. The
| garbage collector would have to be called whenever the
| memory is exhausted, or else the show would stop. A
| successful compilation would demonstrate that the compiler
| needed no more memory than what the machine has. The closer
| its actual usage would be to the available memory, the
| longer it would take, due to the frequent garbage
| collections required to stay afloat.
|
| I'd say that given people's expectations today, shaped by
| experiences with everyday software, they likely greatly
| overestimate how much RAM you need for Lisp compiling.
___________________________________________________________________
(page generated 2022-06-01 23:01 UTC)