Live data from Hacker News

Compiling a Lisp to x86-64: Let expressions

bernsteinbear.com

31–40 of 40 posts

Re: Compiling a Lisp to x86-64: Let expressions

#31
post #16

Earlier quoted context omitted.

And?

Aint I clever? Realized rightaway that forwards JMPs to the next address could have been filled with NOPs instead. But this is not a beauty contest.

Ah, right, I didn't look at your name. Have you worked on any other lisps?

Re: Compiling a Lisp to x86-64: Let expressions

#32
post #9

Earlier quoted context omitted.

Well, you've implemented let* : (let* ((a 1) (b a)) (+ a b)) is equivalent to: ((((lambda (a) (lambda (b) (+ a b))) a) 1) And anyway, implementing 'letrec' in C/Asm is really not that hard: allocate cells, assign names to them, compute the values. Compare that with the machinery of making closures (flat or linked?) and function invocation. I personally prefer to have 'letrec' as a primitive and implement non-recursiv…

> Well, you've implemented let* : (let* ((a 1) (b a)) (+ a b)) I think this should just be plain let. If I do: (define-syntax let- (syntax-rules () [(_ ((x e) ...) b1 b2 ...) ((lambda (x ...) b1 b2 ...) e ...)])) And then try: (let- ((a 2) (b a)) (+ a b)) I get: ; a: undefined; ; cannot reference an identifier before its definition ; in module: top-level

I don't really understand if you are surprised by that or not. That is the expected behaviour of regular let. Parallel binding. let* is sequential.

Re: Compiling a Lisp to x86-64: Let expressions

#33
post #31

Earlier quoted context omitted.

Aint I clever? Realized rightaway that forwards JMPs to the next address could have been filled with NOPs instead. But this is not a beauty contest.

Ah, right, I didn't look at your name. Have you worked on any other lisps?

Musimp/Mulisp dual syntax was very particular. The Lisp-scene has gone just downhill ever since, imho. http://www.edm2.com/index.php/MuLISP

Re: Compiling a Lisp to x86-64: Let expressions

#34
post #32

Earlier quoted context omitted.

> Well, you've implemented let* : (let* ((a 1) (b a)) (+ a b)) I think this should just be plain let. If I do: (define-syntax let- (syntax-rules () [(_ ((x e) ...) b1 b2 ...) ((lambda (x ...) b1 b2 ...) e ...)])) And then try: (let- ((a 2) (b a)) (+ a b)) I get: ; a: undefined; ; cannot reference an identifier before its definition ; in module: top-level

I don't really understand if you are surprised by that or not. That is the expected behaviour of regular let. Parallel binding. let* is sequential.

I'm not surprised by that. The parent suggested (or I thought that they did) that this was actually the definition for let* . And my point was to show that it does not behave like let* but rather like plain let.

Re: Compiling a Lisp to x86-64: Let expressions

#35

Earlier quoted context omitted.

Yes, real compilers do handle `((lambda (x) ...) ...)` as well as a `let`, because as a Lisp programmer you want to be able to define and use new macros freely, without having to worry too much about low-level optimizations. Kent Dybvig gave a talk on this sort of thing called the "macro-writer's Bill of Rights". It's a similar concept to the recent talk about what optimizations need to be guaranteed for "zero-cost a…

By guaranteed optimisations talk, are you referring to this blog post by Robert O'Callahan: https://robert.ocallahan.org/2020/08/what-is-minimal-set-of-... ?

Yes, thanks.

Re: Compiling a Lisp to x86-64: Let expressions

#36

(lets a 1 b 2 (+ a b)) is such a nice macro. Everything but the last expression are bindings.

What? The let way of variable bindings is standard just about everywhere. Why replace it with something that doesn't visually distinguish binding pairs? To my lispy eyes it is harder to navigate than

    (let ((a 1) (b 2))
      (+ a b))
and harder to implement as a syntax rules macro :)

Re: Compiling a Lisp to x86-64: Let expressions

#37
post #18

Earlier quoted context omitted.

That's really not true of Common Lisp implementations. These have many more than 20-30 functions, and they all have to be there because one can obtain them as values and pass those values around (and, in the case of standard generic functions, add new methods for them). There may be specific expansions for calls to particular standard functions when the types of the arguments are known, or when particular keyword and…

Well, of course; many of them will be functions, not macros. What I mean is, there will only be 20~30 builtins ; the rest can be implemented 'in userspace', as it were. Though specifically in the case of cl, clos might complicate that somewhat, but probably not a ton.

Let's go with this restatement.

It's one of the features of Common Lisp that things that might be buried in the compiler in other languages are surfaced and made available to the user. This means a great deal of the language's standard functionality can be implemented as if it were in "user space". Macros, readtables, method combinations, setf expanders and generalized places, for example.

IMO, if Common Lisp were to be extended (it probably won't be, at least officially, as there's no money for another whack at a standard) I think it would be best even if more "internal" features were surfaced this way, and made available for user extension.

Re: Compiling a Lisp to x86-64: Let expressions

#38
post #36

(lets a 1 b 2 (+ a b)) is such a nice macro. Everything but the last expression are bindings.

What? The let way of variable bindings is standard just about everywhere. Why replace it with something that doesn't visually distinguish binding pairs? To my lispy eyes it is harder to navigate than (let ((a 1) (b 2)) (+ a b)) and harder to implement as a syntax rules macro :)

Free yourself from the shackles of parens. Throw off your bindings and run into the streets. It's worth it.

Arc uses (let a 1 (+ a 2)), and lets is simply the logical progression of that.

Re: Compiling a Lisp to x86-64: Let expressions

#39
post #36

Earlier quoted context omitted.

What? The let way of variable bindings is standard just about everywhere. Why replace it with something that doesn't visually distinguish binding pairs? To my lispy eyes it is harder to navigate than (let ((a 1) (b 2)) (+ a b)) and harder to implement as a syntax rules macro :)

Free yourself from the shackles of parens. Throw off your bindings and run into the streets. It's worth it. Arc uses (let a 1 (+ a 2)), and lets is simply the logical progression of that.

I have gone the other way. when I first learned macros I spent loads of time trying to make paren-free versions of the standard scheme forms, and now I can't even be assed to do the racketism of surrounding my binding clauses with [].

The parens of let lets me easily distinguish the binding clauses, and lets me navigate it a lot easier in Emacs. The lets macro seems like the opposite of that. Every odd thing except the last element is an identifier and every even thing is that identifiers value.

Re: Compiling a Lisp to x86-64: Let expressions

#40
post #31

Earlier quoted context omitted.

Ah, right, I didn't look at your name. Have you worked on any other lisps?

Musimp/Mulisp dual syntax was very particular. The Lisp-scene has gone just downhill ever since, imho. http://www.edm2.com/index.php/MuLISP

Even with Racket, Shen, etc.?
Post reply on HN