Case Mode Tutorial

Go to the tutorial main page.

This document describes how code developed in one case mode (i.e., ANSI mode or Modern mode) can be ported to the other case mode.

  1. Background: What are case modes?
  2. Importing ANSI mode source code into Modern mode
  3. Limitations of readtable-case when symbols are named by strings
  4. Importing Modern mode source code into ANSI mode

1. Background: What are case modes?

In addition to providing fully ANSI-compliant Common Lisp, Franz Inc. also provides an alternate Lisp implementation known as Modern mode. Modern mode Lisp is identical to ANSI Common Lisp except for the following two differences:

  1. The Lisp defined names are stored in lowercase.
  2. The default Lisp readtable-case is set to :preserve.

With just these two differences, Modern mode provides a "What You See Is What You Get" (WYSIWYG) symbol name environment. Although, all readtable-case and *print-case* settings are fully supported, they are unnecessary in Modern mode. Further discussion about Modern mode can be found in the Allegro CL documentation's case.htm.

To reduce download size, the Windows Allegro CL 6.2 Trial does not include a Modern mode image. Allegro CL 6.2 Trial users can build Modern mode images, though, by following the directions in the readme.txt file, accessible from the Windows menu item: Start -> Programs -> Allegro CL 6.2 Trial Edition -> README.

The modern mode images are initially named mlisp.dxl and mlisp8.dxl (and, on Windows, allegro.dxl). The ANSI mode images are named alisp.dxl and alisp8.dxl (and, on Windows, allegro-ansi.dxl). The current case mode is the value of *current-case-mode*. The value is :CASE-INSENSITIVE-UPPER in ANSI mode and :case-sensitive-lower in Modern mode.

2. Importing ANSI mode source code into Modern mode

ANSI mode source code may have been written assuming a case-insensitive reader. For example, the source code could use mixed-case text for Common Lisp symbols.

(DeFun my-pathname (x)
  (PathName x))

This code is not portable as-is to Modern mode because the "DeFun" and "PathName" symbols do not correspond to defined names in a fresh Modern mode environment. This code can still be loaded into Modern mode, though, without source modification by making the Lisp reader be case-insensitively lowercase. This can be done by setting readtable-case to :downcase as follows:

(setf (readtable-case *readtable*) :downcase)

Example (in a Modern mode session):

Note that these forms only work in a Modern image. They will not work in an ANSI image (such as the default Trial edition image). The first form tests whether you have a modern image.

;;  This example only works in a Modern image. The following form 
;;  returns T in a Modern image and NIL in an ANSI image. If the form
;;  returns NIL, the example will not work.
(equal "nil" (symbol-name 'common-lisp:nil))

;; Note that the results of the first two forms are displayed in
;; uppercase because *print-case*'s default value is :upcase.

> (setf (readtable-case *readtable*) :downcase)

> (DeFun my-pathname (x) (PathName x))

> (setf (readtable-case *readtable*) :preserve)

;; We can call the function in Modern mode.
> (my-pathname "foo")

An alternate import method is to compile the ANSI-dependent code in an ANSI mode Allegro CL and then load the resulting fasl files into a Modern mode session. As a precaution against inadvertently loading case-incompatible files into the case-sensitive Modern mode, Allegro CL 7.0 signals a continuable error when loading ANSI-compiled files into Modern mode. Continuing from this error allows the file to be loaded with its symbol-name references downcased. Thus, the effect on symbol names is similar to loading the corresponding source file using a :downcase readtable-case setting.

Example (also in Modern mode)

> (load "x.fasl")
; Fast loading x.fasl
Error: #P"x.fasl" was compiled in
       case-insensitive-upper mode.  Continuing to load this file may result
       in symbol-name mismatches.
  [condition type: fasl-casemode-mismatch]

Restart actions (select using :continue):
 0: Continue loading x.fasl

> :cont

> (my-pathname "foo")

One can bypass the error by wrapping the load statement as follows:

(handler-bind ((fasl-casemode-mismatch
		#'(lambda (&rest args)
		    (declare (ignore args))
		    (invoke-restart 'excl::fasl-casemode-mismatch-continue))))
  (load "x.fasl"))

3. Limitations of readtable-case when symbols are named by strings

The readtable-case setting and fasl symbol-name conversions only affects how symbol-names are converted. If literal uppercase strings are being used to name symbols, these will not be converted and the code may not run in Modern mode.


> (setf (readtable-case *readtable*) :downcase)

> (defun my-pathname (x) (funcall (intern "PATHNAME") x))

> (setf (readtable-case *readtable*) :preserve)

> (my-pathname "foo")
Error: attempt to call `PATHNAME' which is an undefined function.
  [condition type: undefined-function]

4. Importing Modern mode source code into ANSI mode

Porting Modern mode code to ANSI mode is generally straightforward as long as there are no dependencies on symbol-name cases. Modern mode code can simply be loaded and/or read into ANSI mode without modifying the Lisp reader controls. The ANSI mode Lisp reader upcases symbol names as they're being read. As long as symbols don't differ only by case and that there are no literal lowercase strings being used to name symbols, the code should run in ANSI mode.

Additionally, Modern mode fasl files can be loaded into ANSI mode sessions. Internally, Modern mode fasl files have symbol-names stored as the symbols were read (i.e., case-sensitively). When loaded into ANSI mode Allegro CL, though, the symbol names are converted to their uppercase equivalents.

This is the end of the tutorial. The documentation for case modes is in doc/case.htm.

Go to the tutorial main page.