Pedro Delfino
Pedro Delfino

Reputation: 2711

Is there a way to find out how the primitive functions (built-in) where exactly defined inside SBCL?

I am learning Common Lisp using Emacs, SBCL and Slime.

I would like to know exactly what is the code definition of the built-in functions.

I know how to use (documentation ...) and (describe ...). However, they provide only high level information. I would like to see the code details.

For instance, take the nth built-in function.

Documentation gives us:

CL-USER> (documentation 'nth 'function)
"Return the nth object in a list where the car is the zero-th element."

Describe gives me:

CL-USER> (describe 'nth)
COMMON-LISP:NTH
  [symbol]

NTH names a compiled function:
  Lambda-list: (SB-IMPL::N LIST)
  Declared type: (FUNCTION (UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
  Derived type: (FUNCTION (T T) (VALUES T &OPTIONAL))
  Documentation:
    Return the nth object in a list where the car is the zero-th element.
  Inline proclamation: MAYBE-INLINE (inline expansion available)
  Known attributes: foldable, flushable, unsafely-flushable
  Source file: SYS:SRC;CODE;LIST.LISP

(SETF NTH) names a compiled function:
  Lambda-list: (SB-KERNEL::NEWVAL SB-IMPL::N LIST)
  Derived type: (FUNCTION (T UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
  Inline proclamation: INLINE (inline expansion available)
  Source file: SYS:SRC;CODE;SETF-FUNS.LISP

(SETF NTH) has a complex setf-expansion:
  Lambda-list: (SB-IMPL::N LIST)
  (undocumented)
  Source file: SYS:SRC;CODE;DEFSETFS.LISP
; No value

I would like to see something like:

(unknown-command 'nth)

Which would return something like:

(defun nth (x xs)
  (if (equal x 0)
      (car xs)
      (my-nth (- x 1) (cdr xs))))

Lisp languages are fantastic and have a huge ecossystem built by awesome programmers. I hope there is some tool or command for that.

Thanks

Upvotes: 1

Views: 336

Answers (2)

agam
agam

Reputation: 5394

First, some general clarifications

  • In your own code, hitting Meta-. should take you to the source of the code
  • This will also "just work" for libraries installed via Quicklisp.

Now for SBCL code itself:

  • If the code is in the "expected place", hitting Meta-. on built-in functions (like nth in your example above) will also take you to its source. I believe the default is /usr/share/sbcl-source/src/code/ but there's possibly a way to configure it.

  • However, there's another practical way to view this: if you look at the output of (describe ...) above, the line was:

Source file: SYS:SRC;CODE;LIST.LISP
  • Note: not the last line, that is for (setf nth), something slightly different

  • This tells you which file in the SBCL source code you can expect to find the function definition.

  • So, within [the repo](https:/ /github.com/sbcl/sbcl/tree/master/src), if you locate src/code/list.lisp, you should find the definition you're looking for; reproducing here:

(defun nth (n list)
  "Return the nth object in a list where the car is the zero-th element."
  (declare (explicit-check)
           (optimize speed))
  (typecase n
    ((and fixnum unsigned-byte)
     (block nil
       (let ((i n)
             (result list))
         (tagbody
          loop
            (the list result)
            (if (plusp i)
                (psetq i (1- i)
                       result (cdr result))
                (return (car result)))
            (go loop)))))
    (t
     (car (nthcdr n list)))))

Upvotes: 7

sds
sds

Reputation: 60062

When such information is available, it should be accessible via function-lambda-expression :

* (FUNCTION-LAMBDA-EXPRESSION #'nth)
(LAMBDA (SB-IMPL::N LIST)
  (DECLARE (SB-INT:EXPLICIT-CHECK)
           (OPTIMIZE SPEED))
  (BLOCK NTH
    (TYPECASE SB-IMPL::N
      ((AND FIXNUM UNSIGNED-BYTE)
       (BLOCK NIL
         (LET ((SB-IMPL::I SB-IMPL::N) (SB-IMPL::RESULT LIST))
           (TAGBODY
            LOOP
             (THE LIST SB-IMPL::RESULT)
             (IF (PLUSP SB-IMPL::I)
                 (PSETQ SB-IMPL::I (1- SB-IMPL::I)
                        SB-IMPL::RESULT (CDR SB-IMPL::RESULT))
                 (RETURN (CAR SB-IMPL::RESULT)))
             (GO LOOP)))))
      (T (CAR (NTHCDR SB-IMPL::N LIST))))))
NIL
NTH

However, it is not always available, in which case you would have to go to the SBCL source code repository.

Upvotes: 4

Related Questions