Live data from Hacker News

CHIP-8 in Common Lisp

stevelosh.com

11–20 of 21 posts

Re: CHIP-8 in Common Lisp

#12
post #3

Very interesting read! But could somebody explain why the following piece of code is needed? And why is it defined inline? (defun-inline (setf vref) (new-value chip x y) (setf (aref (chip-video chip) (+ (* +screen-width+ y) x)) new-value))

Wouldn't a lookup table be much faster here? That multiply on every screen access can't help the speed.

Re: CHIP-8 in Common Lisp

#13
post #3

Very interesting read! But could somebody explain why the following piece of code is needed? And why is it defined inline? (defun-inline (setf vref) (new-value chip x y) (setf (aref (chip-video chip) (+ (* +screen-width+ y) x)) new-value))

Wouldn't a lookup table be much faster here? That multiply on every screen access can't help the speed.

+screen-width+ is 64, which means SBCL can convert the multiply to a left shift if we care about speed and declare types:

    (defun foo (chip y)
      (declare (optimize speed)
               (type chip chip)
               (type int16 y))
      (vref chip 0 y))
    
    (disassemble 'foo)

    ; disassembly for FOO
    ; Size: 48 bytes. Origin: #x100EF5E39D
    ; 9D:       488B423D         MOV RAX, [RDX+61]                ; no-arg-parsing entry point
    ;; ---------------------- Look ma, no multiplication!
    ;;                           vvvvvvvvvvv
    ; A1:       48C1E706         SHL RDI, 6
    ; A5:       B900100000       MOV ECX, 4096
    ; AA:       40F6C701         TEST DIL, 1
    ; AE:       7513             JNE L0
    ; B0:       4839F9           CMP RCX, RDI
    ; B3:       760E             JBE L0
    ; B5:       488B54B801       MOV RDX, [RAX+RDI*4+1]
    ; BA:       488BE5           MOV RSP, RBP
    ; BD:       F8               CLC
    ; BE:       5D               POP RBP
    ; BF:       C3               RET
    ; C0:       0F0B10           BREAK 16                         ; Invalid argument count trap
    ; C3: L0:   0F0B0A           BREAK 10                         ; error trap
    ; C6:       06               BYTE #X06
    ; C7:       0C               BYTE #X0C                        ; INVALID-ARRAY-INDEX-ERROR
    ; C8:       1B               BYTE #X1B                        ; RAX
    ; C9:       9A               BYTE #X9A                        ; RCX
    ; CA:       FE9A03           BYTE #XFE, #X9A, #X03            ; RDI

Re: CHIP-8 in Common Lisp

#14

This is one of the coolest things i've ever seen! It's a rare treat to see low level programming in Common Lisp!! +100 for Steve Losh!

For more low-level Lisp see

https://github.com/kingcons/cl-6502/blob/master/README.md

And the corresponding book

http://redlinernotes.com/docs/cl-6502.pdf

Re: CHIP-8 in Common Lisp

#15
post #3

Very interesting read! But could somebody explain why the following piece of code is needed? And why is it defined inline? (defun-inline (setf vref) (new-value chip x y) (setf (aref (chip-video chip) (+ (* +screen-width+ y) x)) new-value))

vref and (setf vref) define getter and setter functions for manipulating pixel arrays. Since these functions are used a lot, it makes sense to allow compiler to inline them for maximum speed. Normally function must be accessed trough the symbol and it can be redefined on the fly.

I understand what they do, and I appreciate that it helps performance to inline them. What I don't understand is the (setf vref) syntax. I thought that after a defun statement you had to have a symbol, not an S-expression? Something like so:

    (defun-inline set-vref (new-value chip x y)
       ...)
And how would you actually call the original function to set a pixel? (I'm not very familiar with inlines, maybe that's my problem here.)

Re: CHIP-8 in Common Lisp

#16
post #15

Earlier quoted context omitted.

vref and (setf vref) define getter and setter functions for manipulating pixel arrays. Since these functions are used a lot, it makes sense to allow compiler to inline them for maximum speed. Normally function must be accessed trough the symbol and it can be redefined on the fly.

I understand what they do, and I appreciate that it helps performance to inline them. What I don't understand is the (setf vref) syntax. I thought that after a defun statement you had to have a symbol, not an S-expression? Something like so: (defun-inline set-vref (new-value chip x y) ...) And how would you actually call the original function to set a pixel? (I'm not very familiar with inlines, maybe that's my proble…

This is special syntax in Common Lisp. (SETF F) actually names a function too. It allows you to define a setter (a setf-expansion) with a normal DEFUN.

Re: CHIP-8 in Common Lisp

#18
post #15

Earlier quoted context omitted.

vref and (setf vref) define getter and setter functions for manipulating pixel arrays. Since these functions are used a lot, it makes sense to allow compiler to inline them for maximum speed. Normally function must be accessed trough the symbol and it can be redefined on the fly.

I understand what they do, and I appreciate that it helps performance to inline them. What I don't understand is the (setf vref) syntax. I thought that after a defun statement you had to have a symbol, not an S-expression? Something like so: (defun-inline set-vref (new-value chip x y) ...) And how would you actually call the original function to set a pixel? (I'm not very familiar with inlines, maybe that's my proble…

Common lisp has this universal setter-macro, SETF, which can be used to set values to all sorts of places.

In this case you would use

    (setf (vref chip x y) new-value)
to call the function (just like with AREF above). Using SETF has the advantage that you can define "modify macros" that read and write a place. For example,

    (incf (vref chip x y) delta)
would increment the place by DELTA. Or

    (rotatef (vref chip x1 y1)
             (vref chip x2 y2))
would swap two pixels.

Re: CHIP-8 in Common Lisp

#19
So here, Steve Losh, one of the best Vimmers out there, is also an excellent Lisper! It would be interesting to hear his views on Emacs since he transitioned to Clojure. I am curious to know whether he uses Vim for Clojure/Lisp development.

Re: CHIP-8 in Common Lisp

#20
post #19

So here, Steve Losh, one of the best Vimmers out there, is also an excellent Lisper! It would be interesting to hear his views on Emacs since he transitioned to Clojure. I am curious to know whether he uses Vim for Clojure/Lisp development.

I moved from Clojure to Common Lisp a few years ago.

I still use (Neo)Vim, using VLIME for Common Lisp interaction: https://github.com/l04m33/vlime It works great.

Post reply on HN