A Common Lisp source file is plain text. The standard (ANSI X3.226-1994) defines how the text is read and evaluated, not how files are named or stored, so everything on this page about extensions, encodings and headers is convention or implementation behaviour. Each such point says which.
Extensions and file kinds
.lisp– the usual name of a Common Lisp source file, and the one the standard’s own examples use. Implementations’loadandcompile-fileadd it when the name has no type..lsp– the same, from systems that limited extensions to three letters (MS-DOS, old Windows). The same extension is also AutoLISP; see Other Lisps..cl– also used by some Common Lisp programmers, and by OpenCL C kernels; the viewer tells them apart by reading the text..asd– an ASDF system definition. It is Common Lisp source, read by ASDF, usually holding onedefsystemform; see Systems and implementations..ros– a Roswell script: Common Lisp with a shell header that starts the implementation..fasland its relatives – compiled code, binary and specific to one implementation (and usually version); below..coreand other image files – a saved memory image, not source.
The pathname of a file is also a Lisp object: the standard’s pathname components are host, device, directory, name, type and version, and the file type "lisp" is what compile-file assumes when none is given. The default output type is implementation-defined.
Encoding and line endings
The standard defines a set of 96 standard characters (the 94 graphic ASCII characters, Space and Newline) and leaves the rest to the implementation. In practice every current implementation reads UTF-8, and SBCL, CCL, ECL, ABCL and LispWorks default to it in a UTF-8 locale. A file in another encoding is read by naming the external format when it is opened or loaded, for example (load "a.lisp" :external-format :latin-1); the keywords for external formats are implementation-defined, not standard.
A Newline in a source file is a single line feed in Unix text; Windows files with CR LF are accepted because the implementation’s external format turns the pair into #\Newline, or because the carriage return is treated as whitespace. A form feed (page, ^L) is whitespace to the reader, and was once used to separate sections of a file. A byte order mark is not part of the standard; most implementations treat a UTF-8 mark as a stray character unless they are told :utf-8 with BOM handling, so source files are best saved without one.
The mode line and header comments
By convention (from Lisp Machine and Emacs), the first line of a file holds a mode line inside a comment, setting the Emacs mode, the package the file is read in and the base of numbers:
;;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: my-app; Base: 10 -*-
;;;; greeting.lisp --- print greetings
;;;
;;; Copyright and licence text goes here.
(in-package #:my-app)
in-package form. The reader ignores everything on the comment lines.The reader does not look at the mode line: the package is chosen by the in-package form, which sets *package* while the file is being loaded or compiled. The comment conventions are by the number of semicolons: ;;;; for a file title, ;;; for a section, ;; for a comment on code (indented with it) and ; at the end of a line of code. Emacs indents these differently, which is the reason for the rule.
A script can start with a line of #!. SBCL, CCL and CLISP all let the reader skip a first line that begins #!, so #!/usr/bin/sbcl --script works as an interpreter line. This is not in the standard. Roswell scripts use a four-line header that is both a shell script and a Lisp block comment:
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(defun main (&rest argv)
(format t "~{~a~^ ~}~%" argv))
exec line; Lisp sees only a #| … |# comment.Top-level forms
A file is a sequence of forms separated by whitespace and comments. There is no declaration section, no file-level syntax and no terminator. load reads a form, evaluates it, and reads the next; compile-file reads a form, processes it as a top-level form and writes the result to the output file. Two consequences matter when reading a file:
- Each form is read after the previous one has been evaluated (when loading) or processed (when compiling), so an
in-packageordefpackagechanges how the rest of the file is read: the symbols after it are interned in another package. - The reader can run code while it reads, with
#.and with reader macros the program defined earlier, so the same text may read differently in another image.*read-eval*can disable#..
At top level, progn, eval-when, macrolet, symbol-macrolet and locally keep their body forms at top level, and macro forms are expanded first. This is how (eval-when (:compile-toplevel :load-toplevel :execute) …) makes a definition available both while compiling and when loading; see Special operators.
Compiled files
compile-file turns a source file into a fasl (fast-load) file, and load reads one by detecting the format. The standard does not define the format; each implementation has its own and may change it from one release to the next, so a fasl is only good for the implementation, version and often the operating system and processor that wrote it.
| Implementation | Compiled file type |
|---|---|
| SBCL | .fasl |
| Clozure CL | Per platform: .lx64fsl (Linux x86-64), .dx64fsl (macOS x86-64), .wx64fsl (Windows x86-64), .fx64fsl (FreeBSD x86-64), and similar for other processors |
| CMUCL | .x86f on x86; .sparcf on SPARC |
| CLISP | .fas, with a .lib file of information for the compiler |
| ECL | .fas or a native object .o / shared library through C; .fasc bundles |
| ABCL | Java class files, packed into .abcl archives (zip) |
| Allegro CL | .fasl |
| LispWorks | Per platform: .ufasl, .ofasl, .wfasl and others, including 64-bit variants |
An SBCL fasl begins with a text line that identifies it as a fasl, followed by a header naming the version of SBCL that wrote it, so a mismatched file can be refused with a clear message. The other formats are binary from the first byte. These files are shown in the viewer as bytes; they are not described here beyond naming them.
.core is an SBCL (and CMUCL) memory image, produced by save-lisp-and-die; it can include an executable runtime. CLISP’s image is .mem, Allegro’s is .dxl. They are not source files.
How the viewer reads a file
The viewer colours .lisp, .lsp, .asd and .ros files as Common Lisp when the text reads as Common Lisp. A .lsp or .lisp file that clearly belongs to another dialect is named for that dialect and, where the site has a colouring for it, coloured as it; see Other Lisps. The colouring is described on Lexical structure.
See also
- Lexical structure – how the text becomes tokens
- Systems and implementations – ASDF, Quicklisp and the implementations