This library provides a parser interface for the built-in compound types defined in Common Lisp.

Consider when we have an unknown type specifier. It is easy to determine if this type is a subtype of string --- just use subtypep. Ok, so, is it also easy to parse the declared length of this string?

Not quite trivial as expected. This is because CL allows a bunch of alternative representations for a string subtypes. We have to consider all of (simple-base-string 50) , (string) or string. This is the target of this library.

This was initially a re-implementation of Bike/compiler-macro/type-utils.lisp . While it maintains the accessor for each type manually with lots of cond and case statements, I automated the definition of accessors with macros and pattern matcher Trivia, and provide more complete API for Common Lisp.

Types covered by this library are shown in the table below: which means, every compound types in CL. For the complete list of accessors, see quickdocs reference.

c.f. http://www.lispworks.com/documentation/HyperSpec/Body/04_bc.htm

and long-float simple-base-string
array member simple-bit-vector
base-string mod simple-string
bit-vector not simple-vector
complex or single-float
cons rational string
double-float real unsigned-byte
eql satisfies values
float short-float vector
function signed-byte bit
integer simple-array

Type Accessors

We have several accessor functions which returns the corresponding metadata of a given type specifier. The name of a function that obtains the Y portion of a given type X is named X-type-Y, e.g., for size portion of string, we have string-type-size.

(string-type-size '(string 50)) ; --> 50
(string-type-size '(string))    ; --> '*
(string-type-size 'string)      ; --> '*
(string-type-size 'base-string) ; |- error
(string-type-size '(base-string 50)) ; |- error

At this moment, the subtype relationship is not considered. For example, string-type-size does not match base-string. We have string-subtype-size and similar variants that matches all such subtypes.

(string-subtype-size '(string 50)) ; --> 50
(string-subtype-size '(string))    ; --> '*
(string-subtype-size 'string)      ; --> '*
(string-subtype-size 'base-string) ; --> '*
(string-subtype-size '(base-string 50)) ; --> 50

List of general pattern names related to arrays

  • base-string-subtype
  • string-subtype
  • bitvector-subtype
  • vector-subtype
  • simple-array-subtype
  • array-subtype

For type specifiers that are "Compound Type Specifier Kind: Specializing." or "Compound Type Specifier Kind: Abbreviating." in CLHS, there may be more metadata that do not explicitly appear in the type specifier but is still useful. For example, string implies that it is an array of character subtypes .

Given that array's element-type is accessible through array-type-element-type, we also provide string-type-element-type and so on.

(array-type-element-type 'array)               ; --> '*
(array-type-element-type '(array * 20))        ; --> '*
(array-type-element-type '(array character *)) ; --> 'character
(string-type-element-type 'string)             ; --> 'character
(array-subtype-element-type 'string)           ; --> 'character
(array-type-element-type 'string)              ; |- error (use *-subtype-* instead)

Number types

List of general pattern names related to numbers

  • byte-subtype
  • integer-subtype
  • float-subtype
  • real-subtype
  • float-subtype

Number type X have the corresponding functions X-low and X-high which shows the lower and the upper bound.

MOD type is a subtype of integers, so it is also supported. Same for BIT type.

Other types

We also support function, values, member, or, and, cons, member, eql.

  • function has function-type-return-type / function-type-args-type accessors.
  • member has member-type-members-.
  • or / and has or/and-type-types.
  • cons has cons-type-car/cdr-type.
  • eql has eql-type-object.

Pattern Matcher Integration

Type-R is implemented with a pattern matcher Trivia. This allows further integration of type specifiers with pattern matchers.

For a given type specifier X, there is a Trivia pattern X-type, e.g., for string, we have a pattern named string-type .

(match '(string 50)
  ((string-type size) size)) ; --> 50

(match '(string)
  ((string-type size) size)) ; --> '*

(match 'string
  ((string-type size) size)) ; --> '*
(ematch '(simple-array * 3)
  ((array-type _ rank) rank)) ; --> match error!

(ematch '(simple-array * 3)
  ((array-subtype _ rank) rank)) ; --> 3

(ematch '(simple-array * (3 2))
  ((array-subtype _ (list _ column)) column)) ; --> 2
(ematch '(simple-string 5)
  ((simple-string-type size) size)) ; --> 5

(ematch '(simple-string 5)
  ((simple-string-type _ type) type)) ; --> 'character

(ematch '(base-string 5)
  ((base-string-type _ type) type)) ; --> 'base-char

For number types, we have patterns like (float-type low high). Similarly to the array types, we have optional values that are bounded by default, e.g.,

(match 'fixnum
  ((integer-subtype low _) low)) ; --> [MOST-NEGATIVE-FIXNUM] (implementation dependent)


This library is at least tested on implementation listed below:

  • SBCL 1.2.8 on X86-64 Linux 3.13.0-46-generic (author's environment)

Also, it depends on the following libraries:

Trivia by Masataro Asai

NON-Optimized Pattern Matching Library

alexandria by

Alexandria is a collection of portable public domain utilities.

iterate by

Jonathan Amsterdam's iterator/gatherer/accumulator facility


  • Masataro Asai (guicho2.71828@gmail.com)


Copyright (c) 2015 Masataro Asai (guicho2.71828@gmail.com)


Licensed under the LLGPL License.

Masataro Asai