Update automatically managed build utilities. buildable/master
authorMark Wooding <mdw@distorted.org.uk>
Sun, 20 Sep 2015 13:55:17 +0000 (14:55 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 20 Sep 2015 13:55:17 +0000 (14:55 +0100)
47 files changed:
.gitignore
Makefile.am
Makefile.in
configure
configure.ac
debian/control
debian/rules
debian/sod-doc.install [new file with mode: 0644]
doc/Makefile.am [new file with mode: 0644]
doc/Makefile.in [new file with mode: 0644]
doc/SYMBOLS [new file with mode: 0644]
doc/clang.tex [moved from doc/sod-protocol.tex with 52% similarity]
doc/concepts.tex [new file with mode: 0644]
doc/cutting-room-floor.tex [new file with mode: 0644]
doc/lispintro.tex [new file with mode: 0644]
doc/list-exports.lisp
doc/misc.tex [new file with mode: 0644]
doc/output.tex [new file with mode: 0644]
doc/parsing.tex [new file with mode: 0644]
doc/runtime.tex [new file with mode: 0644]
doc/sod-backg.tex [deleted file]
doc/sod.sty [new file with mode: 0644]
doc/sod.tex
doc/structures.tex [new file with mode: 0644]
doc/syntax.tex [new file with mode: 0644]
doc/tutorial.tex [moved from doc/sod-tut.tex with 86% similarity]
lib/sod-structs.3
src/c-types-impl.lisp
src/c-types-proto.lisp
src/class-make-impl.lisp
src/class-make-proto.lisp
src/codegen-impl.lisp
src/codegen-proto.lisp
src/final.lisp
src/frontend.lisp
src/lexer-bits.lisp [deleted file]
src/lexer-proto.lisp
src/module-impl.lisp
src/optparse.lisp
src/package.lisp
src/parser/parser-expr-impl.lisp
src/parser/parser-expr-proto.lisp
src/parser/parser-proto.lisp
src/parser/scanner-charbuf-impl.lisp
src/parser/scanner-impl.lisp
src/pset-proto.lisp
src/utilities.lisp

index 0bf9e54..b841037 100644 (file)
@@ -3,7 +3,9 @@
 *.out
 *.log
 *.dvi
+*.toc
 *.aux
+_region_.tex
 Makefile.in
 /COPYING
 /COPYING.LIB
@@ -11,4 +13,3 @@ Makefile.in
 /autom4te.cache/
 /config/
 /configure
-/doc/SYMBOLS
index d1a016d..302119b 100644 (file)
@@ -47,6 +47,9 @@ SUBDIRS                       += src
 ## The runtime support library.
 SUBDIRS                        += lib
 
+## The manual.
+SUBDIRS                        += doc
+
 ## The tests and examples.
 SUBDIRS                        += test
 
@@ -77,6 +80,9 @@ EXTRA_DIST              += debian/libsod-dev.install
 ## sod
 EXTRA_DIST              += debian/sod.install
 
+## sod-doc
+EXTRA_DIST              += debian/sod-doc.install
+
 ## sod-dev
 EXTRA_DIST              += debian/sod-dev.install
 
index e71cd0a..710e72b 100644 (file)
@@ -355,7 +355,8 @@ pkglispsrcdir = $(lispsrcdir)/$(PACKAGE)
 EXTRA_DIST = sod.pc.in config/auto-version config/confsubst \
        debian/rules debian/copyright debian/control debian/changelog \
        debian/compat debian/libsod.install debian/libsod-dev.install \
-       debian/sod.install debian/sod-dev.install
+       debian/sod.install debian/sod-doc.install \
+       debian/sod-dev.install
 CLEANFILES = $(BUILT_SOURCES) sod.pc
 DISTCLEANFILES = 
 MAINTAINERCLEANFILES = 
@@ -408,7 +409,7 @@ V_TEST_0 = @echo "  TEST   $@";
 
 ###--------------------------------------------------------------------------
 ### Subdirectories to build
-SUBDIRS = src lib test
+SUBDIRS = src lib doc test
 
 ###--------------------------------------------------------------------------
 ### Package-configuration file.
index 7b21c2f..b4b7a7d 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for sod 0.2.0-30-g58a9.
+# Generated by GNU Autoconf 2.69 for sod 0.2.0-86-g67d1.
 #
 # Report bugs to <mdw@distorted.org.uk>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='sod'
 PACKAGE_TARNAME='sod'
-PACKAGE_VERSION='0.2.0-30-g58a9'
-PACKAGE_STRING='sod 0.2.0-30-g58a9'
+PACKAGE_VERSION='0.2.0-86-g67d1'
+PACKAGE_STRING='sod 0.2.0-86-g67d1'
 PACKAGE_BUGREPORT='mdw@distorted.org.uk'
 PACKAGE_URL=''
 
@@ -1320,7 +1320,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures sod 0.2.0-30-g58a9 to adapt to many kinds of systems.
+\`configure' configures sod 0.2.0-86-g67d1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1390,7 +1390,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sod 0.2.0-30-g58a9:";;
+     short | recursive ) echo "Configuration of sod 0.2.0-86-g67d1:";;
    esac
   cat <<\_ACEOF
 
@@ -1499,7 +1499,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sod configure 0.2.0-30-g58a9
+sod configure 0.2.0-86-g67d1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1777,7 +1777,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by sod $as_me 0.2.0-30-g58a9, which was
+It was created by sod $as_me 0.2.0-86-g67d1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2593,7 +2593,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sod'
- VERSION='0.2.0-30-g58a9'
+ VERSION='0.2.0-86-g67d1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -11323,7 +11323,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 ## decimal.  Why two?  Because if there's no brown-paper-bag number, we
 ## want to make sure that the first BPB release is higher than any of the
 ## preceding Git revisions.
-ver=0.2.0-30-g58a9
+ver=0.2.0-86-g67d1
 case $ver in
   *-*-g*)
     base=${ver%%-*} tail=${ver#*-}
@@ -11435,7 +11435,7 @@ lispsysdir=$with_lisp_system_dir
 
 
 
-ac_config_files="$ac_config_files Makefile src/Makefile lib/Makefile test/Makefile"
+ac_config_files="$ac_config_files Makefile src/Makefile lib/Makefile doc/Makefile test/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -11995,7 +11995,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by sod $as_me 0.2.0-30-g58a9, which was
+This file was extended by sod $as_me 0.2.0-86-g67d1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12052,7 +12052,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-sod config.status 0.2.0-30-g58a9
+sod config.status 0.2.0-86-g67d1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -12452,6 +12452,7 @@ do
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
     "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
     "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+    "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
     "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
index c1fed50..73a903a 100644 (file)
@@ -105,7 +105,12 @@ AC_SUBST([lispsysdir], [$with_lisp_system_dir])
 dnl--------------------------------------------------------------------------
 dnl Output.
 
-AC_CONFIG_FILES([Makefile src/Makefile lib/Makefile test/Makefile])
+AC_CONFIG_FILES(
+  [Makefile]
+  [src/Makefile]
+  [lib/Makefile]
+  [doc/Makefile]
+  [test/Makefile])
 AC_OUTPUT
 
 dnl----- That's all, folks --------------------------------------------------
index 4fda78f..d94b77d 100644 (file)
@@ -36,7 +36,7 @@ Description: An object system for C, runtime library
 Package: sod
 Architecture: any
 Depends: ${shlibs:Depends}
-Recommends: libsod-dev (= ${Source-Version})
+Recommends: libsod-dev (= ${Source-Version}), sod-doc (= ${Source-Version})
 Description: An object system for C, translator
  Sod is a `sensible object design' for C, supporting a number of fancy
  features, including multiple inheritance, method combinations with daemon
@@ -46,9 +46,20 @@ Description: An object system for C, translator
  This package contains the Sod translator, which reads object definitions and
  produces compilable C code.
 
+Package: sod-doc
+Architecture: all
+Description: An object system for C, translator
+ Sod is a `sensible object design' for C, supporting a number of fancy
+ features, including multiple inheritance, method combinations with daemon
+ methods, and a compile-time metaprotocol.  The only downside is that the
+ translator is written in Common Lisp.
+ .
+ This package contains the Sod manual, which describes everything in
+ excruciating detail.
+
 Package: sod-dev
 Architecture: any
-Recommends: sbcl | clisp, cl-asdf, cl-xlunit
+Recommends: sbcl | clisp, cl-asdf, cl-xlunit, sod-doc (= ${Source-Version})
 Description: An object system for C, Lisp source
  Sod is a `sensible object design' for C, supporting a number of fancy
  features, including multiple inheritance, method combinations with daemon
index cec98bb..b6d10e5 100755 (executable)
@@ -1,2 +1,6 @@
 #! /usr/bin/make -f
 %:; dh $@ --parallel -Bdebian/build
+
+## Don't strip the main executable.  (It doesn't work, and you get left with
+## a bare SBCL.)
+override_dh_strip:; dh_strip -Xusr/bin/sod
diff --git a/debian/sod-doc.install b/debian/sod-doc.install
new file mode 100644 (file)
index 0000000..eac8396
--- /dev/null
@@ -0,0 +1 @@
+usr/share/doc/sod/*                    /usr/share/doc/sod-doc/
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644 (file)
index 0000000..882f01b
--- /dev/null
@@ -0,0 +1,74 @@
+### -*-makefile-*-
+###
+### Build script for the manual
+###
+### (c) 2015 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Sensble Object Design, an object system for C.
+###
+### SOD is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### SOD is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with SOD; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+include $(top_srcdir)/vars.am
+
+doc_DATA                =
+TEX_FILES               =
+
+CLEANFILES             += *.aux *.out *.log *.toc
+EXTRA_DIST             += $(TEX_FILES)
+
+###--------------------------------------------------------------------------
+### The manual.
+
+## The master file.
+TEX_FILES              += sod.tex
+
+## Main document styling and definitions.
+TEX_FILES              += sod.sty
+
+## Tutorial.
+TEX_FILES              += tutorial.tex
+
+## Reference.
+TEX_FILES              += concepts.tex
+##TEX_FILES            += cmdline.tex
+TEX_FILES              += syntax.tex
+TEX_FILES              += runtime.tex
+TEX_FILES              += structures.tex
+
+## Lisp interface.
+TEX_FILES              += lispintro.tex
+TEX_FILES              += misc.tex
+TEX_FILES              += parsing.tex
+TEX_FILES              += clang.tex
+##TEX_FILES            += meta.tex
+##TEX_FILES            += layout.tex
+##TEX_FILES            += module.tex
+##TEX_FILES            += ouptut.tex
+
+## Other hacks.
+TEX_FILES              += cutting-room-floor.tex
+
+## Building the output documents.
+MAINTAINERCLEANFILES   += sod.pdf
+EXTRA_DIST             += sod.pdf
+doc_DATA               += sod.pdf
+sod.pdf: $(TEX_FILES)
+       cd $(srcdir) && pdflatex --output-directory=$(abs_builddir) sod.tex
+       cd $(srcdir) && pdflatex --output-directory=$(abs_builddir) sod.tex
+
+###----- That's all, folks --------------------------------------------------
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644 (file)
index 0000000..999fc5d
--- /dev/null
@@ -0,0 +1,667 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+### -*-makefile-*-
+###
+### Build script for the manual
+###
+### (c) 2015 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Sensble Object Design, an object system for C.
+###
+### SOD is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### SOD is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with SOD; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+### -*-makefile-*-
+###
+### Common variable definitions for build scripts
+###
+### (c) 2015 Straylight/Edgeware
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of the Sensble Object Design, an object system for C.
+###
+### SOD is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### SOD is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with SOD; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Miscellaneous useful definitions.
+
+
+
+VPATH = @srcdir@
+am__make_dryrun = \
+  { \
+    am__dry=no; \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
+          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+      *) \
+        for am__flg in $$MAKEFLAGS; do \
+          case $$am__flg in \
+            *=*|--*) ;; \
+            *n*) am__dry=yes; break;; \
+          esac; \
+        done;; \
+    esac; \
+    test $$am__dry = yes; \
+  }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(dist_man_MANS) $(pkginclude_HEADERS) \
+       $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+       $(top_srcdir)/vars.am
+bin_PROGRAMS =
+check_PROGRAMS =
+subdir = doc
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docdir)" \
+       "$(DESTDIR)$(pkgincludedir)"
+PROGRAMS = $(bin_PROGRAMS)
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN   " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+DATA = $(doc_DATA)
+HEADERS = $(pkginclude_HEADERS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+ASDF_VERSION = @ASDF_VERSION@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CL_LAUNCH = @CL_LAUNCH@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION_INFO = @LIBTOOL_VERSION_INFO@
+LIPO = @LIPO@
+LISPSYS = @LISPSYS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fasl = @fasl@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+lispsrcdir = @lispsrcdir@
+lispsysdir = @lispsysdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+pkglispsrcdir = $(lispsrcdir)/$(PACKAGE)
+
+###--------------------------------------------------------------------------
+### Initial values for common variables.
+EXTRA_DIST = $(TEX_FILES) sod.pdf
+CLEANFILES = $(BUILT_SOURCES) *.aux *.out *.log *.toc
+DISTCLEANFILES = 
+MAINTAINERCLEANFILES = sod.pdf
+SUFFIXES = .c .h .sod
+BUILT_SOURCES = 
+pkginclude_HEADERS = 
+dist_man_MANS = 
+
+###--------------------------------------------------------------------------
+### Include and library path.
+SOD_INCLUDES = \
+       -I$(top_srcdir)/lib -I$(top_builddir)/lib
+
+AM_CPPFLAGS = $(SOD_INCLUDES)
+LDADD = $(top_builddir)/lib/libsod.la
+
+###--------------------------------------------------------------------------
+### Standard configuration substitutions.
+confsubst = $(top_srcdir)/config/confsubst
+SUBSTITUTIONS = \
+       prefix=$(prefix) exec_prefix=$(exec_prefix) \
+       libdir=$(libdir) includedir=$(includedir) \
+       bindir=$(bindir) sbindir=$(sbindir) \
+       srcdir=$(srcdir) \
+       PACKAGE=$(PACKAGE) VERSION=$(VERSION) ASDF_VERSION=$(ASDF_VERSION)
+
+V_SUBST = $(V_SUBST_$(V))
+V_SUBST_ = $(V_SUBST_$(AM_DEFAULT_VERBOSITY))
+V_SUBST_0 = @echo "  SUBST  $@";
+SUBST = $(V_SUBST)$(confsubst)
+
+###--------------------------------------------------------------------------
+### Translating SOD input files.
+SOD = $(top_builddir)/src/sod
+V_SOD_c = $(V_SOD_c_$(V))
+V_SOD_c_ = $(V_SOD_c_$(AM_DEFAULT_VERBOSITY))
+V_SOD_c_0 = @echo "  SOD[c] $@";
+V_SOD_h = $(V_SOD_h_$(V))
+V_SOD_h_ = $(V_SOD_h_$(AM_DEFAULT_VERBOSITY))
+V_SOD_h_0 = @echo "  SOD[h] $@";
+
+###--------------------------------------------------------------------------
+### Silent rules for Lisp.
+V_DUMP = $(V_DUMP_$(V))
+V_DUMP_ = $(V_DUMP_$(AM_DEFAULT_VERBOSITY))
+V_DUMP_0 = @echo "  DUMP   $@";
+V_TEST = $(V_TEST_$(V))
+V_TEST_ = $(V_TEST_$(AM_DEFAULT_VERBOSITY))
+V_TEST_0 = @echo "  TEST   $@";
+doc_DATA = sod.pdf
+
+###--------------------------------------------------------------------------
+### The manual.
+TEX_FILES = sod.tex sod.sty tutorial.tex concepts.tex syntax.tex \
+       runtime.tex structures.tex lispintro.tex misc.tex parsing.tex \
+       clang.tex cutting-room-floor.tex
+all: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .h .sod
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am $(top_srcdir)/vars.am $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign doc/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --foreign doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+$(top_srcdir)/vars.am:
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+       fi; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p || test -f $$p1; \
+         then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+           echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+           $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+       @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+clean-checkPROGRAMS:
+       @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+       echo " rm -f" $$list; \
+       rm -f $$list || exit $$?; \
+       test -n "$(EXEEXT)" || exit 0; \
+       list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+       echo " rm -f" $$list; \
+       rm -f $$list
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+install-docDATA: $(doc_DATA)
+       @$(NORMAL_INSTALL)
+       @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \
+       done
+
+uninstall-docDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir)
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+       @$(NORMAL_INSTALL)
+       @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+       fi; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+         $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+       done
+
+uninstall-pkgincludeHEADERS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(DATA) $(HEADERS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: $(BUILT_SOURCES)
+       $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       if test -z '$(STRIP)'; then \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+             install; \
+       else \
+         $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+           install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+           "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+       fi
+mostlyclean-generic:
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+       -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+       clean-libtool mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-docDATA install-pkgincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-docDATA \
+       uninstall-pkgincludeHEADERS
+
+.MAKE: all check check-am install install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-binPROGRAMS \
+       clean-checkPROGRAMS clean-generic clean-libtool distclean \
+       distclean-generic distclean-libtool distdir dvi dvi-am html \
+       html-am info info-am install install-am install-binPROGRAMS \
+       install-data install-data-am install-docDATA install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-pkgincludeHEADERS \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+       uninstall-binPROGRAMS uninstall-docDATA \
+       uninstall-pkgincludeHEADERS
+
+.sod.c: $(SOD); $(V_SOD_c)$(SOD) -tc $<
+.sod.h: $(SOD); $(V_SOD_h)$(SOD) -th $<
+
+###----- That's all, folks --------------------------------------------------
+sod.pdf: $(TEX_FILES)
+       cd $(srcdir) && pdflatex --output-directory=$(abs_builddir) sod.tex
+       cd $(srcdir) && pdflatex --output-directory=$(abs_builddir) sod.tex
+
+###----- That's all, folks --------------------------------------------------
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/doc/SYMBOLS b/doc/SYMBOLS
new file mode 100644 (file)
index 0000000..a6ae09d
--- /dev/null
@@ -0,0 +1,1957 @@
+-----------------------------------------------------------------------------
+Package `sod'
+
+pset-proto.lisp
+  add-property                                  function
+  check-unused-properties                       function
+  coerce-property-value                         generic
+  decode-property                               generic
+  get-property                                  function
+  make-property                                 function
+  make-property-set                             function
+  make-pset                                     function
+  p-key                                         function setf
+  p-name                                        function setf
+  p-seenp                                       function setf
+  p-type                                        function setf
+  p-value                                       function setf
+  property                                      class
+  property-key                                  function
+  property-set                                  generic
+  propertyp                                     function
+  pset                                          class
+  pset-get                                      function
+  pset-map                                      function
+  pset-store                                    function
+  psetp                                         function
+  store-property                                function
+  with-pset-iterator                            macro
+
+pset-parse.lisp
+  parse-property-set                            function
+
+output-proto.lisp
+  add-sequencer-constraint                      generic
+  add-sequencer-item-function                   generic
+  ensure-sequencer-item                         generic
+  hook-output                                   generic
+  invoke-sequencer-items                        generic
+  make-sequencer-item                           function
+  sequence-output                               macro
+  sequencer                                     class
+  sequencer-constraints                         generic setf
+  sequencer-item                                class
+  sequencer-item-functions                      function setf
+  sequencer-item-name                           function
+  sequencer-item-p                              function
+  sequencer-table                               generic
+
+module-proto.lisp
+  *module*                                      variable
+  add-clear-the-decks-function                  function
+  add-module-binding                            function
+  add-to-module                                 generic
+  clear-the-decks                               function
+  define-clear-the-decks                        macro
+  define-module                                 macro
+  define-module-var                             macro
+  finalize-module                               generic
+  module                                        class
+  module-dependencies                           generic setf
+  module-import                                 generic
+  module-items                                  generic setf
+  module-name                                   generic
+  module-pset                                   generic
+  with-module-environment                       macro
+  with-temporary-module                         macro
+
+module-parse.lisp
+  read-module                                   function
+
+module-output.lisp
+  banner                                        function
+  declare-output-type                           function
+  guard-name                                    function
+  output-module                                 function
+  output-type-pathname                          function
+
+module-impl.lisp
+  *module-dirs*                                 variable
+  c-fragment                                    class
+  c-fragment-text                               generic setf
+  code-fragment-item                            class
+  find-file                                     function
+  type-item                                     class
+
+method-proto.lisp
+  codegen-class                                 generic
+  codegen-message                               generic
+  codegen-method                                generic
+  codegen-target                                generic
+  compute-effective-method-body                 generic
+  compute-effective-methods                     generic
+  compute-method-entry-functions                generic
+  compute-sod-effective-method                  generic
+  convert-to-ilayout-inst                       class
+  effective-method                              class
+  effective-method-basic-argument-names         generic
+  effective-method-class                        generic
+  effective-method-function-name                generic
+  effective-method-message                      generic
+  ensure-ilayout-var                            function
+  inst-chain-head                               generic
+  inst-class                                    generic
+  inst-expr                                     generic
+  invoke-delegation-chain                       function
+  invoke-method                                 function
+  make-convert-to-ilayout-inst                  function
+  make-method-entries                           generic
+  make-trampoline                               function
+  message-effective-method-class                generic
+  method-codegen                                class
+  method-entry                                  class
+  method-entry-chain-head                       generic
+  method-entry-chain-tail                       generic
+  method-entry-effective-method                 generic
+  method-entry-function-name                    generic
+  method-entry-function-type                    generic
+  method-entry-slot-name                        generic
+  primary-method-class                          generic
+  simple-method-body                            generic
+  sod-message-argument-tail                     generic
+  sod-message-no-varargs-tail                   generic
+  sod-method-function-name                      generic
+  sod-method-function-type                      generic
+  sod-method-next-method-type                   generic
+  varargs-message-p                             function
+
+method-impl.lisp
+  basic-direct-method                           class
+  basic-effective-method                        class
+  basic-effective-method-body                   function
+  basic-message                                 class
+  daemon-direct-method                          class
+  delegating-direct-method                      class
+  simple-effective-method                       class
+  simple-message                                class
+  standard-effective-method                     class
+  standard-message                              class
+
+method-aggregate.lisp
+  aggregating-effective-method                  class
+  aggregating-message                           class
+  aggregating-message-properties                generic
+  check-aggregating-message-type                generic
+  compute-aggregating-message-kernel            generic
+  define-aggregating-method-combination         macro
+
+lexer-proto.lisp
+  define-indicator                              function
+  cl:error                                      function class parser
+  lexer-error                                   function
+  scan-comment                                  function
+  skip-until                                    function parser
+  sod-token-scanner                             class
+  syntax-error                                  function
+
+fragment-parse.lisp
+  parse-delimited-fragment                      function
+  scan-c-fragment                               function
+
+final.lisp
+  *debugout-pathname*                           variable
+  *sod-version*                                 variable
+  exercise                                      function
+  test-module                                   function
+
+codegen-proto.lisp
+  *sod-ap*                                      variable
+  *sod-master-ap*                               variable
+  block-inst                                    class
+  break-inst                                    class
+  codegen-add-function                          generic
+  codegen-build-function                        function
+  codegen-functions                             generic setf
+  codegen-pop                                   generic
+  codegen-pop-block                             generic
+  codegen-pop-function                          generic
+  codegen-push                                  generic
+  continue-inst                                 class
+  convert-stmts                                 function
+  definst                                       macro
+  deliver-expr                                  function
+  emit-decl                                     generic
+  emit-decls                                    generic
+  emit-inst                                     generic
+  emit-insts                                    generic
+  ensure-var                                    generic
+  expr-inst                                     class
+  format-compound-statement                     macro
+  format-temporary-name                         generic
+  function-inst                                 class
+  inst                                          class
+  inst-body                                     generic
+  inst-decls                                    generic
+  inst-expr                                     generic
+  inst-init                                     generic
+  inst-metric                                   generic
+  inst-name                                     generic
+  inst-op                                       generic
+  inst-type                                     generic
+  inst-var                                      generic
+  make-block-inst                               function
+  make-break-inst                               function
+  make-continue-inst                            function
+  make-expr-inst                                function
+  make-function-inst                            function
+  make-return-inst                              function
+  make-set-inst                                 function
+  make-update-inst                              function
+  make-var-inst                                 function
+  return-inst                                   class
+  set-inst                                      class
+  temp-tag                                      generic
+  temporary-name                                class
+  temporary-var                                 generic
+  update-inst                                   class
+  var-in-use-p                                  generic setf
+  var-inst                                      class
+  with-temporary-var                            macro
+
+codegen-impl.lisp
+  call-inst                                     class
+  codegen                                       class
+  do-while-inst                                 class
+  if-inst                                       class
+  inst-alt                                      generic
+  inst-ap                                       generic
+  inst-arg                                      generic
+  inst-args                                     generic
+  inst-body                                     generic
+  inst-cond                                     generic
+  inst-conseq                                   generic
+  inst-from                                     generic
+  inst-func                                     generic
+  inst-to                                       generic
+  make-call-inst                                function
+  make-do-while-inst                            function
+  make-if-inst                                  function
+  make-va-copy-inst                             function
+  make-va-end-inst                              function
+  make-va-start-inst                            function
+  make-while-inst                               function
+  temporary-argument                            class
+  temporary-function                            function class
+  temporary-variable                            class
+  va-copy-inst                                  class
+  va-end-inst                                   class
+  va-start-inst                                 class
+  while-inst                                    class
+
+classes.lisp
+  sod-class                                     class
+  sod-class-chain                               generic setf
+  sod-class-chain-head                          generic setf
+  sod-class-chain-link                          generic
+  sod-class-chains                              generic setf
+  sod-class-class-initializers                  generic setf
+  sod-class-direct-superclasses                 generic
+  sod-class-ilayout                             generic setf
+  sod-class-initializer                         class
+  sod-class-instance-initializers               generic setf
+  sod-class-messages                            generic setf
+  sod-class-metaclass                           generic
+  sod-class-methods                             generic setf
+  sod-class-name                                generic
+  sod-class-nickname                            generic
+  sod-class-precedence-list                     generic setf
+  sod-class-slots                               generic setf
+  sod-class-state                               generic setf
+  sod-class-type                                generic setf
+  sod-class-vtables                             generic setf
+  sod-initializer                               class
+  sod-initializer-class                         generic
+  sod-initializer-slot                          generic
+  sod-initializer-value-form                    generic
+  sod-initializer-value-kind                    generic
+  sod-instance-initializer                      class
+  sod-message                                   class
+  sod-message-class                             generic
+  sod-message-name                              generic
+  sod-message-type                              generic
+  sod-method                                    class
+  sod-method-body                               generic
+  sod-method-class                              generic
+  sod-method-message                            generic
+  sod-method-type                               generic
+  sod-slot                                      class
+  sod-slot-class                                generic
+  sod-slot-name                                 generic
+  sod-slot-type                                 generic
+
+class-utilities.lisp
+  argument-lists-compatible-p                   function
+  find-class-slot-by-name                       function
+  find-instance-slot-by-name                    function
+  find-message-by-name                          function
+  find-root-metaclass                           function
+  find-root-superclass                          function
+  find-superclass-by-nick                       function
+  ichain-struct-tag                             function
+  ichain-union-tag                              function
+  ilayout-struct-tag                            function
+  islots-struct-tag                             function
+  message-macro-name                            function
+  sod-subclass-p                                function
+  valid-name-p                                  function
+  vtable-name                                   function
+  vtable-struct-tag                             function
+  vtable-union-tag                              function
+  vtmsgs-struct-tag                             function
+
+class-make-proto.lisp
+  check-message-type                            generic
+  check-method-type                             generic
+  define-sod-class                              macro
+  guess-metaclass                               generic
+  make-sod-class                                function
+  make-sod-class-initializer                    generic
+  make-sod-initializer-using-slot               generic
+  make-sod-instance-initializer                 generic
+  make-sod-message                              generic
+  make-sod-method                               generic
+  make-sod-method-using-message                 generic
+  make-sod-slot                                 generic
+  sod-message-method-class                      generic
+
+class-layout-proto.lisp
+  base-offset                                   class
+  base-offset-chain-head                        generic
+  base-offset-class                             generic
+  chain-offset                                  class
+  chain-offset-chain-head                       generic
+  chain-offset-class                            generic
+  chain-offset-target-head                      generic
+  class-pointer                                 class
+  class-pointer-chain-head                      generic
+  class-pointer-class                           generic
+  class-pointer-meta-chain-head                 generic
+  class-pointer-metaclass                       generic
+  compute-effective-slot                        generic
+  compute-ichain                                generic
+  compute-ilayout                               generic
+  compute-islots                                generic
+  compute-vtable                                generic
+  compute-vtable-items                          generic
+  compute-vtables                               generic
+  compute-vtmsgs                                generic
+  effective-slot                                class
+  effective-slot-class                          generic
+  effective-slot-direct-slot                    generic
+  effective-slot-initializer                    generic
+  find-slot-initializer                         generic
+  ichain                                        class
+  ichain-body                                   generic
+  ichain-class                                  generic
+  ichain-head                                   generic
+  ichain-tail                                   generic
+  ilayout                                       class
+  ilayout-class                                 generic
+  ilayout-ichains                               generic
+  islots                                        class
+  islots-class                                  generic
+  islots-slots                                  generic
+  islots-subclass                               generic
+  make-base-offset                              generic
+  make-class-pointer                            generic
+  vtable                                        class
+  vtable-body                                   generic
+  vtable-chain-head                             generic
+  vtable-chain-tail                             generic
+  vtable-class                                  generic
+  vtable-pointer                                class
+  vtable-pointer-chain-head                     generic
+  vtable-pointer-chain-tail                     generic
+  vtable-pointer-class                          generic
+
+class-layout-impl.lisp
+  sod-class-effective-slot                      class
+  sod-class-slot                                class
+
+c-types-proto.lisp
+  argument                                      class
+  argument-name                                 function setf
+  argument-type                                 function setf
+  argumentp                                     function
+  c-name-case                                   function
+  c-type                                        macro class
+  c-type-alias                                  macro
+  c-type-equal-p                                generic
+  c-type-qualifiers                             generic
+  c-type-space                                  function
+  c-type-subtype                                generic
+  canonify-qualifiers                           function
+  commentify-argument-name                      generic
+  defctype                                      macro
+  define-c-type-syntax                          macro
+  expand-c-type-form                            generic
+  expand-c-type-spec                            generic
+  format-qualifiers                             function
+  make-argument                                 function
+  maybe-in-parens                               macro
+  pprint-c-type                                 generic
+  print-c-type                                  generic
+  qualifiable-c-type                            class
+  qualify-c-type                                generic
+
+c-types-parse.lisp
+  parse-c-type                                  function
+  parse-declarator                              function
+
+c-types-impl.lisp
+  cl:*                                          variable function c-type
+  cl:array                                      class c-type
+  c-array-dimensions                            generic
+  c-array-type                                  class
+  c-enum-type                                   class
+  c-function-arguments                          generic
+  c-function-type                               class
+  c-pointer-type                                class
+  c-struct-type                                 class
+  c-tagged-type-kind                            generic
+  c-type-name                                   generic
+  c-type-tag                                    generic
+  c-union-type                                  class
+  cl:char                                       function setf c-type parser
+  commentify-argument-names                     function
+  commentify-function-type                      function
+  const-string                                  c-type
+  define-simple-c-type                          macro
+  double                                        c-type
+  enum                                          c-type
+  cl:float                                      function class c-type
+  fn                                            c-type
+  fun                                           c-type
+  func                                          c-type
+  cl:function                                   function class c-type
+  int                                           c-type
+  kind-c-tagged-type                            generic
+  llong                                         c-type
+  long                                          c-type
+  long-double                                   c-type
+  long-int                                      c-type
+  long-long                                     c-type
+  long-long-int                                 c-type
+  make-array-type                               function
+  make-c-tagged-type                            function
+  make-enum-type                                function
+  make-function-type                            function
+  make-pointer-type                             function
+  make-simple-type                              function
+  make-struct-type                              function
+  make-union-type                               function
+  cl:nil                                        constant c-type parser
+  pointer                                       c-type
+  ptr                                           c-type
+  ptrdiff-t                                     c-type
+  cl:schar                                      function setf c-type
+  short                                         c-type
+  short-int                                     c-type
+  signed                                        c-type
+  signed-char                                   c-type
+  signed-int                                    c-type
+  signed-long                                   c-type
+  signed-long-int                               c-type
+  signed-long-long                              c-type
+  signed-long-long-int                          c-type
+  signed-short                                  c-type
+  signed-short-int                              c-type
+  simple-c-type                                 class
+  sint                                          c-type
+  size-t                                        c-type
+  sllong                                        c-type
+  slong                                         c-type
+  sshort                                        c-type
+  cl:string                                     function class c-type opthandler
+  struct                                        c-type
+  tagged-c-type                                 class
+  uchar                                         c-type
+  uint                                          c-type
+  ullong                                        c-type
+  ulong                                         c-type
+  cl:union                                      function c-type
+  unsigned                                      c-type
+  unsigned-char                                 c-type
+  unsigned-int                                  c-type
+  unsigned-long                                 c-type
+  unsigned-long-int                             c-type
+  unsigned-long-long                            c-type
+  unsigned-long-long-int                        c-type
+  unsigned-short                                c-type
+  unsigned-short-int                            c-type
+  ushort                                        c-type
+  va-list                                       c-type
+  vec                                           c-type
+  void                                          c-type
+  []                                            c-type
+
+c-types-class-impl.lisp
+  c-class-type                                  class
+  c-type-class                                  generic setf
+  cl:class                                      class c-type
+  find-class-type                               function
+  find-sod-class                                function
+  make-class-type                               function
+  record-sod-class                              function
+
+builtin.lisp
+  *builtin-module*                              variable
+  make-builtin-module                           function
+
+Classes:
+cl:t
+  sb-pcl::slot-object
+    cl:standard-object
+      base-offset
+      sod::basic-codegen
+        codegen
+          method-codegen
+      c-fragment
+      c-type
+        c-array-type
+        c-function-type
+        qualifiable-c-type
+          c-pointer-type
+          simple-c-type
+            c-class-type
+          tagged-c-type
+            c-enum-type
+            c-struct-type
+            c-union-type
+      chain-offset
+      class-pointer
+      code-fragment-item
+      sb-pcl::definition-source-mixin
+        cl:class [sb-pcl::dependent-update-mixin sb-pcl::standard-specializer]
+      effective-method
+        basic-effective-method
+          simple-effective-method
+            aggregating-effective-method
+            standard-effective-method
+      effective-slot
+        sod-class-effective-slot
+      ichain
+      ilayout
+      inst
+        block-inst
+        break-inst
+        call-inst
+        continue-inst
+        convert-to-ilayout-inst
+        do-while-inst
+        expr-inst
+        function-inst
+        if-inst
+        return-inst
+        set-inst
+        update-inst
+        va-copy-inst
+        va-end-inst
+        va-start-inst
+        var-inst
+        while-inst
+      islots
+      sb-mop:metaobject
+        sb-mop:specializer
+          sb-pcl::standard-specializer
+            cl:class [sb-pcl::dependent-update-mixin sb-pcl::definition-source-mixin]
+      method-entry
+      module
+      sb-pcl::plist-mixin
+        sb-pcl::dependent-update-mixin
+          cl:class [sb-pcl::definition-source-mixin sb-pcl::standard-specializer]
+      sequencer
+      sod-class
+      sod-initializer
+        sod-class-initializer
+        sod-instance-initializer
+      sod-message
+        basic-message
+          simple-message
+            aggregating-message
+            standard-message
+      sod-method
+        basic-direct-method
+          daemon-direct-method
+          delegating-direct-method
+      sod-slot
+        sod-class-slot
+      temporary-name
+        temporary-argument
+        temporary-function
+        temporary-variable
+      sod-parser:token-scanner
+        sod-token-scanner
+      type-item
+      vtable
+      vtable-pointer
+    cl:structure-object
+      argument
+      property
+      pset
+      sequencer-item
+
+Methods:
+add-sequencer-constraint
+  sequencer cl:list
+add-sequencer-item-function
+  sequencer t t
+add-to-module
+  module t
+aggregating-message-properties
+  aggregating-message (eql :custom)
+  t t
+base-offset-chain-head
+  base-offset
+base-offset-class
+  base-offset
+c-array-dimensions
+  c-array-type
+c-fragment-text
+  c-fragment
+(setf c-fragment-text)
+  t c-fragment
+c-function-arguments
+  c-function-type
+c-tagged-type-kind
+  c-union-type
+  c-struct-type
+  c-enum-type
+c-type-class
+  c-class-type
+(setf c-type-class)
+  t c-class-type
+c-type-equal-p
+  c-class-type c-class-type
+  c-function-type c-function-type
+  c-array-type c-array-type
+  c-pointer-type c-pointer-type
+  tagged-c-type tagged-c-type
+  simple-c-type simple-c-type
+  qualifiable-c-type qualifiable-c-type
+  t t
+c-type-name
+  simple-c-type
+c-type-qualifiers
+  qualifiable-c-type
+c-type-subtype
+  c-function-type
+  c-array-type
+  c-pointer-type
+c-type-tag
+  tagged-c-type
+chain-offset-chain-head
+  chain-offset
+chain-offset-class
+  chain-offset
+chain-offset-target-head
+  chain-offset
+check-aggregating-message-type
+  aggregating-message (eql :or) c-function-type
+  aggregating-message (eql :and) c-function-type
+  aggregating-message (eql :progn) c-function-type
+  t t t
+check-message-type
+  aggregating-message t
+  sod-message c-type
+  sod-message c-function-type
+check-method-type
+  daemon-direct-method sod-message c-function-type
+  sod-method sod-message c-function-type
+  sod-method sod-message c-type
+class-pointer-chain-head
+  class-pointer
+class-pointer-class
+  class-pointer
+class-pointer-meta-chain-head
+  class-pointer
+class-pointer-metaclass
+  class-pointer
+codegen-add-function
+  codegen t
+codegen-class
+  method-codegen
+codegen-functions
+  codegen
+(setf codegen-functions)
+  t codegen
+codegen-message
+  method-codegen
+codegen-method
+  method-codegen
+codegen-pop
+  codegen
+codegen-pop-block
+  t
+codegen-pop-function
+  t t t
+codegen-push
+  codegen
+codegen-target
+  method-codegen
+coerce-property-value
+  cl:symbol (eql :symbol) (eql :id)
+  cl:string (eql :string) (eql :id)
+  cl:string (eql :string) (eql :symbol)
+  cl:string (eql :id) (eql :symbol)
+  cl:string (eql :string) (eql :keyword)
+  cl:string (eql :id) (eql :keyword)
+  cl:symbol (eql :symbol) (eql :keyword)
+  t t t
+  t t (eql cl:t)
+commentify-argument-name
+  temporary-name
+  cl:null
+  t
+compute-aggregating-message-kernel
+  aggregating-message (eql :custom) t t t t
+  aggregating-message (eql :or) t t t t
+  aggregating-message (eql :and) t t t t
+  aggregating-message (eql :max) t t t t
+  aggregating-message (eql :min) t t t t
+  aggregating-message (eql :product) t t t t
+  aggregating-message (eql :sum) t t t t
+  aggregating-message (eql :progn) t t t t
+compute-effective-method-body
+  simple-effective-method t t
+compute-effective-methods
+  sod-class
+compute-effective-slot
+  sod-class sod-class-slot
+  sod-class sod-slot
+compute-ichain
+  sod-class t
+compute-ilayout
+  sod-class
+compute-islots
+  sod-class sod-class
+compute-method-entry-functions
+  simple-effective-method
+  basic-effective-method
+compute-sod-effective-method
+  sod-message sod-class
+compute-vtable
+  sod-class cl:list
+compute-vtable-items
+  sod-class sod-class sod-class sod-class cl:function
+compute-vtables
+  sod-class
+compute-vtmsgs
+  sod-class sod-class sod-class sod-class
+decode-property
+  cl:symbol
+  cl:integer
+  cl:string
+  cl:character
+  property
+  cl:cons
+  cl:function
+effective-method-basic-argument-names
+  basic-effective-method
+effective-method-class
+  effective-method
+effective-method-function-name
+  effective-method
+effective-method-message
+  effective-method
+effective-slot-class
+  effective-slot
+effective-slot-direct-slot
+  effective-slot
+effective-slot-initializer
+  effective-slot
+emit-decl
+  sod::basic-codegen t
+emit-decls
+  sod::basic-codegen t
+emit-inst
+  sod::basic-codegen t
+emit-insts
+  sod::basic-codegen t
+  t t
+ensure-sequencer-item
+  sequencer t
+ensure-var
+  sod::basic-codegen t t
+expand-c-type-form
+  (eql cl:class) t
+  (eql fn) t
+  (eql func) t
+  (eql cl:nil) t
+  (eql cl:function) t
+  (eql fun) t
+  (eql vec) t
+  (eql cl:array) t
+  (eql []) t
+  (eql ptr) t
+  (eql pointer) t
+  (eql cl:*) t
+  (eql cl:union) t
+  (eql struct) t
+  (eql enum) t
+  (eql ptrdiff-t) t
+  (eql size-t) t
+  (eql va-list) t
+  (eql long-double) t
+  (eql double) t
+  (eql cl:float) t
+  (eql unsigned-long-long) t
+  (eql long-long) t
+  (eql unsigned-long) t
+  (eql long) t
+  (eql unsigned-short) t
+  (eql short) t
+  (eql unsigned) t
+  (eql int) t
+  (eql signed-char) t
+  (eql unsigned-char) t
+  (eql cl:char) t
+  (eql void) t
+  cl:string t
+  (eql sod-parser:lisp) t
+expand-c-type-spec
+  (eql const-string)
+  (eql cl:string)
+  (eql ptrdiff-t)
+  (eql size-t)
+  (eql va-list)
+  (eql long-double)
+  (eql double)
+  (eql cl:float)
+  (eql ullong)
+  (eql unsigned-long-long-int)
+  (eql unsigned-long-long)
+  (eql sllong)
+  (eql llong)
+  (eql signed-long-long-int)
+  (eql long-long-int)
+  (eql signed-long-long)
+  (eql long-long)
+  (eql ulong)
+  (eql unsigned-long-int)
+  (eql unsigned-long)
+  (eql slong)
+  (eql signed-long-int)
+  (eql long-int)
+  (eql signed-long)
+  (eql long)
+  (eql ushort)
+  (eql unsigned-short-int)
+  (eql unsigned-short)
+  (eql sshort)
+  (eql signed-short-int)
+  (eql short-int)
+  (eql signed-short)
+  (eql short)
+  (eql uint)
+  (eql unsigned-int)
+  (eql unsigned)
+  (eql sint)
+  (eql signed-int)
+  (eql signed)
+  (eql int)
+  (eql cl:schar)
+  (eql signed-char)
+  (eql uchar)
+  (eql unsigned-char)
+  (eql cl:char)
+  (eql void)
+  cl:string
+  cl:list
+sod-parser:file-location
+  property
+  sod-method
+  sod-message
+  sod-initializer
+  sod-slot
+  sod-class
+finalize-module
+  module
+find-slot-initializer
+  sod-class sod-slot
+format-temporary-name
+  temporary-function t
+  temporary-variable t
+  temporary-argument t
+  temporary-name t
+guess-metaclass
+  sod-class
+hook-output
+  effective-slot (eql cl:class) t
+  sod-class-effective-slot (eql cl:class) t
+  vtable-pointer (eql cl:class) t
+  islots (eql cl:class) t
+  ichain (eql cl:class) t
+  method-entry (eql :c) t
+  sod::vtmsgs (eql :c) t
+  chain-offset (eql :c) t
+  base-offset (eql :c) t
+  class-pointer (eql :c) t
+  vtable (eql :c) t
+  basic-effective-method (eql :c) t
+  sod-method (eql :c) t
+  delegating-direct-method (eql :c) t
+  sod-class (eql :c) t
+  chain-offset (eql :h) t
+  base-offset (eql :h) t
+  class-pointer (eql :h) t
+  method-entry (eql sod::vtmsgs) t
+  sod::vtmsgs t t
+  sod::vtmsgs (eql sod::vtmsgs) t
+  sod::vtmsgs (eql :h) t
+  vtable (eql :h) t
+  sod-method (eql :h) t
+  vtable t t
+  islots (eql :h) t
+  islots t t
+  vtable-pointer (eql :h) t
+  ichain (eql ilayout) t
+  ichain (eql :h) t
+  ilayout (eql :h) t
+  ichain t t
+  ilayout t t
+  sod-slot (eql islots) t
+  sod-class t t
+  sod-class (eql :h) t
+  module (eql :c) t
+  module (eql :h) t
+  code-fragment-item t t
+  module t t
+  t t t
+ichain-body
+  ichain
+ichain-class
+  ichain
+ichain-head
+  ichain
+ichain-tail
+  ichain
+ilayout-class
+  ilayout
+ilayout-ichains
+  ilayout
+inst-alt
+  if-inst
+inst-ap
+  va-end-inst
+  va-start-inst
+inst-arg
+  va-start-inst
+inst-args
+  call-inst
+inst-body
+  do-while-inst
+  while-inst
+  function-inst
+  block-inst
+inst-chain-head
+  convert-to-ilayout-inst
+inst-class
+  convert-to-ilayout-inst
+inst-cond
+  do-while-inst
+  while-inst
+  if-inst
+inst-conseq
+  if-inst
+inst-decls
+  block-inst
+inst-expr
+  convert-to-ilayout-inst
+  expr-inst
+  return-inst
+  update-inst
+  set-inst
+inst-from
+  va-copy-inst
+inst-func
+  call-inst
+inst-init
+  var-inst
+inst-metric
+  convert-to-ilayout-inst
+  call-inst
+  va-end-inst
+  va-copy-inst
+  va-start-inst
+  do-while-inst
+  while-inst
+  if-inst
+  function-inst
+  block-inst
+  expr-inst
+  continue-inst
+  break-inst
+  return-inst
+  update-inst
+  set-inst
+  var-inst
+  t
+  cl:null
+  cl:list
+inst-name
+  function-inst
+  var-inst
+inst-op
+  update-inst
+inst-to
+  va-copy-inst
+inst-type
+  function-inst
+  var-inst
+inst-var
+  update-inst
+  set-inst
+invoke-sequencer-items
+  sequencer
+islots-class
+  islots
+islots-slots
+  islots
+islots-subclass
+  islots
+kind-c-tagged-type
+  (eql :union)
+  (eql :struct)
+  (eql :enum)
+make-base-offset
+  sod-class sod-class
+make-class-pointer
+  sod-class sod-class sod-class sod-class
+cl:make-load-form
+  c-fragment
+make-method-entries
+  basic-effective-method sod-class sod-class
+sod-parser:make-scanner-stream
+  sod-token-scanner
+make-sod-class-initializer
+  sod-class t t t t t
+make-sod-initializer-using-slot
+  sod-class sod-slot t t t t t
+make-sod-instance-initializer
+  sod-class t t t t t
+make-sod-message
+  sod-class t t t
+make-sod-method
+  sod-class t t t t t
+make-sod-method-using-message
+  sod-message sod-class t t t t
+make-sod-slot
+  sod-class t t t
+message-effective-method-class
+  aggregating-message
+  standard-message
+method-entry-chain-head
+  method-entry
+method-entry-chain-tail
+  method-entry
+method-entry-effective-method
+  method-entry
+method-entry-function-name
+  effective-method sod-class t
+method-entry-function-type
+  method-entry
+method-entry-slot-name
+  method-entry
+module-dependencies
+  module
+(setf module-dependencies)
+  t module
+module-import
+  sod-class
+  type-item
+  module
+  t
+module-items
+  module
+(setf module-items)
+  t module
+module-name
+  module
+module-pset
+  module
+pprint-c-type
+  c-function-type t t
+  c-array-type t t
+  c-pointer-type t t
+  tagged-c-type t t
+  simple-c-type t t
+  t t t
+primary-method-class
+  standard-message
+  simple-message
+print-c-type
+  t c-class-type
+  t c-function-type
+  t c-array-type
+  t c-pointer-type
+  t tagged-c-type
+  t simple-c-type
+cl:print-object
+  vtable t
+  chain-offset t
+  base-offset t
+  class-pointer t
+  ilayout t
+  ichain t
+  vtable-pointer t
+  islots t
+  method-entry t
+  effective-method t
+  effective-slot t
+  convert-to-ilayout-inst t
+  sequencer-item t
+  c-fragment t
+  call-inst t
+  va-end-inst t
+  va-copy-inst t
+  va-start-inst t
+  do-while-inst t
+  while-inst t
+  if-inst t
+  temporary-name t
+  function-inst t
+  block-inst t
+  expr-inst t
+  continue-inst t
+  break-inst t
+  return-inst t
+  update-inst t
+  set-inst t
+  var-inst t
+  pset t
+  sod-method t
+  sod-message t
+  sod-initializer t
+  sod-slot t
+  sod-class t
+  c-type t
+property-set
+  pset
+  cl:list
+qualify-c-type
+  qualifiable-c-type t
+sod-parser:scanner-token
+  sod-token-scanner
+sequencer-constraints
+  sequencer
+(setf sequencer-constraints)
+  t sequencer
+sequencer-table
+  sequencer
+cl:shared-initialize
+  aggregating-message t
+  method-codegen t
+  simple-effective-method t
+  basic-direct-method t
+  sod-class-slot t
+  sod-method t
+  sod-message t
+  sod-initializer t
+  sod-slot t
+  sod-class t
+  module t
+  c-function-type t
+  sod-token-scanner t
+simple-method-body
+  aggregating-effective-method t t
+  standard-effective-method t t
+cl:slot-unbound
+  t basic-effective-method (eql sod::functions)
+  t basic-effective-method (eql sod::basic-argument-names)
+  t delegating-direct-method (eql sod::function-type)
+  t delegating-direct-method (eql sod::next-method-type)
+  t basic-direct-method (eql sod::function-type)
+  t basic-message (eql sod::no-varargs-tail)
+  t basic-message (eql sod::argument-tail)
+  t sod-class (eql sod::vtables)
+  t sod-class (eql sod::effective-methods)
+  t sod-class (eql sod::%ilayout)
+sod-class-chain
+  sod-class
+(setf sod-class-chain)
+  t sod-class
+sod-class-chain-head
+  sod-class
+(setf sod-class-chain-head)
+  t sod-class
+sod-class-chain-link
+  sod-class
+sod-class-chains
+  sod-class
+(setf sod-class-chains)
+  t sod-class
+sod-class-class-initializers
+  sod-class
+(setf sod-class-class-initializers)
+  t sod-class
+sod-class-direct-superclasses
+  sod-class
+sod-class-ilayout
+  sod-class
+(setf sod-class-ilayout)
+  t sod-class
+sod-class-instance-initializers
+  sod-class
+(setf sod-class-instance-initializers)
+  t sod-class
+sod-class-messages
+  sod-class
+(setf sod-class-messages)
+  t sod-class
+sod-class-metaclass
+  sod-class
+sod-class-methods
+  sod-class
+(setf sod-class-methods)
+  t sod-class
+sod-class-name
+  sod-class
+sod-class-nickname
+  sod-class
+sod-class-precedence-list
+  sod-class
+(setf sod-class-precedence-list)
+  t sod-class
+sod-class-slots
+  sod-class
+(setf sod-class-slots)
+  t sod-class
+sod-class-state
+  sod-class
+(setf sod-class-state)
+  t sod-class
+sod-class-type
+  sod-class
+(setf sod-class-type)
+  t sod-class
+sod-class-vtables
+  sod-class
+(setf sod-class-vtables)
+  t sod-class
+sod-initializer-class
+  sod-initializer
+sod-initializer-slot
+  sod-initializer
+sod-initializer-value-form
+  sod-initializer
+sod-initializer-value-kind
+  sod-initializer
+sod-message-argument-tail
+  basic-message
+sod-message-class
+  sod-message
+sod-message-method-class
+  simple-message sod-class t
+  basic-message sod-class t
+  sod-message sod-class t
+sod-message-name
+  sod-message
+sod-message-no-varargs-tail
+  basic-message
+sod-message-type
+  sod-message
+sod-method-body
+  sod-method
+sod-method-class
+  sod-method
+sod-method-function-name
+  basic-direct-method
+sod-method-function-type
+  basic-direct-method
+sod-method-message
+  sod-method
+sod-method-next-method-type
+  delegating-direct-method
+sod-method-type
+  sod-method
+sod-slot-class
+  sod-slot
+sod-slot-name
+  sod-slot
+sod-slot-type
+  sod-slot
+temp-tag
+  temporary-name
+temporary-var
+  sod::basic-codegen t
+var-in-use-p
+  temporary-variable
+  t
+(setf var-in-use-p)
+  t temporary-variable
+vtable-body
+  vtable
+vtable-chain-head
+  vtable
+vtable-chain-tail
+  vtable
+vtable-class
+  vtable
+vtable-pointer-chain-head
+  vtable-pointer
+vtable-pointer-chain-tail
+  vtable-pointer
+vtable-pointer-class
+  vtable-pointer
+
+-----------------------------------------------------------------------------
+Package `sod-frontend'
+
+frontend.lisp
+  main                                          function
+
+Classes:
+cl:t
+
+Methods:
+
+-----------------------------------------------------------------------------
+Package `sod-parser'
+
+floc-proto.lisp
+  cerror*                                       function
+  cerror*-with-location                         function
+  cerror-with-location                          function
+  condition-with-location                       class
+  count-and-report-errors                       macro
+  enclosed-condition                            generic
+  enclosing-condition                           class
+  enclosing-condition-with-location             class
+  enclosing-error-with-location                 class
+  enclosing-warning-with-location               class
+  error-with-location                           function class
+  file-location                                 generic class
+  file-location-column                          function
+  file-location-filename                        function
+  file-location-line                            function
+  file-location-p                               function
+  make-condition-with-location                  function
+  make-file-location                            function
+  simple-condition-with-location                class
+  simple-error-with-location                    class
+  simple-warning-with-location                  class
+  warn-with-location                            function
+  warning-with-location                         class
+  with-default-error-location                   macro
+
+parser-expr-proto.lisp
+  apply-operator                                generic
+  binop                                         macro
+  close-parenthesis                             class
+  expr                                          parser
+  lparen                                        function
+  open-parenthesis                              class
+  operator-left-precedence                      generic
+  operator-push-action                          generic
+  operator-right-precedence                     generic
+  postop                                        macro
+  prefix-operator                               class
+  preop                                         macro
+  push-operator                                 generic
+  push-value                                    generic
+  rparen                                        function
+  simple-binary-operator                        class
+  simple-operator                               class
+  simple-postfix-operator                       class
+  simple-prefix-operator                        class
+  simple-unary-operator                         class
+
+parser-impl.lisp
+  list-parser                                   class
+  string-parser                                 class
+
+parser-proto.lisp
+  ?                                             parser
+  cl:and                                        macro parser
+  call-pluggable-parser                         function
+  cl:char                                       function setf c-type parser
+  character-parser-context                      class
+  combine-parser-failures                       function
+  cond-parse                                    macro
+  define-pluggable-parser                       macro
+  defparse                                      macro
+  expand-parser-form                            generic
+  expand-parser-spec                            generic
+  filter                                        parser
+  if-char                                       parser
+  if-parse                                      macro
+  sod-utilities:it
+  label                                         parser
+  lisp                                          c-type parser
+  cl:list                                       function class parser opthandler
+  many                                          parser
+  cl:not                                        function parser
+  cl:or                                         macro parser
+  parse
+  parser                                        macro
+  parser-at-eof-p                               generic
+  parser-capture-place                          generic
+  parser-current-char                           generic
+  parser-places-must-be-released-p              generic
+  parser-release-place                          generic
+  parser-restore-place                          generic
+  parser-step                                   generic
+  parser-token-type                             generic
+  parser-token-value                            generic
+  peek                                          parser
+  plug                                          parser
+  pluggable-parser-add                          function
+  cl:satisfies                                  parser
+  seq                                           parser
+  skip-many                                     parser
+  token                                         parser
+  token-parser-context                          class
+  when-parse                                    macro
+  with-parser-context                           macro
+  with-parser-place                             macro
+  wrap-parser                                   generic
+
+scanner-charbuf-impl.lisp
+  charbuf-scanner                               class
+  charbuf-scanner-map                           generic
+  charbuf-scanner-place-p                       function
+  charbuf-scanner-stream                        class
+
+scanner-impl.lisp
+  list-scanner                                  class
+  list-scanner-p                                function
+  make-list-scanner                             function
+  make-string-scanner                           function
+  string-scanner                                class
+  string-scanner-p                              function
+
+scanner-proto.lisp
+  character-scanner                             class
+  character-scanner-context                     class
+  character-scanner-stream                      class
+  make-scanner-stream                           generic
+  parser-scanner                                generic
+  scanner-at-eof-p                              generic
+  scanner-capture-place                         generic
+  scanner-column                                generic setf
+  scanner-context                               class
+  scanner-current-char                          generic
+  scanner-filename                              generic
+  scanner-interval                              generic
+  scanner-line                                  generic setf
+  scanner-release-place                         generic
+  scanner-restore-place                         generic
+  scanner-step                                  generic
+  scanner-token                                 generic
+  scanner-unread                                generic
+  token-scanner                                 class
+  token-scanner-context                         class
+  token-scanner-place                           class
+  token-scanner-place-p                         function
+  token-type                                    generic
+  token-value                                   generic
+  with-scanner-place                            macro
+
+streams-impl.lisp
+  position-aware-input-stream                   class
+  position-aware-output-stream                  class
+  position-aware-stream                         class
+  position-aware-stream-column                  generic setf
+  position-aware-stream-line                    generic setf
+
+streams-proto.lisp
+  stream-pathname                               generic
+
+Classes:
+cl:t
+  sb-pcl::slot-object
+    cl:standard-object
+      character-parser-context
+        character-scanner-context [scanner-context]
+        string-parser
+      character-scanner
+        charbuf-scanner
+      sb-gray:fundamental-stream [cl:stream]
+        sb-gray:fundamental-character-stream
+          sb-gray:fundamental-character-input-stream [sb-gray:fundamental-input-stream]
+            character-scanner-stream
+              charbuf-scanner-stream
+            sod-parser::proxy-character-input-stream [sod-parser::proxy-input-stream]
+              position-aware-input-stream [position-aware-stream]
+          sb-gray:fundamental-character-output-stream [sb-gray:fundamental-output-stream]
+            sod-parser::proxy-character-output-stream [sod-parser::proxy-stream]
+              position-aware-output-stream [position-aware-stream]
+        sb-gray:fundamental-input-stream
+          sb-gray:fundamental-character-input-stream [sb-gray:fundamental-character-stream]
+            character-scanner-stream
+              charbuf-scanner-stream
+            sod-parser::proxy-character-input-stream [sod-parser::proxy-input-stream]
+              position-aware-input-stream [position-aware-stream]
+          sod-parser::proxy-input-stream [sod-parser::proxy-stream]
+            sod-parser::proxy-character-input-stream [sb-gray:fundamental-character-input-stream]
+              position-aware-input-stream [position-aware-stream]
+        sb-gray:fundamental-output-stream
+          sb-gray:fundamental-character-output-stream [sb-gray:fundamental-character-stream]
+            sod-parser::proxy-character-output-stream [sod-parser::proxy-stream]
+              position-aware-output-stream [position-aware-stream]
+        sod-parser::proxy-stream
+          position-aware-stream
+            position-aware-input-stream [sod-parser::proxy-character-input-stream]
+            position-aware-output-stream [sod-parser::proxy-character-output-stream]
+          sod-parser::proxy-character-output-stream [sb-gray:fundamental-character-output-stream]
+            position-aware-output-stream [position-aware-stream]
+          sod-parser::proxy-input-stream [sb-gray:fundamental-input-stream]
+            sod-parser::proxy-character-input-stream [sb-gray:fundamental-character-input-stream]
+              position-aware-input-stream [position-aware-stream]
+      list-parser
+      sod-parser::parenthesis
+        close-parenthesis
+        open-parenthesis [prefix-operator]
+      prefix-operator
+        open-parenthesis [sod-parser::parenthesis]
+        simple-prefix-operator [simple-unary-operator]
+      scanner-context
+        character-scanner-context [character-parser-context]
+        token-scanner-context [token-parser-context]
+      simple-operator
+        simple-binary-operator
+        simple-unary-operator
+          simple-postfix-operator
+          simple-prefix-operator [prefix-operator]
+      token-parser-context
+        token-scanner-context [scanner-context]
+      token-scanner
+    cl:structure-object
+      file-location
+      list-scanner
+      string-scanner
+      token-scanner-place
+  cl:stream
+    sb-gray:fundamental-stream [cl:standard-object]
+      sb-gray:fundamental-character-stream
+        sb-gray:fundamental-character-input-stream [sb-gray:fundamental-input-stream]
+          character-scanner-stream
+            charbuf-scanner-stream
+          sod-parser::proxy-character-input-stream [sod-parser::proxy-input-stream]
+            position-aware-input-stream [position-aware-stream]
+        sb-gray:fundamental-character-output-stream [sb-gray:fundamental-output-stream]
+          sod-parser::proxy-character-output-stream [sod-parser::proxy-stream]
+            position-aware-output-stream [position-aware-stream]
+      sb-gray:fundamental-input-stream
+        sb-gray:fundamental-character-input-stream [sb-gray:fundamental-character-stream]
+          character-scanner-stream
+            charbuf-scanner-stream
+          sod-parser::proxy-character-input-stream [sod-parser::proxy-input-stream]
+            position-aware-input-stream [position-aware-stream]
+        sod-parser::proxy-input-stream [sod-parser::proxy-stream]
+          sod-parser::proxy-character-input-stream [sb-gray:fundamental-character-input-stream]
+            position-aware-input-stream [position-aware-stream]
+      sb-gray:fundamental-output-stream
+        sb-gray:fundamental-character-output-stream [sb-gray:fundamental-character-stream]
+          sod-parser::proxy-character-output-stream [sod-parser::proxy-stream]
+            position-aware-output-stream [position-aware-stream]
+      sod-parser::proxy-stream
+        position-aware-stream
+          position-aware-input-stream [sod-parser::proxy-character-input-stream]
+          position-aware-output-stream [sod-parser::proxy-character-output-stream]
+        sod-parser::proxy-character-output-stream [sb-gray:fundamental-character-output-stream]
+          position-aware-output-stream [position-aware-stream]
+        sod-parser::proxy-input-stream [sb-gray:fundamental-input-stream]
+          sod-parser::proxy-character-input-stream [sb-gray:fundamental-character-input-stream]
+            position-aware-input-stream [position-aware-stream]
+
+Methods:
+apply-operator
+  open-parenthesis sod-parser::expression-parse-state
+  simple-binary-operator sod-parser::expression-parse-state
+  simple-unary-operator sod-parser::expression-parse-state
+charbuf-scanner-map
+  charbuf-scanner t
+enclosed-condition
+  enclosing-condition
+expand-parser-form
+  token-scanner-context (eql cl:error) t
+  token-scanner-context (eql sod:skip-until) t
+  t (eql expr) t
+  list-parser (eql cl:type) t
+  list-parser (eql cl:quote) t
+  token-parser-context (eql token) t
+  character-parser-context (eql filter) t
+  character-parser-context (eql cl:not) t
+  character-parser-context (eql cl:satisfies) t
+  character-parser-context (eql cl:char) t
+  character-parser-context (eql if-char) t
+  t (eql peek) t
+  t (eql plug) t
+  t (eql ?) t
+  t (eql cl:or) t
+  t (eql skip-many) t
+  t (eql cl:list) t
+  t (eql many) t
+  t (eql lisp) t
+  t (eql cl:and) t
+  t (eql seq) t
+  t (eql cl:when) t
+  t (eql cl:nil) t
+  t (eql cl:t) t
+  t (eql label) t
+  t t t
+expand-parser-spec
+  list-parser t
+  token-parser-context cl:string
+  token-parser-context t
+  character-parser-context cl:string
+  character-parser-context (eql :whitespace)
+  character-parser-context cl:character
+  character-parser-context (eql :any)
+  t (eql cl:nil)
+  t (eql cl:t)
+  t (eql :eof)
+  t cl:list
+file-location
+  sod:property
+  sod:sod-method
+  sod:sod-message
+  sod:sod-initializer
+  sod:sod-slot
+  sod:sod-class
+  token-scanner-place
+  sod-parser::charbuf-scanner-place
+  token-scanner
+  character-scanner
+  position-aware-stream
+  cl:stream
+  t
+  condition-with-location
+  file-location
+cl:make-load-form
+  file-location
+make-scanner-stream
+  sod:sod-token-scanner
+  charbuf-scanner
+  string-scanner
+  character-scanner
+operator-left-precedence
+  simple-postfix-operator
+  simple-binary-operator
+operator-push-action
+  open-parenthesis t
+  t open-parenthesis
+  t t
+operator-right-precedence
+  simple-prefix-operator
+  simple-postfix-operator
+  simple-binary-operator
+parser-at-eof-p
+  scanner-context
+  string-parser
+  list-parser
+  token-parser-context
+parser-capture-place
+  scanner-context
+  string-parser
+  list-parser
+  t
+parser-current-char
+  character-scanner-context
+  string-parser
+parser-places-must-be-released-p
+  sod-parser::list-scanner-context
+  sod-parser::string-scanner-context
+  string-parser
+  list-parser
+  t
+parser-release-place
+  scanner-context t
+  t t
+parser-restore-place
+  scanner-context t
+  string-parser t
+  list-parser t
+parser-scanner
+  scanner-context
+parser-step
+  scanner-context
+  string-parser
+parser-token-type
+  token-scanner-context
+parser-token-value
+  token-scanner-context
+position-aware-stream-column
+  position-aware-stream
+(setf position-aware-stream-column)
+  t position-aware-stream
+position-aware-stream-line
+  position-aware-stream
+(setf position-aware-stream-line)
+  t position-aware-stream
+cl:print-object
+  simple-operator t
+  file-location t
+push-operator
+  close-parenthesis sod-parser::expression-parse-state
+  open-parenthesis sod-parser::expression-parse-state
+  prefix-operator sod-parser::expression-parse-state
+  t sod-parser::expression-parse-state
+push-value
+  t sod-parser::expression-parse-state
+scanner-at-eof-p
+  token-scanner
+  charbuf-scanner
+  list-scanner
+  string-scanner
+scanner-capture-place
+  token-scanner
+  charbuf-scanner
+  list-scanner
+  string-scanner
+  t
+scanner-column
+  charbuf-scanner
+  token-scanner
+  t
+(setf scanner-column)
+  t token-scanner
+scanner-current-char
+  charbuf-scanner
+  string-scanner
+scanner-filename
+  charbuf-scanner
+  token-scanner
+  t
+scanner-interval
+  charbuf-scanner t
+  string-scanner t
+scanner-line
+  charbuf-scanner
+  token-scanner
+  t
+(setf scanner-line)
+  t token-scanner
+scanner-release-place
+  token-scanner t
+  charbuf-scanner t
+  t t
+scanner-restore-place
+  token-scanner t
+  charbuf-scanner t
+  list-scanner t
+  string-scanner t
+scanner-step
+  token-scanner
+  charbuf-scanner
+  list-scanner
+  string-scanner
+scanner-token
+  sod:sod-token-scanner
+scanner-unread
+  charbuf-scanner t
+cl:shared-initialize
+  simple-binary-operator t
+  token-scanner t
+  charbuf-scanner t
+sb-gray:stream-line-column
+  position-aware-output-stream
+stream-pathname
+  position-aware-stream
+  sod-parser::proxy-stream
+  cl:stream
+  cl:file-stream
+sb-gray:stream-peek-char
+  character-scanner-stream
+sb-gray:stream-read-char
+  character-scanner-stream
+  position-aware-input-stream
+sb-gray:stream-read-line
+  charbuf-scanner-stream
+  position-aware-input-stream
+sb-gray:stream-read-sequence
+  charbuf-scanner-stream cl:string
+  position-aware-input-stream t
+sb-gray:stream-start-line-p
+  position-aware-output-stream
+sb-gray:stream-terpri
+  position-aware-output-stream
+sb-gray:stream-unread-char
+  character-scanner-stream t
+  position-aware-input-stream t
+sb-gray:stream-write-char
+  position-aware-output-stream t
+sb-gray:stream-write-sequence
+  position-aware-output-stream t
+sb-gray:stream-write-string
+  position-aware-output-stream t
+token-type
+  list-scanner
+  token-scanner
+token-value
+  list-scanner
+  token-scanner
+wrap-parser
+  string-parser t
+  t t
+
+-----------------------------------------------------------------------------
+Package `optparse'
+
+optparse.lisp
+  *command-line*                                variable
+  *help*                                        variable
+  *options*                                     variable
+  *program-name*                                variable
+  *usage*                                       variable
+  *version*                                     variable
+  clear                                         opthandler
+  dec                                           opthandler
+  define-program                                function
+  defopthandler                                 macro
+  defoptmacro                                   macro
+  die                                           function
+  die-usage                                     function
+  do-options                                    macro
+  do-usage                                      function
+  exit                                          function
+  help-options                                  optmacro
+  inc                                           opthandler
+  int                                           opthandler
+  invoke-option-handler                         function
+  cl:keyword                                    opthandler
+  cl:list                                       function class parser opthandler
+  make-option                                   function
+  make-option-parser                            function
+  moan                                          function
+  op-long-only-p                                function setf
+  op-negated-numeric-p                          function setf
+  op-negated-p                                  function setf
+  op-non-option                                 function setf
+  op-numeric-p                                  function setf
+  op-options                                    function setf
+  opt-arg-name                                  function setf
+  opt-arg-optional-p                            function setf
+  opt-documentation                             function setf
+  opt-long-name                                 function setf
+  opt-negated-tag                               function setf
+  opt-short-name                                function setf
+  opt-tag                                       function setf
+  option                                        class
+  option-parse-error                            function class
+  option-parse-next                             function
+  option-parse-remainder                        function
+  option-parse-return                           function
+  option-parse-try                              macro
+  option-parser                                 class
+  option-parser-p                               function
+  optionp                                       function
+  options                                       macro
+  parse-option-form                             function
+  cl:read                                       function opthandler
+  sanity-check-option-list                      function
+  cl:set                                        function opthandler
+  set-command-line-arguments                    function
+  show-help                                     function
+  show-usage                                    function
+  simple-usage                                  function
+  cl:string                                     function class c-type opthandler
+  with-unix-error-reporting                     macro
+
+Leaked slot names: cl:documentation, options
+  option: cl:documentation
+  option-parser: options
+
+Classes:
+cl:t
+  sb-pcl::slot-object
+    cl:structure-object
+      option
+      option-parser
+
+Methods:
+cl:print-object
+  option t
+
+-----------------------------------------------------------------------------
+Package `sod-utilities'
+
+utilities.lisp
+  acase                                         macro
+  acond                                         macro
+  aecase                                        macro
+  aetypecase                                    macro
+  aif                                           macro
+  asetf                                         macro
+  atypecase                                     macro
+  awhen                                         macro
+  backtrack-position                            function
+  categorize                                    macro
+  compose                                       function
+  copy-instance                                 function
+  copy-instance-using-class                     generic
+  default-slot                                  macro
+  define-access-wrapper                         macro
+  define-on-demand-slot                         macro
+  dosequence                                    macro
+  sb-mop:eql-specializer                        class
+  sb-mop:eql-specializer-object                 generic
+  frob-identifier                               function
+  sb-mop:generic-function-methods               generic setf
+  inconsistent-merge-error                      class
+  instance-initargs                             generic
+  it
+  lbuild-add                                    function
+  lbuild-add-list                               function
+  lbuild-list                                   function
+  loc                                           class
+  locf                                          macro
+  locp                                          function
+  make-list-builder                             function
+  mappend                                       function
+  maybe-print-unreadable-object                 macro
+  merge-error-candidates                        generic
+  merge-lists                                   function
+  sb-mop:method-specializers                    generic
+  once-only                                     macro
+  parse-body                                    function
+  ref                                           function setf
+  symbolicate                                   function
+  update-position                               function
+  whitespace-char-p                             function
+  with-gensyms                                  macro
+  with-locatives                                macro
+
+Classes:
+cl:t
+  sb-pcl::slot-object
+    cl:standard-object
+      sb-mop:metaobject
+        sb-mop:specializer
+          sb-pcl::exact-class-specializer
+            sb-mop:eql-specializer [sb-pcl::standard-specializer sb-pcl::specializer-with-object]
+          sb-pcl::specializer-with-object
+            sb-mop:eql-specializer [sb-pcl::standard-specializer sb-pcl::exact-class-specializer]
+          sb-pcl::standard-specializer
+            sb-mop:eql-specializer [sb-pcl::exact-class-specializer sb-pcl::specializer-with-object]
+    cl:structure-object
+      loc
+
+Methods:
+copy-instance-using-class
+  cl:standard-class t
+sb-mop:eql-specializer-object
+  sb-mop:eql-specializer
+sb-mop:generic-function-methods
+  cl:standard-generic-function
+(setf sb-mop:generic-function-methods)
+  t cl:standard-generic-function
+instance-initargs
+  cl:standard-object
+merge-error-candidates
+  inconsistent-merge-error
+sb-mop:method-specializers
+  cl:standard-method
+
similarity index 52%
rename from doc/sod-protocol.tex
rename to doc/clang.tex
index f0bd115..52e330d 100644 (file)
@@ -1,13 +1,13 @@
 %%% -*-latex-*-
 %%%
-%%% Description of the internal class structure and protocol
+%%% C language utilities
 %%%
-%%% (c) 2009 Straylight/Edgeware
+%%% (c) 2015 Straylight/Edgeware
 %%%
 
 %%%----- Licensing notice ---------------------------------------------------
 %%%
-%%% This file is part of the Simple Object Definition system.
+%%% This file is part of the Sensble Object Design, an object system for C.
 %%%
 %%% SOD is free software; you can redistribute it and/or modify
 %%% it under the terms of the GNU General Public License as published by
 %%% along with SOD; if not, write to the Free Software Foundation,
 %%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-\chapter{Protocol overview} \label{ch:proto}
-
-This chapter provides an overview of the Sod translator's internal object
-model.  It describes most of the important classes and generic functions, how
-they are used to build a model of a Sod module and produce output code, and
-how an extension might modify the translator's behaviour.
-
-I assume familiarity with the Common Lisp Object System (CLOS).  Familiarity
-with the CLOS Metaobject Protocol isn't necessary but may be instructive.
-
-%%%--------------------------------------------------------------------------
-\section{A tour through the translator}
-
-At the very highest level, the Sod translator works in two phases: it
-\emph{parses} source files into an internal representation, and then it
-\emph{generates} output files from the internal representation.
-
-The function @|read-module| is given a pathname for a file: it opens the
-file, parses the program text, and returns a @|module| instance describing
-the classes and other items found.
-
-At the other end, the main output function is @|output-module|, which is
-given a module, an output stream and a 
-
-
-%%%--------------------------------------------------------------------------
-\section{Specification conventions} \label{sec:proto.conventions}
-
-Throughout this specification, the phrase `it is an error' indicates that a
-particular circumstance is erroneous and results in unspecified and possibly
-incorrect behaviour.  In particular, the situation need not be immediately
-diagnosed, and the consequences may be far-reaching.
-
-The following conventions apply throughout this specification.
-
-\begin{itemize}
-
-\item If a specification describes an argument as having a particular type or
-  syntax, then it is an error to provide an argument not having that
-  particular type or syntax.
-
-\item If a specification describes a function then that function might be
-  implemented as a generic function; it is an error to attempt to (re)define
-  it as a generic function, or to attempt to add methods to it.  A function
-  specified as being a generic function will certainly be so; if user methods
-  are permitted on the generic function then this will be specified.
-
-\item Where a class precedence list is specified, either explicitly or
-  implicitly by a class hierarchy, the implementation may include additional
-  superclasses not specified here.  Such additional superclasses will not
-  affect the order of specified classes in the class precedence lists either
-  of specified classes themselves or of user-defined subclasses of specified
-  classes.
-
-\item Unless otherwise specified, generic functions use the standard method
-  combination.
-
-\item The specifications for methods are frequently brief; they should be
-  read in conjunction with and in the context of the specification for the
-  generic function and specializing classes, if any.
-
-\item An object $o$ is a \emph{direct instance} of a class $c$ if @|(eq
-  (class-of $o$) $c$)|; $o$ is an \emph{instance} of $c$ if it is a direct
-  instance of any subclass of $c$.
-
-\item If a class is specified as being \emph{abstract} then it is an error to
-  construct direct instances of it, e.g., using @|make-instance|.
-
-\item If an object is specified as being \emph{immutable} then it is an error
-  to mutate it, e.g., using @|(setf (slot-value \ldots) \ldots)|.  Programs
-  may rely on immutable objects retaining their state.
-
-\item A value is \emph{fresh} if it is guaranteed to be not @|eql| to any
-  previously existing value.
-
-\item Unless otherwise specified, it is an error to change the class of an
-  instance of any class described here; and it is an error to change the
-  class of an object to a class described here.
-
-\end{itemize}
-
-\subsection{Format of the entries} \label{sec:proto.conventions.format}
-
-Most symbols defined by the protocol have their own entries.  An entry begins
-with a header line, showing a synopsis of the symbol on the left, and the
-category (function, class, macro, etc.) on the right.
-
-\begin{describe}{fun}{example-function @<required>
-    \&optional @<optional>
-    \&rest @<rest>
-    \&key :keyword}
-  The synopsis for a function, generic function or method describes the
-  function's lambda-list using the usual syntax.  Note that keyword arguments
-  are shown by naming their keywords; in the description, the value passed
-  for the keyword argument @|keyword| is shown as @<keyword>.
-
-  For a method, specializers are shown using the usual @|defmethod| syntax,
-  e.g.,
-  \begin{quote}
-    some-generic-function ((@<specialized> list) @<unspecialized>)
-  \end{quote}
-\end{describe}
-
-\begin{describe}{mac}{example-macro
-  ( @{ @<symbol> @! (@<symbol> @<form>) @}^* ) \\ \push
-    @[[ @<declaration>^* @! @<documentation-string> @]] \\
-    @<body-form>^*}
-  The synopsis for a macro describes the acceptable syntax using the
-  following notation.
-  \begin{itemize}
-  \item Literal symbols, e.g., keywords and parenthesis, are shown in
-    @|monospace|.
-  \item Metasyntactic variables are shown in @<italics>.
-  \item Items are grouped together by braces `@{ $\dots$ @}'.  The notation
-    `@{ $\dots$ @}^*' indicates that the enclosed items may be repeated zero
-    or more times; `@{ $\dots$ @}^+' indicates that the enclosed items may be
-    repeated one or more times.  This notation may be applied to a single
-    item without the braces.
-  \item Optional items are shown enclosed in brackets `@[ $\dots$ @]'.
-  \item Alternatives are separated by vertical bars `@!'; the vertical bar
-    has low precedence, so alternatives extend as far as possible between
-    bars and up to the enclosing brackets if any.
-  \item A sequence of alternatives enclosed in double-brackets `@[[ $\ldots$
-    @]]' indicates that the alternatives may occur in any order, but each may
-    appear at most once unless marked by a star.
-  \end{itemize}
-  For example, the notation at the head of this example describes syntax
-  for @|let|.
-\end{describe}
-
-
-\begin{describe}{cls}{example-class (direct-super other-direct-super) \&key
-    :initarg}
-  The synopsis for a class lists the class's direct superclasses, and the
-  acceptable initargs in the form of a lambda-list.  The initargs may be
-  passed to @|make-instance| when constructing an instance of the class or a
-  subclass of it.  If instances of the class may be reinitialized, or if
-  objects can be changed to be instances of the class, then these initargs
-  may also be passed to @|reinitialize-instance| and/or @|change-class| as
-  applicable; the class description will state explicitly when these
-  operations are allowed.
-\end{describe}
+\chapter{C language utilities} \label{ch:clang}
 
 %%%--------------------------------------------------------------------------
-\section{C type representation} \label{sec:proto.c-types}
+\section{C type representation} \label{sec:clang.c-types}
 
-\subsection{Overview} \label{sec:proto.c-types.over}
+\subsection{Overview} \label{sec:clang.c-types.over}
 
 The Sod translator represents C types in a fairly simple and direct way.
 However, because it spends a fair amount of its time dealing with C types, it
 provides a number of useful operations and macros.
 
-The class hierarchy is shown in~\xref{fig:proto.c-types}.
+The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}.
 
 \begin{figure} \centering
   \parbox{10pt}{\begin{tabbing}
-    @|c-type| \\ \push
-      @|qualifiable-c-type| \\ \push
-        @|simple-c-type| \\ \push
+    @|c-type| \\ \ind
+      @|qualifiable-c-type| \\ \ind
+        @|simple-c-type| \\ \ind
           @|c-class-type| \- \\
-        @|tagged-c-type| \\ \push
+        @|tagged-c-type| \\ \ind
           @|c-struct-type| \\
           @|c-union-type| \\
           @|c-enum-type| \- \\
@@ -192,7 +51,7 @@ The class hierarchy is shown in~\xref{fig:proto.c-types}.
       @|c-function-type|
   \end{tabbing}}
   \caption{Classes representing C types}
-\label{fig:proto.c-types}
+\label{fig:codegen.c-types.classes}
 \end{figure}
 
 C type objects are immutable unless otherwise specified.
@@ -229,7 +88,7 @@ similar names.
 Neither generic function defines a default primary method; subclasses of
 @|c-type| must define their own methods in order to print correctly.
 
-\subsection{The C type root class} \label{sec:proto.c-types.root}
+\subsection{The C type root class} \label{sec:clang.c-types.root}
 
 \begin{describe}{cls}{c-type ()}
   The class @|c-type| marks the root of the built-in C type hierarchy.
@@ -241,7 +100,7 @@ Neither generic function defines a default primary method; subclasses of
   The class @|c-type| is abstract.
 \end{describe}
 
-\subsection{C type S-expression notation} \label{sec:proto.c-types.sexp}
+\subsection{C type S-expression notation} \label{sec:clang.c-types.sexp}
 
 The S-expression representation of a type is described syntactically as a
 type specifier.  Type specifiers fit into two syntactic categories.
@@ -255,13 +114,14 @@ type specifier.  Type specifiers fit into two syntactic categories.
   arguments to the type operator.
 \end{itemize}
 
-\begin{describe}{mac}{c-type @<type-spec> @to @<type>}
+\begin{describe}{mac}{c-type @<type-spec> @> @<c-type>}
   Evaluates to a C type object, as described by the type specifier
   @<type-spec>.
 \end{describe}
 
-\begin{describe}{mac}{
-    defctype @{ @<name> @! (@<name>^*) @} @<type-spec> @to @<names>}
+\begin{describe}{mac}
+    {defctype @{ @<name> @! (@<name> @<nickname>^*) @} @<type-spec>
+      @> @<names>}
   Defines a new symbolic type specifier @<name>; if a list of @<name>s is
   given, then all are defined in the same way.  The type constructed by using
   any of the @<name>s is as described by the type specifier @<type-spec>.
@@ -271,16 +131,14 @@ type specifier.  Type specifiers fit into two syntactic categories.
   @<name> is used in a type specifier.
 \end{describe}
 
-\begin{describe}{mac}{c-type-alias @<original> @<alias>^* @to @<aliases>}
+\begin{describe}{mac}{c-type-alias @<original> @<alias>^* @> @<aliases>}
   Defines each @<alias> as being a type operator identical in behaviour to
   @<original>.  If @<original> is later redefined then the behaviour of the
   @<alias>es changes too.
 \end{describe}
 
-\begin{describe}{mac}{%
-  define-c-type-syntax @<name> @<lambda-list> \\ \push
-    @<form>^* \-\\
-  @to @<name>}
+\begin{describe}{mac}
+    {define-c-type-syntax @<name> @<lambda-list> @<form>^* @> @<name>}
   Defines the symbol @<name> as a new type operator.  When a list of the form
   @|(@<name> @<argument>^*)| is used as a type specifier, the @<argument>s
   are bound to fresh variables according to @<lambda-list> (a destructuring
@@ -292,12 +150,12 @@ type specifier.  Type specifiers fit into two syntactic categories.
   type specifiers among its arguments.
 \end{describe}
 
-\begin{describe}{fun}{expand-c-type-spec @<type-spec> @to @<form>}
+\begin{describe}{fun}{expand-c-type-spec @<type-spec> @> @<form>}
   Returns the Lisp form that @|(c-type @<type-spec>)| would expand into.
 \end{describe}
 
-\begin{describe}{gf}{%
-    print-c-type @<stream> @<type> \&optional @<colon> @<atsign>}
+\begin{describe}{gf}
+    {print-c-type @<stream> @<type> \&optional @<colon> @<atsign>}
   Print the C type object @<type> to @<stream> in S-expression form.  The
   @<colon> and @<atsign> arguments may be interpreted in any way which seems
   appropriate: they are provided so that @|print-c-type| may be called via
@@ -308,14 +166,15 @@ type specifier.  Type specifiers fit into two syntactic categories.
   default method.
 \end{describe}
 
-\subsection{Comparing C types} \label{sec:proto.c-types.cmp}
+\subsection{Comparing C types} \label{sec:clang.c-types.cmp}
 
 It is necessary to compare C types for equality, for example when checking
 argument lists for methods.  This is done by @|c-type-equal-p|.
 
-\begin{describe}{gf}{c-type-equal-p @<type>_1 @<type>_2 @to @<boolean>}
-  The generic function @|c-type-equal-p| compares two C types @<type>_1 and
-  @<type>_2 for equality; it returns true if the two types are equal and
+\begin{describe}{gf}
+    {c-type-equal-p @<c-type>_1 @<c-type>_2 @> @<generalized-boolean>}
+  The generic function @|c-type-equal-p| compares two C types @<c-type>_1 and
+  @<c-type>_2 for equality; it returns true if the two types are equal and
   false if they are not.
 
   Two types are equal if they are structurally similar, where this property
@@ -324,24 +183,24 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
 
   The generic function @|c-type-equal-p| uses the @|and| method combination.
 
-  \begin{describe}{meth}{c-type-equal-p @<type>_1 @<type>_2}
+  \begin{describe}{meth}{c-type-equal-p @<c-type>_1 @<c-type>_2}
     A default primary method for @|c-type-equal-p| is defined.  It simply
     returns @|nil|.  This way, methods can specialize on both arguments
     without fear that a call will fail because no methods are applicable.
   \end{describe}
-  \begin{describe}{ar-meth}{c-type-equal-p @<type>_1 @<type>_2}
+  \begin{describe}{ar-meth}{c-type-equal-p @<c-type>_1 @<c-type>_2}
     A default around-method for @|c-type-equal-p| is defined.  It returns
-    true if @<type>_1 and @<type>_2 are @|eql|; otherwise it delegates to the
-    primary methods.  Since several common kinds of C types are interned,
+    true if @<c-type>_1 and @<c-type>_2 are @|eql|; otherwise it delegates to
+    the primary methods.  Since several common kinds of C types are interned,
     this is a common case worth optimizing.
   \end{describe}
 \end{describe}
 
-\subsection{Outputting C types} \label{sec:proto.c-types.output}
+\subsection{Outputting C types} \label{sec:clang.c-types.output}
 
-\begin{describe}{gf}{pprint-c-type @<type> @<stream> @<kernel>}
+\begin{describe}{gf}{pprint-c-type @<c-type> @<stream> @<kernel>}
   The generic function @|pprint-c-type| pretty-prints to @<stream> a C-syntax
-  declaration of an object or function of type @<type>.  The result is
+  declaration of an object or function of type @<c-type>.  The result is
   written to @<stream>.
 
   A C declaration has two parts: a sequence of \emph{declaration specifiers}
@@ -386,7 +245,7 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   Every concrete subclass of @|c-type| is expected to provide a primary
   method on this function.  There is no default primary method.
 
-  \begin{describe}{ar-meth}{pprint-c-type @<type> @<stream> @<kernel>}
+  \begin{describe}{ar-meth}{pprint-c-type @<c-type> @<stream> @<kernel>}
     A default around method is defined on @|pprint-c-type| which `canonifies'
     non-function @<kernel> arguments.  In particular:
     \begin{itemize}
@@ -405,9 +264,8 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   specifiers.  The precise details are subject to change.
 \end{describe}
 
-\begin{describe}{mac}{%
-  maybe-in-parens (@<stream-var> @<guard-form>) \\ \push
-    @<form>^*}
+\begin{describe}{mac}
+    {maybe-in-parens (@<stream-var> @<guard-form>) @<form>^*}
   The @<guard-form> is evaluated, and then the @<form>s are evaluated in
   sequence within a pretty-printer logical block writing to the stream named
   by the symbol @<stream-var>.  If the @<guard-form> evaluates to nil, then
@@ -420,7 +278,7 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
 \end{describe}
 
 \subsection{Type qualifiers and qualifiable types}
-\label{sec:proto.ctypes.qual}
+\label{sec:clang.ctypes.qual}
 
 \begin{describe}{cls}{qualifiable-c-type (c-type) \&key :qualifiers}
   The class @|qualifiable-c-type| describes C types which can bear
@@ -438,18 +296,18 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   The class @|qualifiable-c-type| is abstract.
 \end{describe}
 
-\begin{describe}{gf}{c-type-qualifiers @<type> @to @<list>}
-  Returns the qualifiers of the @|qualifiable-c-type| instance @<type> as an
-  immutable list.
+\begin{describe}{gf}{c-type-qualifiers @<c-type> @> @<list>}
+  Returns the qualifiers of the @|qualifiable-c-type| instance @<c-type> as
+  an immutable list.
 \end{describe}
 
-\begin{describe}{fun}{qualify-type @<type> @<qualifiers>}
-  The argument @<type> must be an instance of @|qualifiable-c-type|,
+\begin{describe}{fun}{qualify-type @<c-type> @<qualifiers> @> @<c-type>}
+  The argument @<c-type> must be an instance of @|qualifiable-c-type|,
   currently bearing no qualifiers, and @<qualifiers> a list of qualifier
   keywords.  The result is a C type object like @<c-type> except that it
   bears the given @<qualifiers>.
 
-  The @<type> is not modified.  If @<type> is interned, then the returned
+  The @<c-type> is not modified.  If @<c-type> is interned, then the returned
   type will be interned.
 \end{describe}
 
@@ -459,7 +317,7 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   non-null then the final character of the returned string will be a space.
 \end{describe}
 
-\subsection{Leaf types} \label{sec:proto.c-types.leaf}
+\subsection{Leaf types} \label{sec:clang.c-types.leaf}
 
 A \emph{leaf type} is a type which is not defined in terms of another type.
 In Sod, the leaf types are
@@ -484,58 +342,59 @@ In Sod, the leaf types are
   and matching qualifiers.
 
   A number of symbolic type specifiers for builtin types are predefined as
-  shown in \xref{tab:proto.c-types.simple}.  These are all defined as if by
+  shown in \xref{tab:codegen.c-types.simple}.  These are all defined as if by
   @|define-simple-c-type|, so can be used to construct qualified types.
 \end{describe}
 
 \begin{table}
-  \begin{tabular}[C]{|l|l|}                                        \hlx{hv}
-    \textbf{C type}     & \textbf{Specifiers}                   \\ \hlx{vhv}
-    @|void|             & @|void|                               \\ \hlx{vhv}
+  \begin{tabular}[C]{ll}                                           \hlx*{hv}
+    \thd{C type}        & \thd{Specifiers}                      \\ \hlx{vhv}
+    @|void|             & @|void|                               \\ \hlx{v}
     @|char|             & @|char|                               \\ \hlx{v}
-    @|unsigned char|    & @|unsigned-char|, @|uchar|            \\ \hlx{v}
-    @|signed char|      & @|signed-char|, @|schar|              \\ \hlx{vhv}
+    @|unsigned char|    & @|unsigned-char|, @|uchar|            \\ \hlx{}
+    @|signed char|      & @|signed-char|, @|schar|              \\ \hlx{v}
     @|short|            & @|short|, @|signed-short|, @|short-int|,
-                          @|signed-short-int| @|sshort|         \\ \hlx{v}
+                          @|signed-short-int| @|sshort|         \\ \hlx{}
     @|unsigned short|   & @|unsigned-short|, @|unsigned-short-int|,
-                          @|ushort|                             \\ \hlx{vhv}
+                          @|ushort|                             \\ \hlx{v}
     @|int|              & @|int|, @|signed|, @|signed-int|,
-                          @|sint|                               \\ \hlx{v}
-    @|unsigned int|     & @|unsigned|, @|unsigned-int|, @|uint| \\ \hlx{vhv}
+                          @|sint|                               \\ \hlx{}
+    @|unsigned int|     & @|unsigned|, @|unsigned-int|, @|uint| \\ \hlx{v}
     @|long|             & @|long|, @|signed-long|, @|long-int|,
-                          @|signed-long-int|, @|slong|          \\ \hlx{v}
+                          @|signed-long-int|, @|slong|          \\ \hlx{}
     @|unsigned long|    & @|unsigned-long|, @|unsigned-long-int|,
-                          @|ulong|                              \\ \hlx{vhv}
+                          @|ulong|                              \\ \hlx{v}
     @|long long|        & @|long-long|, @|signed-long-long|,
                           @|long-long-int|,                     \\
                         & \qquad @|signed-long-long-int|,
                           @|llong|, @|sllong|                   \\ \hlx{v}
     @|unsigned long long|
                         & @|unsigned-long-long|, @|unsigned-long-long-int|,
-                          @|ullong|                             \\ \hlx{vhv}
-    @|float|            & @|float|                              \\ \hlx{v}
-    @|double|           & @|double|                             \\ \hlx{vhv}
+                          @|ullong|                             \\ \hlx{v}
+    @|float|            & @|float|                              \\ \hlx{}
+    @|double|           & @|double|                             \\ \hlx{v}
     @|va_list|          & @|va-list|                            \\ \hlx{v}
     @|size_t|           & @|size-t|                             \\ \hlx{v}
-    @|ptrdiff_t|        & @|ptrdiff-t|                          \\ \hlx{vh}
+    @|ptrdiff_t|        & @|ptrdiff-t|                          \\ \hlx*{vh}
   \end{tabular}
   \caption{Builtin symbolic type specifiers for simple C types}
-  \label{tab:proto.c-types.simple}
+  \label{tab:codegen.c-types.simple}
 \end{table}
 
-\begin{describe}{fun}{make-simple-type @<name> \&optional @<qualifiers>}
+\begin{describe}{fun}
+    {make-simple-type @<name> \&optional @<qualifiers> @> @<c-type>}
   Return the (unique interned) simple C type object for the C type whose name
   is @<name> (a string) and which has the given @<qualifiers> (a list of
   keywords).
 \end{describe}
 
-\begin{describe}{gf}{c-type-name @<type>}
-  Returns the name of a @|simple-c-type| instance @<type> as an immutable
+\begin{describe}{gf}{c-type-name @<c-type> @> @<string>}
+  Returns the name of a @|simple-c-type| instance @<c-type> as an immutable
   string.
 \end{describe}
 
-\begin{describe}{mac}{%
-    define-simple-c-type @{ @<name> @! (@<name>^*) @} @<string>}
+\begin{describe}{mac}
+    {define-simple-c-type @{ @<name> @! (@<name>^*) @} @<string> @> @<name>}
   Define type specifiers for a new simple C type.  Each symbol @<name> is
   defined as a symbolic type specifier for the (unique interned) simple C
   type whose name is the value of @<string>.  Further, each @<name> is
@@ -560,13 +419,22 @@ In Sod, the leaf types are
   structs and unions.
 \end{boxy}
 
-\begin{describe}{gf}{c-tagged-type-kind @<type>}
-  Returns a symbol classifying the tagged @<type>: one of @|enum|, @|struct|
-  or @|union|.  User-defined subclasses of @|tagged-c-type| should return
-  their own classification symbols.  It is intended that @|(string-downcase
-  (c-tagged-type-kind @<type>))| be valid C syntax.\footnote{%
+\begin{describe}{gf}{c-tagged-type-kind @<c-type> @> @<keyword>}
+  Returns a keyword classifying the tagged @<c-type>: one of @|:enum|,
+  @|:struct| or @|:union|.  User-defined subclasses of @|tagged-c-type|
+  should return their own classification symbols.  It is intended that
+  @|(string-downcase (c-tagged-type-kind @<c-type>))| be valid C
+  syntax.\footnote{%
     Alas, C doesn't provide a syntactic category for these keywords;
     \Cplusplus\ calls them a @<class-key>.} %
+  There is a method defined for each of the built-in tagged type classes
+  @|c-struct-type|, @|c-union-type| and @|c-enum-type|.
+\end{describe}
+
+\begin{describe}{gf}{kind-c-tagged-type @<keyword> @> @<symbol>}
+  This is not quite the inverse of @|c-tagged-type-kind|.  Given a keyword
+  naming a kind of tagged type, return the name of the corresponding C
+  type class as a symbol.
 \end{describe}
 
 \begin{describe}{cls}{c-enum-type (tagged-c-type) \&key :qualifiers :tag}
@@ -577,7 +445,8 @@ In Sod, the leaf types are
   interned) enumerated type with the given @<tag> and @<qualifier>s (all
   evaluated).
 \end{describe}
-\begin{describe}{fun}{make-enum-type @<tag> \&optional @<qualifiers>}
+\begin{describe}{fun}
+    {make-enum-type @<tag> \&optional @<qualifiers> @> @<c-enum-type>}
   Return the (unique interned) C type object for the enumerated C type whose
   tag is @<tag> (a string) and which has the given @<qualifiers> (a list of
   keywords).
@@ -591,7 +460,8 @@ In Sod, the leaf types are
   interned) structured type with the given @<tag> and @<qualifier>s (all
   evaluated).
 \end{describe}
-\begin{describe}{fun}{make-struct-type @<tag> \&optional @<qualifiers>}
+\begin{describe}{fun}
+    {make-struct-type @<tag> \&optional @<qualifiers> @> @<c-struct-type>}
   Return the (unique interned) C type object for the structured C type whose
   tag is @<tag> (a string) and which has the given @<qualifiers> (a list of
   keywords).
@@ -606,24 +476,31 @@ In Sod, the leaf types are
   interned) union type with the given @<tag> and @<qualifier>s (all
   evaluated).
 \end{describe}
-\begin{describe}{fun}{make-union-type @<tag> \&optional @<qualifiers>}
+\begin{describe}{fun}
+    {make-union-type @<tag> \&optional @<qualifiers> @> @<c-union-type>}
   Return the (unique interned) C type object for the union C type whose tag
   is @<tag> (a string) and which has the given @<qualifiers> (a list of
   keywords).
 \end{describe}
 
-\subsection{Pointers and arrays} \label{sec:proto.c-types.ptr-array}
+\subsection{Compound C types} \label{sec:code.c-types.compound}
+
+Some C types are \emph{compound types}: they're defined in terms of existing
+types.  The classes which represent compound types implement a common
+protocol.
 
-Pointers and arrays are \emph{compound types}: they're defined in terms of
-existing types.  A pointer describes the type of objects it points to; an
-array describes the type of array element.
-\begin{describe}{gf}{c-type-subtype @<type>}
-  Returns the underlying type of a compound type @<type>.  Precisely what
-  this means depends on the class of @<type>.
+\begin{describe}{gf}{c-type-subtype @<c-type> @> @<subtype>}
+  Returns the underlying type of a compound type @<c-type>.  Precisely what
+  this means depends on the class of @<c-type>.
 \end{describe}
 
-\begin{describe}{cls}{c-pointer-type (qualifiable-c-type)
-    \&key :qualifiers :subtype}
+\subsection{Pointer types} \label{sec:clang.c-types.pointer}
+
+Pointers compound types.  The subtype of a pointer type is the type it points
+to.
+
+\begin{describe}{cls}
+    {c-pointer-type (qualifiable-c-type) \&key :qualifiers :subtype}
   Represents a C pointer type.  An instance denotes the C type @<subtype>
   @|*|@<qualifiers>.
 
@@ -636,16 +513,24 @@ array describes the type of array element.
   evaluated).  The synonyms @|ptr| and @|pointer| may be used in place of the
   star @`*'.
 
-  The symbol @|string| is a type specifier for the type of pointer to
+  The symbol @|string| is a type specifier for the type pointer to
   characters; the symbol @|const-string| is a type specifier for the type
   pointer to constant characters.
 \end{describe}
-\begin{describe}{fun}{make-pointer-type @<subtype> \&optional @<qualifiers>}
-  Return an object describing the type of qualified pointers to @<subtype>.
+
+\begin{describe}{fun}
+    {make-pointer-type @<c-type> \&optional @<qualifiers>
+      @> @<c-pointer-type>}
+  Return an object describing the type qualified pointer to @<subtype>.
   If @<subtype> is interned, then the returned pointer type object is
   interned also.
 \end{describe}
 
+\subsection{Array types} \label{sec:clang.c-types.array}
+
+Arrays implement the compound-type protocol.  The subtype of an array type is
+the array element type.
+
 \begin{describe}{cls}{c-array-type (c-type) \&key :subtype :dimensions}
   Represents a multidimensional C array type.  The @<dimensions> are a list
   of dimension specifiers $d_0$, $d_1$, \ldots, $d_{n-1}$; an instance then
@@ -669,23 +554,380 @@ array describes the type of array element.
   single-dimensional array with unspecified extent.  The synonyms @|array|
   and @|vector| may be used in place of the brackets @`[]'.
 \end{describe}
-\begin{describe}{fun}{make-array-type @<subtype> @<dimensions>}
+
+\begin{describe}{fun}
+    {make-array-type @<subtype> @<dimensions> @> @<c-array-type>}
   Return an object describing the type of arrays with given @<dimensions> and
   with element type @<subtype> (an instance of @|c-type|).  The @<dimensions>
   argument is a list whose elements are strings or nil; see the description
   of the class @|c-array-type| above for details.
 \end{describe}
-\begin{describe}{gf}{c-array-dimensions @<type>}
-  Returns the dimensions of @<type>, an array type, as an immutable list.
+
+\begin{describe}{gf}{c-array-dimensions @<c-type> @> @<list>}
+  Returns the dimensions of @<c-type>, an array type, as an immutable list.
+\end{describe}
+
+\subsection{Function types} \label{sec:clang.c-types.fun}
+
+Function types implement the compound-type protocol.  The subtype of a
+function type is the type of the function's return value.
+
+\begin{describe}{cls}{argument}
+  Represents an ordinary function argument.
+\end{describe}
+
+\begin{describe}{fun}{argumentp @<value> @> @<generalized-boolean>}
+  Decide whether @<value> is an @<argument> object: if so, return non-nil; if
+  not return nil.
+\end{describe}
+
+\begin{describe}{fun}{make-argument @<name> @<c-type> @> @<argument>}
+  Construct and a return a new @<argument> object.  The argument has type
+  @<c-type>, which must be a @|c-type| object, and is named @<name>.
+
+  The @<name> may be nil to indicate that the argument has no name: in this
+  case the argument will be formatted as an abstract declarator, which is not
+  suitable for function definitions.  If @<name> is not nil, then the
+  @<name>'s print representation, with @|*print-escape*| nil, is used as the
+  argument name.
+\end{describe}
+
+\begin{describe}{fun}{argument-name @<argument> @> @<name>}
+  Return the name of the @<argument>, as it was supplied to @|make-argument|.
+\end{describe}
+
+\begin{describe}{fun}{argument-type @<argument> @> @<c-type>}
+  Return the type of the @<argument>, as it was supplied to @|make-argument|.
+\end{describe}
+
+\begin{describe}{gf}
+    {commentify-argument-name @<name> @> @<commentified-name>}
+  Convert the argument name @<name> so that it's suitable to declare the
+  function in a header file.
+
+  Robust header files shouldn't include literal argument names in
+  declarations of functions or function types, since this restricts the
+  including file from defining such names as macros.  This generic function
+  is used to convert names into a safe form.
+
+  \begin{describe}{meth}{commentify-argument-name (@<name> null) @> nil}
+    Returns nil: if the argument name is already omitted, it's safe for use
+    in a header file.
+  \end{describe}
+  \begin{describe}{meth}{commentify-argument-name (@<name> t) @> @<string>}
+    Returns the print form of @<name> wrapped in a C comment, as
+    @`/*@<name>*/'.
+  \end{describe}
 \end{describe}
 
-\subsection{Function types} \label{sec:proto.c-types.fun}
+\begin{describe}{fun}
+    {commentify-argument-names @<arguments> @> @<commentified-arguments>}
+  Convert the @<arguments> list so that it's suitable for use in a header
+  file.
+
+  The @<arguments> list should be a list whose items are @|argument| objects
+  or the keyword @|:ellipsis|.  The return value is a list constructed as
+  follows.  For each @|argument| object in the input list, there is a
+  corresponding @|argument| object in the returned list, with the same type,
+  and whose name is the result of @|commentify-argument-name| applied to the
+  input argument name; an @|:ellipsis| in the input list is passed through
+  unchanged.
+\end{describe}
 
 \begin{describe}{cls}{c-function-type (c-type) \&key :subtype :arguments}
-  Represents C function types.  An instance denotes the C type of a C
-  function which 
+  Represents C function types.  An instance denotes the type of a C
+  function which accepts the @<arguments> and returns @<subtype>.
+
+  The @<arguments> are a possibly empty list.  All but the last element of
+  the list must be @|argument| objects; the final element may instead be the
+  keyword @|:ellipsis|, which denotes a variable argument list.
+
+  An @<arguments> list consisting of a single argument with type @|void| is
+  converted into an empty list.  On output as C code, an empty argument list
+  is written as @|void|.  It is not possible to represent a pre-ANSI C
+  function without prototypes.
+
+  Two function types are considered to be the same if their return types are
+  the same, and their argument lists consist of arguments with the same type,
+  in the same order, and either both or neither argument list ends with
+  @|:ellipsis|; argument names are not compared.
+
+  The type specifier @|(fun @<return-type> @{ (@<arg-name> @<arg-type>) @}^*
+  @[:ellipsis @! . @<form> @])| constructs a function type.  The function has
+  the subtype @<return-type>.  The remaining items in the type-specifier list
+  are used to construct the argument list.  The argument items are a possibly
+  improper list, beginning with zero or more \emph{explicit arguments}:
+  two-item @<arg-name>/@<arg-type> lists.  For each such list, an @|argument|
+  object is constructed with the given name (evaluated) and type.  Following
+  the explicit arguments, there may be
+  \begin{itemize}
+  \item nothing, in which case the function's argument list consists only of
+    the explicit arguments;
+  \item the keyword @|:ellipsis|, as the final item in the type-specifier
+    list, indicating a variable argument list may follow the explicit
+    arguments; or
+  \item a possibly-improper list tail, beginning with an atom either as a
+    list item or as the final list cdr, indicating that the entire list tail
+    is Lisp expression which is to be evaluated to compute the remaining
+    arguments.
+  \end{itemize}
+  A tail expression may return a list of @|argument| objects, optionally
+  followed by an @|:ellipsis|.
+
+  For example,
+  \begin{prog}
+    (c-type (fun \=(lisp (c-type-subtype other-func)) \+ \\
+                   ("first" int) . (c-function-arguments other-func))
+  \end{prog}
+  evaluates to a function type like @|other-func|, only with an additional
+  argument of type @|int| added to the front of its argument list.  This
+  could also have been written
+  \begin{prog}
+    (let (\=(args (c-function-arguments other-func)) \+ \\
+            (ret (c-type-subtype other-func))) \- \\ \ind
+      (c-type (fun \=(lisp ret) ("first" int) . args)
+  \end{prog}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-function-type @<subtype> @<arguments> @> @<c-function-type>}
+  Construct and return a new function type, returning @<subtype> and
+  accepting the @<arguments>.
+\end{describe}
+
+\begin{describe}{gf}
+    {c-function-arguments @<c-function-type> @> @<arguments>}
+  Return the arguments list of the @<c-function-type>.
+\end{describe}
+
+\begin{describe}{fun}
+    {commentify-function-type @<c-function-type> @> @<commentified-c-type>}
+  Return a commentified version of the @<c-function-type>.
+
+  The returned type has the same subtype as the given type, and the argument
+  list of the returned type is the result of applying
+  @|commentify-argument-names| to the argument list of the given type.
+\end{describe}
+
+\subsection{Parsing C types} \label{sec:clang.c-types.parsing}
+
+%%%--------------------------------------------------------------------------
+\section{Generating C code} \label{sec:clang.codegen}
+
+This section deals with Sod's facilities for constructing and manipulating C
+expressions, declarations, instructions and definitions.
+
+\subsection{Temporary names} \label{sec:clang.codegen.temporaries}
+
+Many C-level objects, especially ones with external linkage or inclusion in a
+header file, are assigned names which are simple strings, perhaps fixed ones,
+perhaps constructed.  Other objects don't need meaningful names, and
+suitably unique constructed names would be tedious and most likely rather
+opaque.  Therefore Sod has an ability to construct \emph{temporary names}.
+
+These aren't temporary in the sense that they name C objects which have
+limited lifetimes at runtime.  Rather, the idea is that the names be
+significant only to small pieces of Lisp code, which will soon forget about
+them.
+
+\subsubsection{The temporary name protocol}
+Temporary names are represented by objects which implement a simple protocol.
+
+\begin{describe}{gf}{format-temporary-name @<var> @<stream>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{gf}{var-in-use-p @<var> @> @<generalized-boolean>}
+     \dhead[setf var-in-use-p]
+       {gf}{setf (var-in-use-p @<var>) @<generalized-boolean>}}
+\end{describe*}
+
+\subsubsection{Temporary name objects}
+
+\begin{describe}{cls}{temporary-name () \&key :tag}
+  A temporary name object.  This is the root of a small collection of
+  subclasses, but is also usable on its own.
+\end{describe}
+
+\begin{describe}{meth}
+    {commentify-argument-name (@<name> temporary-name) @> nil}
+\end{describe}
+
+\begin{table}
+  \begin{tabular}[C]{*2{>{\codeface}l}}                            \hlx*{hv}
+    \thd{\textbf{Class}} & \thd{\textbf{Name format}}           \\ \hlx{vhv}
+    temporary-name              & @<tag>                        \\
+    temporary-argument          & sod__a@<tag>                  \\
+    temporary-function          & sod__f@<tag>                  \\
+    temporary-variable          & sod__v@<tag>                  \\ \hlx*{vh}
+  \end{tabular}
+  \caption{Temporary name formats}
+  \label{tab:codegen.codegen.temps-format}
+\end{table}
+
+\begin{describe}{cls}{temporary-argument (temporary-name) \&key :tag}
+\end{describe}
+
+\begin{describe}{cls}{temporary-function (temporary-name) \&key :tag}
+\end{describe}
+
+\begin{describe}{fun}{temporary-function @> @<name>}
+\end{describe}
+
+\begin{describe}{cls}
+    {temporary-variable (temporary-name) \&key :tag :in-use-p}
+\end{describe}
+
+\subsubsection{Well-known `temporary' names}
+
+\begin{table}
+  \begin{tabular}[C]{*2{>{\codeface}l}}                            \hlx*{hv}
+    \thd{\textbf{Variable}} & \thd{\textbf{Name format}}        \\ \hlx{vhv}
+    {}*sod-ap*                  & sod__ap                       \\
+    {}*sod-master-ap*           & sod__master_ap                \\
+    {}*sod-tmp-ap*              & sod__tmp_ap                   \\ \hlx*{vh}
+  \end{tabular}
+  \caption{Well-known temporary names}
+  \label{tab:codegen.codegen.well-known-temps}
+\end{table}
+
+\subsection{Instructions} \label{sec:clang.codegen.insts}
+
+\begin{describe}{cls}{inst () \&key}
+\end{describe}
+
+\begin{describe}{gf}{inst-metric @<inst>}
+\end{describe}
+
+\begin{describe}{mac}
+    {definst @<code> (@<streamvar> \&key @<export>) (@<arg>^*)
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {format-compound-statement (@<stream> @<child> \&optional @<morep>)
+      @<body-form>^*}
+\end{describe}
+
+\begin{table}
+  \begin{tabular}[C]{ll>{\codeface}l}                              \hlx*{hv}
+    \thd{Class name} &
+    \thd{Arguments} &
+    \thd{Output format}                                         \\ \hlx{vhv}
+    @|var|      & @<name> @<type> @<init>  & @<type> @<name> @[= @<init>@];
+                                                                \\ \hlx{v}
+    @|set|      & @<var> @<expr>           & @<var> = @<expr>;  \\ \hlx{v}
+    @|update|   & @<var> @<op> @<expr>     & @<var> @<op>= @<expr>;
+                                                                \\ \hlx{v}
+    @|return|   & @<expr>                  & return @[@<expr>@];
+                                                                \\ \hlx{v}
+    @|break|    & ---                      & break;             \\ \hlx{v}
+    @|continue| & ---                      & continue;          \\ \hlx{v}
+    @|expr|     & @<expr>                  & @<expr>;           \\ \hlx{v}
+    @|call|     & @<func> @<args>          & @<func>(@<arg>_1,
+                                                     $\ldots$,
+                                                     @<arg>_n)  \\ \hlx{v}
+    @|va-start| & @<ap> @<arg>             & va_start(@<ap>, @<arg>);
+                                                                \\ \hlx{v}
+    @|va-copy|  & @<to> @<from>            & va_copy(@<to>, @<from>);
+                                                                \\ \hlx{v}
+    @|va-end|   & @<ap>                    & va_end(@<ap>);     \\ \hlx{vhv}
+    @|block|    & @<decls> @<body>         & \{ @[@<decls>@] @<body> \}
+                                                                \\ \hlx{v}
+    @|if|       & @<cond> @<conseq> @<alt> & if (@<cond>) @<conseq>
+                                             @[else @<alt>@]    \\ \hlx{v}
+    @|while|    & @<cond> @<body>          & while (@<cond>) @<body>
+                                                                \\ \hlx{v}
+    @|do-while| & @<body> @<cond>          & do @<body> while (@<cond>);
+                                                                \\ \hlx{v}
+    @|function| & @<name> @<type> @<body>  &
+      @<type>_0 @<name>(@<type>_1 @<arg>_1, $\ldots$,
+                             @<type>_n @<arg>_n @[, \dots@])
+        @<body>                                                 \\ \hlx*{vh}
+  \end{tabular}
+  \caption{Instruction classes}
+  \label{tab:codegen.codegen.insts}
+\end{table}
+
+\subsection{Code generation} \label{sec:clang.codegen.codegen}
+
+\begin{describe}{gf}{codegen-functions @<codegen> @> @<list>}
+\end{describe}
+
+\begin{describe}{gf}
+    {ensure-var @<codegen> @<name> @<type> \&optional @<init>}
+\end{describe}
+
+\begin{describe}{gf}{emit-inst @<codegen> @<inst>}
+\end{describe}
+
+\begin{describe}{gf}{emit-insts @<codegen> @<insts>}
+\end{describe}
+
+\begin{describe}{gf}{emit-decl @<codegen> @<decl>}
+\end{describe}
+
+\begin{describe}{gf}{emit-declss @<codegen> @<decls>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-push @<codegen>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-pop @<codegen> @> @<decls> @<insts>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-pop-block @<codegen> @> @<block-inst>}
+\end{describe}
+
+\begin{describe}{gf}
+    {codegen-pop-function @<codegen> @<name> @<type> @> @<name>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-add-function @<codegen> @<function>}
+\end{describe}
+
+\begin{describe}{fun}
+    {codegen-build-function @<codegen> @<name> @<type> @<vars> @<insts>
+      @> @<name>}
+\end{describe}
+
+\begin{describe}{gf}{temporary-var @<codegen> @<type> @> @<name>}
+\end{describe}
+
+\begin{describe}{mac}
+    {with-temporary-var (@<codegen> @<var> @<type>) @<body-form>^*
+      @> @<value>^*}
+\end{describe}
+
+\begin{describe}{fun}{deliver-expr @<codegen> @<target> @<expr>}
+\end{describe}
+
+\begin{describe}{fun}{convert-stmts @<codegen> @<target> @<type> @<func>}
+\end{describe}
+
+\begin{describe}{cls}{codegen () \&key :vars :insts (:temp-index 0)}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Literal C code fragments} \label{sec:clang.fragment}
+
+\begin{describe}{cls}{c-fragment () \&key :location :text}
+\end{describe}
+
+\begin{describe}{gf}{c-fragment-text @<fragment> @> @<string>}
+\end{describe}
+
+\begin{describe}{fun}
+    {scan-c-fragment @<scanner> @<end-chars>
+      @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{fun}
+    {parse-delimited-fragment @<scanner> @<begin> @<end> \&key :keep-end
+      \nlret @<result> @<success-flag> @<consumed-flag>}
 \end{describe}
 
+\relax
 %%%----- That's all, folks --------------------------------------------------
 
 %%% Local variables:
diff --git a/doc/concepts.tex b/doc/concepts.tex
new file mode 100644 (file)
index 0000000..d554b51
--- /dev/null
@@ -0,0 +1,42 @@
+%%% -*-latex-*-
+%%%
+%%% Conceptual background
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Concepts}
+
+\section{Classes and slots}
+
+\section{Messages and methods}
+
+\section{Metaclasses}
+
+\section{Modules}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/cutting-room-floor.tex b/doc/cutting-room-floor.tex
new file mode 100644 (file)
index 0000000..c8f241b
--- /dev/null
@@ -0,0 +1,489 @@
+%%% -*-latex-*-
+%%%
+%%% Conceptual background
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Cutting-room floor}
+
+%%%--------------------------------------------------------------------------
+\section{Generated names}
+
+The generated names for functions and objects related to a class are
+constructed systematically so as not to interfere with each other.  The rules
+on class, slot and message naming exist so as to ensure that the generated
+names don't collide with each other.
+
+The following notation is used in this section.
+\begin{description}
+\item[@<class>] The full name of the `focus' class: the one for which we are
+  generating name.
+\item[@<super-nick>] The nickname of a superclass.
+\item[@<head-nick>] The nickname of the chain-head class of the chain
+  in question.
+\end{description}
+
+\subsection{Instance layout}
+
+%%%--------------------------------------------------------------------------
+\section{Class objects}
+
+\begin{listing}
+typedef struct SodClass__ichain_obj SodClass;
+
+struct sod_chain {
+  size_t n_classes;                     /* Number of classes in chain */
+  const SodClass *const *classes;       /* Vector of classes, head first */
+  size_t off_ichain;                    /* Offset of ichain from instance base */
+  const struct sod_vtable *vt;          /* Vtable pointer for chain */
+  size_t ichainsz;                      /* Size of the ichain structure */
+};
+
+struct sod_vtable {
+  SodClass *_class;                     /* Pointer to instance's class */
+  size_t _base;                         /* Offset to instance base */
+};
+
+struct SodClass__islots {
+
+  /* Basic information */
+  const char *name;                     /* The class's name as a string */
+  const char *nick;                     /* The nickname as a string */
+
+  /* Instance allocation and initialization */
+  size_t instsz;                        /* Instance layout size in bytes */
+  void *(*imprint)(void *);             /* Stamp instance with vtable ptrs */
+  void *(*init)(void *);                /* Initialize instance */
+
+  /* Superclass structure */
+  size_t n_supers;                      /* Number of direct superclasses */
+  const SodClass *const *supers;        /* Vector of direct superclasses */
+  size_t n_cpl;                         /* Length of class precedence list */
+  const SodClass *const *cpl;           /* Vector for class precedence list */
+
+  /* Chain structure */
+  const SodClass *link;                 /* Link to next class in chain */
+  const SodClass *head;                 /* Pointer to head of chain */
+  size_t level;                         /* Index of class in its chain */
+  size_t n_chains;                      /* Number of superclass chains */
+  const sod_chain *chains;              /* Vector of chain structures */
+
+  /* Layout */
+  size_t off_islots;                    /* Offset of islots from ichain base */
+  size_t islotsz;                       /* Size of instance slots */
+};
+
+struct SodClass__ichain_obj {
+  const SodClass__vt_obj *_vt;
+  struct SodClass__islots cls;
+};
+
+struct sod_instance {
+  struct sod_vtable *_vt;
+};
+\end{listing}
+
+\begin{listing}
+void *sod_convert(const SodClass *cls, const void *obj)
+{
+  const struct sod_instance *inst = obj;
+  const SodClass *real = inst->_vt->_cls;
+  const struct sod_chain *chain;
+  size_t i, index;
+
+  for (i = 0; i < real->cls.n_chains; i++) {
+    chain = &real->cls.chains[i];
+    if (chain->classes[0] == cls->cls.head) {
+      index = cls->cls.index;
+      if (index < chain->n_classes && chain->classes[index] == cls)
+        return ((char *)cls - inst->_vt._base + chain->off_ichain);
+      else
+        return (0);
+    }
+  }
+  return (0);
+}
+\end{listing}
+
+%%%--------------------------------------------------------------------------
+\section{Classes}
+\label{sec:class}
+
+\subsection{Classes and superclasses} \label{sec:class.defs}
+
+A @<full-class-definition> must list one or more existing classes to be the
+\emph{direct superclasses} for the new class being defined.  We make the
+following definitions.
+\begin{itemize}
+\item The \emph{superclasses} of a class consist of the class itself together
+  with the superclasses of its direct superclasses.
+\item The \emph{proper superclasses} of a class are its superclasses other
+  than itself.
+\item If $C$ is a (proper) superclass of $D$ then $D$ is a (\emph{proper})
+  \emph{subclass} of $C$.
+\end{itemize}
+The predefined class @|SodObject| has no direct superclasses; it is unique in
+this respect.  All classes are subclasses of @|SodObject|.
+
+\subsection{The class precedence list} \label{sec:class.cpl}
+
+Let $C$ be a class.  The superclasses of $C$ form a directed graph, with an
+edge from each class to each of its direct superclasses.  This is the
+\emph{superclass graph of $C$}.
+
+In order to resolve inheritance of items, we define a \emph{class precedence
+  list} (or CPL) for each class, which imposes a total order on that class's
+superclasses.  The default algorithm for computing the CPL is the \emph{C3}
+algorithm \cite{fixme-c3}, though extensions may implement other algorithms.
+
+The default algorithm works as follows.  Let $C$ be the class whose CPL we
+are to compute.  Let $X$ and $Y$ be two of $C$'s superclasses.
+\begin{itemize}
+\item $C$ must appear first in the CPL.
+\item If $X$ appears before $Y$ in the CPL of one of $C$'s direct
+  superclasses, then $X$ appears before $Y$ in the $C$'s CPL.
+\item If the above rules don't suffice to order $X$ and $Y$, then whichever
+  of $X$ and $Y$ has a subclass which appears further left in the list of
+  $C$'s direct superclasses will appear earlier in the CPL.
+\end{itemize}
+This last rule is sufficient to disambiguate because if both $X$ and $Y$ are
+superclasses of the same direct superclass of $C$ then that direct
+superclass's CPL will order $X$ and $Y$.
+
+We say that \emph{$X$ is more specific than $Y$ as a superclass of $C$} if
+$X$ is earlier than $Y$ in $C$'s class precedence list.  If $C$ is clear from
+context then we omit it, saying simply that $X$ is more specific than $Y$.
+
+\subsection{Instances and metaclasses} \label{sec:class.meta}
+
+A class defines the structure and behaviour of its \emph{instances}: run-time
+objects created (possibly) dynamically.  An instance is an instance of only
+one class, though structurally it may be used in place of an instance of any
+of that class's superclasses.  It is possible, with care, to change the class
+of an instance at run-time.
+
+Classes are themselves represented as instances -- called \emph{class
+  objects} -- in the running program.  Being instances, they have a class,
+called the \emph{metaclass}.  The metaclass defines the structure and
+behaviour of the class object.
+
+The predefined class @|SodClass| is the default metaclass for new classes.
+@|SodClass| has @|SodObject| as its only direct superclass.  @|SodClass| is
+its own metaclass.
+
+To make matters more complicated, Sod has \emph{two} distinct metalevels: as
+well as the runtime metalevel, as discussed above, there's a compile-time
+metalevel hosted in the Sod translator.  Since Sod is written in Common Lisp,
+a Sod class's compile-time metaclass is a CLOS class.  The usual compile-time
+metaclass is @|sod-class|.  The compile-time metalevel is the subject of
+\xref{ch:api}.
+
+\subsection{Items and inheritance} \label{sec:class.inherit}
+
+A class definition also declares \emph{slots}, \emph{messages},
+\emph{initializers} and \emph{methods} -- collectively referred to as
+\emph{items}.  In addition to the items declared in the class definition --
+the class's \emph{direct items} -- a class also \emph{inherits} items from
+its superclasses.
+
+The precise rules for item inheritance vary according to the kinds of items
+involved.
+
+Some object systems have a notion of `repeated inheritance': if there are
+multiple paths in the superclass graph from a class to one of its
+superclasses then items defined in that superclass may appear duplicated in
+the subclass.  Sod does not have this notion.
+
+\subsubsection{Slots} \label{sec:class.inherit.slots}
+A \emph{slot} is a unit of state.  In other object systems, slots may be
+called `fields', `member variables', or `instance variables'.
+
+A slot has a \emph{name} and a \emph{type}.  The name serves only to
+distinguish the slot from other direct slots defined by the same class.  A
+class inherits all of its proper superclasses' slots.  Slots inherited from
+superclasses do not conflict with each other or with direct slots, even if
+they have the same names.
+
+At run-time, each instance of the class holds a separate value for each slot,
+whether direct or inherited.  Changing the value of an instance's slot
+doesn't affect other instances.
+
+\subsubsection{Initializers} \label{sec:class.inherit.init}
+Mumble.
+
+\subsubsection{Messages} \label{sec:class.inherit.messages}
+A \emph{message} is the stimulus for behaviour.  In Sod, a class must define,
+statically, the name and format of the messages it is able to receive and the
+values it will return in reply.  In this respect, a message is similar to
+`abstract member functions' or `interface member functions' in other object
+systems.
+
+Like slots, a message has a \emph{name} and a \emph{type}.  Again, the name
+serves only to distinguish the message from other direct messages defined by
+the same class.  Messages inherited from superclasses do not conflict with
+each other or with direct messages, even if they have the same name.
+
+At run-time, one sends a message to an instance by invoking a function
+obtained from the instance's \emph{vtable}: \xref{sec:fixme-vtable}.
+
+\subsubsection{Methods} \label{sec:class.inherit.methods}
+A \emph{method} is a unit of behaviour.  In other object systems, methods may
+be called `member functions'.
+
+A method is associated with a message.  When a message is received by an
+instance, all of the methods associated with that message on the instance's
+class or any of its superclasses are \emph{applicable}.  The details of how
+the applicable methods are invoked are described fully in
+\xref{sec:fixme-method-combination}.
+
+\subsection{Chains and instance layout} \label{sec:class.layout}
+
+C is a rather low-level language, and in particular it exposes details of the
+way data is laid out in memory.  Since an instance of a class~$C$ should be
+(at least in principle) usable anywhere an instance of some superclass $B
+\succeq C$ is expected, this implies that an instance of the subclass $C$
+needs to contain within it a complete instance of each superclass $B$, laid
+out according to the rules of instances of $B$, so that if we have (the
+address of) an instance of $C$, we can easily construct a pointer to a thing
+which looks like an instance of $B$ contained within it.
+
+Specifically, the information we need to retain for an instance of a
+class~$C$ is:
+\begin{itemize}
+\item the values of each of the slots defined by $C$, including those defined
+  by superclasses;
+\item information which will let us convert a pointer to $C$ into a pointer
+  to any superclass $B \succeq C$;
+\item information which will let us call the appropriate effective method for
+  each message defined by $C$, including those defined by superclasses; and
+\item some additional meta-level information, such as how to find the class
+  object for $C$ given (the address of) one of its instances.
+\end{itemize}
+
+Observe that, while each distinct instance must clearly have its own storage
+for slots, all instances of $C$ can share a single copy of the remaining
+information.  The individual instance only needs to keep a pointer to this
+shared table, which, inspired by the similar structure in many \Cplusplus\
+ABIs, are called a \emph{vtable}.
+
+The easiest approach would be to decide that instances of $C$ are exactly
+like instances of $B$, only with extra space at the end for the extra slots
+which $C$ defines over and above those already existing in $B$.  Conversion
+is then trivial: a pointer to an instance of $C$ can be converted to a
+pointer to an instance of some superclass $B$ simply by casting.  Even though
+the root class @|SodObject| doesn't have any slots at all, its instances will
+still need a vtable so that you can find its class object: the address of the
+vtable therefore needs to be at the very start of the instance structure.
+Again, a vtable for a superclass would have a vtable for each of its
+superclasses as a prefix, with new items added afterwards.
+
+This appealing approach works well for an object system which only permits
+single inheritance of both state and behaviour.  Alas, it breaks down when
+multiple inheritance is allowed: $C$ can be a subclass of both $B$ and $B'$,
+even though $B$ is not a subclass of $B'$, nor \emph{vice versa}; so, in
+general, $B$'s instance structure will not be a prefix of $B'$'s, nor will
+$B'$'s be a prefix of $B$'s, and therefore $C$ cannot have both $B$ and $B'$
+as a prefix.
+
+A (non-root) class may -- though need not -- have a distinguished \emph{link}
+superclass, which need not be a direct superclass.  Furthermore, each
+class~$C$ must satisfy the \emph{chain condition}: for any superclass $A$ of
+$C$, there can be at most one other superclass of $C$ whose link superclass
+is $A$.\footnote{%
+  That is, it's permitted for two classes $B$ and $B'$ to have the same link
+  superclass $A$, but $B$ and $B'$ can't then both be superclasses of the
+  same class $C$.} %
+Therefore, the links partition the superclasses of~$C$ into nice linear
+\emph{chains}, such that each superclass is a member of exactly one chain.
+If a class~$B$ has a link superclass~$A$, then $B$'s \emph{level} is one more
+than that of $A$; otherwise $B$ is called a \emph{chain head} and its level
+is zero.  If the classes in a chain are written in a list, chain head first,
+then the level of each class gives its index in the list.
+
+Chains therefore allow us to recover some of the linearity properties which
+made layout simple in the case of single inheritance.  The instance structure
+for a class $C$ contains a substructure for each of $C$'s superclass chains;
+a pointer to an object of class $C$ actually points to the substructure for
+the chain containing $C$.  The order of these substructures is unimportant
+for now.\footnote{%
+  The chains appear in the order in which their most specific classes appear
+  in $C$'s class precedence list.  This guarantees that the chain containing
+  $C$ itself appears first, so that a pointer to $C$'s instance structure is
+  actually a pointer to $C$'s chain substructure.  Apart from that, it's a
+  simple, stable, but basically arbitrary choice which can't be changed
+  without breaking the ABI.} %
+The substructure for each chain begins with a pointer to a vtable, followed
+by a structure for each superclass in the chain containing the slots defined
+by that superclass, with the chain head (least specific class) first.
+
+Suppose we have a pointer to (static) type $C$, and want to convert it into a
+pointer to some superclass $B$ of $C$ -- an \emph{upcast}.\footnote{%
+  In the more general case, we have a pointer to static type $C$, which
+  actually points to an object of some subclass $D$ of $C$, and want to
+  convert it into a pointer to type $B$.  Such a conversion is called a
+  \emph{downcast} if $B$ is a subclass of $C$, or a \emph{cross-cast}
+  otherwise.  Downcasts and cross-casts require complicated run-time
+  checking, and can will fail unless $B$ is a superclass of $D$.} %
+If $B$ is in the same chain as $C$ -- an \emph{in-chain upcast} -- then the
+pointer value is already correct and it's only necessary to cast it
+appropriately.  Otherwise -- a \emph{cross-chain upcast} -- the pointer needs
+to be adjusted to point to a different chain substructure.  Since the lengths
+and relative positions of the chain substructures vary between classes, the
+adjustments are stored in the vtable.  Cross-chain upcasts are therefore a
+bit slower than in-chain upcasts.
+
+Each chain has its own separate vtable, because much of the metadata stored
+in the vtable is specific to a particular chain.  For example:
+\begin{itemize}
+\item offsets to other chains' substructures will vary depending on which
+  chain we start from; and
+\item entry points to methods 
+\end{itemize}
+%%%--------------------------------------------------------------------------
+\section{Superclass linearization}
+
+Before making any decisions about relationships between superclasses, Sod
+\emph{linearizes} them, i.e., imposes a total order consistent with the
+direct-subclass/superclass partial order.
+
+In the vague hope that we don't be completely bogged down in formalism by the
+end of this, let's introduce some notation.  We'll fix some class $z$ and
+consider its set of superclasses $S(z) = \{ a, b, \dots \}$.  We can define a
+relation $c \prec_1 d$ if $c$ is a direct subclass of $d$, and extend it by
+taking the reflexive, transitive closure: $c \preceq d$ if and only if
+\begin{itemize}
+\item $c = d$, or
+\item there exists some class $x$ such that $c \prec_1 x$ and $x \preceq d$.
+\end{itemize}
+This is the `is-subclass-of' relation we've been using so far.\footnote{%
+  In some object systems, notably Flavors, this relation is allowed to fail
+  to be a partial order because of cycles in the class graph.  I haven't
+  given a great deal of thought to how well Sod would cope with a cyclic
+  class graph.} %
+We write $d \succeq c$ and say that $d$ is a superclass of $c$ if and only if
+$c \preceq d$.
+
+The problem comes when we try to resolve inheritance questions.  A class
+should inherit behaviour from its superclasses; but, in a world of multiple
+inheritance, which one do we choose?  We get a simple version of this problem
+when we try to resolve inheritance of slot initializers: only one initializer
+can be inherited.
+
+We start by collecting into a set~$I$ the classes which define an initializer
+for the slot.  If $I$ contains both a class $x$ and one of $x$'s superclasses
+then we should prefer $x$ and consider the superclass to be overridden.  So
+we should confine our attention to \emph{least} classes: a member $x$ of a
+set $I$ is least, with respect to a particular partial order, if $y \preceq
+x$ only when $x = y$.  If there is a single least class in our set the we
+have a winner.  Otherwise we want some way to choose among them.
+
+This is not uncontroversial.  Languages such as \Cplusplus\ refuse to choose
+among least classes; instead, any program in which such a choice must be made
+is simply declared erroneous.
+
+Simply throwing up our hands in horror at this situation is satisfactory when
+we only wanted to pick one `winner', as we do for slot initializers.
+However, method combination is a much more complicated business.  We don't
+want to pick just one winner: we want to order all of the applicable methods
+in some way.  Insisting that there is a clear winner at every step along the
+chain is too much of an imposition.  Instead, we \emph{linearize} the
+classes.
+
+%%%--------------------------------------------------------------------------
+\section{Invariance, covariance, contravariance}
+
+In Sod, at least with regard to the existing method combinations, method
+types are \emph{invariant}.  This is not an accident, and it's not due to
+ignorance.
+
+The \emph{signature} of a function, method or message describes its argument
+and return-value types.  If a method's arguments are an integer and a string,
+and it returns a character, we might write its signature as
+\[ (@|int|, @|string|) \to @|char| \]
+In Sod, a method's arguments have to match its message's arguments precisely,
+and the return type must either be @|void| -- for a dæmon method -- or again
+match the message's return type.  This is argument and return-type
+\emph{invariance}.
+
+Some object systems allow methods with subtly different signatures to be
+defined on a single message.  In particular, since the idea is that instances
+of a subclass ought to be broadly compatible~(see \xref{sec:phil.lsp}) with
+existing code which expects instances of a superclass, we might be able to
+get away with bending method signatures one way or another to permit this.
+
+\Cplusplus\ permits \emph{return-type covariance}, where a method's return
+type can be a subclass of the return type specified by a less-specific
+method.  Eiffel allows \emph{argument covariance}, where a method's arguments
+can be subclasses of the arguments specified by a less-specific
+method.\footnote{%
+  Attentive readers will note that I ought to be talking about pointers to
+  instances throughout.  I'm trying to limit the weight of the notation.
+  Besides, I prefer data models as found in Lisp and Python where all values
+  are held by reference.} %
+
+Eiffel's argument covariance is unsafe.\footnote{%
+  Argument covariance is correct if you're doing runtime dispatch based on
+  argument types.  Eiffel isn't: it's single dispatch, like Sod is.} %
+Suppose that we have two pairs of classes, $a \prec_1 b$ and $c \prec_1 d$.
+Class $b$ defines a message $m$ with signature $d \to @|int|$; class $a$
+defines a method with signature $c \to @|int|$.  This means that it's wrong
+to send $m$ to an instance $a$ carrying an argument of type $d$.  But of
+course, we can treat an instance of $a$ as if it's an instance of $b$,
+whereupon it appears that we are permitted to pass a~$c$ in our message.  The
+result is a well-known hole in the type system.  Oops.
+
+\Cplusplus's return-type covariance is fine.  Also fine is argument
+\emph{contravariance}.  If $b$ defined its message to have signature $c \to
+@|int|$, and $a$ were to broaden its method to $d \to @|int|$, there'd be no
+problem.  All $c$s are $d$s, so viewing an $a$ as a $b$ does no harm.
+
+All of this fiddling with types is fine as long as method inheritance or
+overriding is an all-or-nothing thing.  But Sod has method combinations,
+where applicable methods are taken from the instance's class and all its
+superclasses and combined.  And this makes everything very messy.
+
+It's possible to sort all of the mess out in the generated effective method
+-- we'd just have to convert the arguments to the types that were expected by
+the direct methods.  This would require expensive run-time conversions of all
+of the non-invariant arguments and return values.  And we'd need some
+complicated rule so that we could choose sensible types for the method
+entries in our vtables.  Something like this:
+\begin{quote} \itshape
+  For each named argument of a message, there must be a unique greatest type
+  among the types given for that argument by the applicable methods; and
+  there must be a unique least type among all of the return types of the
+  applicable methods.
+\end{quote}
+I have visions of people wanting to write special no-effect methods whose
+only purpose is to guide the translator around the class graph properly.
+Let's not.
+
+%% things to talk about:
+%% Liskov substitution principle and why it's mad
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/lispintro.tex b/doc/lispintro.tex
new file mode 100644 (file)
index 0000000..5f1043f
--- /dev/null
@@ -0,0 +1,207 @@
+%%% -*-latex-*-
+%%%
+%%% Description of the internal class structure and protocol
+%%%
+%%% (c) 2009 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Simple Object Definition system.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Protocol overview} \label{ch:proto}
+
+This chapter provides an overview of the Sod translator's internal object
+model.  It describes most of the important classes and generic functions, how
+they are used to build a model of a Sod module and produce output code, and
+how an extension might modify the translator's behaviour.
+
+I assume familiarity with the Common Lisp Object System (CLOS).  Familiarity
+with the CLOS Metaobject Protocol isn't necessary but may be instructive.
+
+%%%--------------------------------------------------------------------------
+\section{A tour through the translator}
+
+At the very highest level, the Sod translator works in two phases: it
+\emph{parses} source files into an internal representation, and then it
+\emph{generates} output files from the internal representation.
+
+The function @|read-module| is given a pathname for a file: it opens the
+file, parses the program text, and returns a @|module| instance describing
+the classes and other items found.  Parsing has a number of extension points
+which allow extensions to add their own module syntax.  Properties can be
+attached to modules and the items defined within them, which select which
+internal classes are used to represent them, and possibly provide additional
+parameters to them.
+
+Modules contain a variety of objects, but the most important objects are
+classes, which are associated with a menagerie of other objects representing
+the slots, messages, methods and so on defined in the module.  These various
+objects engage in a (fairly complicated) protocol to construct another
+collection of \emph{layout objects} describing the low-level data structures
+and tables which need to be creates.
+
+At the far end, the main output function is @|output-module|, which is given
+a module, an output stream and a \emph{reason}, which describes what kind of
+output is wanted.  The module items and the layout objects then engage in
+another protocol to work out what output needs to be produced, and which
+order it needs to be written in.
+
+%%%--------------------------------------------------------------------------
+\section{Specification conventions} \label{sec:proto.conventions}
+
+Throughout this specification, the phrase `it is an error' indicates that a
+particular circumstance is erroneous and results in unspecified and possibly
+incorrect behaviour.  In particular, the situation need not be immediately
+diagnosed, and the consequences may be far-reaching.
+
+The following conventions apply throughout this specification.
+
+\begin{itemize}
+
+\item If a specification describes an argument as having a particular type or
+  syntax, then it is an error to provide an argument not having that
+  particular type or syntax.
+
+\item If a specification describes a function then that function might be
+  implemented as a generic function; it is an error to attempt to (re)define
+  it as a generic function, or to attempt to add methods to it.  A function
+  specified as being a generic function will certainly be so; if user methods
+  are permitted on the generic function then this will be specified.
+
+\item Where a class precedence list is specified, either explicitly or
+  implicitly by a class hierarchy, the implementation may include additional
+  superclasses not specified here.  Such additional superclasses will not
+  affect the order of specified classes in the class precedence lists either
+  of specified classes themselves or of user-defined subclasses of specified
+  classes.
+
+\item Unless otherwise specified, generic functions use the standard method
+  combination.
+
+\item The specifications for methods are frequently brief; they should be
+  read in conjunction with and in the context of the specification for the
+  generic function and specializing classes, if any.
+
+\item An object $o$ is a \emph{direct instance} of a class $c$ if @|(eq
+  (class-of $o$) $c$)|; $o$ is an \emph{instance} of $c$ if it is a direct
+  instance of any subclass of $c$.
+
+\item If a class is specified as being \emph{abstract} then it is an error to
+  construct direct instances of it, e.g., using @|make-instance|.
+
+\item If an object is specified as being \emph{immutable} then it is an error
+  to mutate it, e.g., using @|(setf (slot-value \ldots) \ldots)|.  Programs
+  may rely on immutable objects retaining their state.
+
+\item A value is \emph{fresh} if it is guaranteed to be not @|eql| to any
+  previously existing value.  A list is \emph{fresh} if it is guaranteed that
+  none of the cons cells in its main cdr chain (i.e., the list head, its cdr,
+  and so on) are @|eql| to any previously existing value.
+
+\item Unless otherwise specified, it is an error to mutate any part of value
+  passed as an argument to, or a non-fresh part of a value returned by, a
+  function specified in this document.
+
+\item Unless otherwise specified, it is an error to change the class of an
+  instance of any class described here; and it is an error to change the
+  class of an object to a class described here.
+
+\end{itemize}
+
+\subsection{Format of the entries} \label{sec:proto.conventions.format}
+
+Most symbols defined by the protocol have their own entries.  An entry begins
+with a header line, showing a synopsis of the symbol on the left, and the
+category (function, class, macro, etc.) on the right.
+
+\begin{describe}{fun}{example-function @<required>
+    \&optional @<optional>
+    \&rest @<rest>
+    \&key :keyword
+    @> @<result>}
+  The synopsis for a function, generic function or method describes the
+  function's lambda-list using the usual syntax.  Note that keyword arguments
+  are shown by naming their keywords; in the description, the value passed
+  for the keyword argument @|:keyword| is shown as @<keyword>.
+
+  If no results are shown, then the return values (if any) are not
+  specified.  Functions may return more than one result, e.g.,
+  \begin{quote} \sffamily
+    floor @<dividend> \&optional (@<divisor> 1) @> @<quotient> @<remainder>
+  \end{quote}
+  or possibly multiple results, e.g.,
+  \begin{quote} \sffamily
+    values \&rest @<values> @> @<value>^*
+  \end{quote}
+
+  For a method, specializers are shown using the usual @|defmethod| syntax,
+  e.g.,
+  \begin{quote} \sffamily
+    some-generic-function ((@<specialized> list) @<unspecialized>)
+      @> @<result>
+  \end{quote}
+\end{describe}
+
+\begin{describe}{mac}{example-macro
+  ( @{ @<symbol> @! (@<symbol> @<form>) @}^* ) \\ \ind
+    @[[ @<declaration>^* @! @<documentation-string> @]] \\
+    @<body-form>^*
+      \nlret @<value>^*}
+  The synopsis for a macro describes the acceptable syntax using the
+  following notation.
+  \begin{itemize}
+  \item Literal symbols, e.g., keywords and parenthesis, are shown in
+    @|sans|.
+  \item Metasyntactic variables are shown in (roman) @<italics>.
+  \item Items are grouped together by braces `@{ $\dots$ @}'.  The notation
+    `@{ $\dots$ @}^*' indicates that the enclosed items may be repeated zero
+    or more times; `@{ $\dots$ @}^+' indicates that the enclosed items may be
+    repeated one or more times.  This notation may be applied to a single
+    item without the braces.
+  \item Optional items are shown enclosed in brackets `@[ $\dots$ @]'.
+  \item Alternatives are separated by vertical bars `@!'; the vertical bar
+    has low precedence, so alternatives extend as far as possible between
+    bars and up to the enclosing brackets if any.
+  \item A sequence of alternatives enclosed in double-brackets `@[[ $\ldots$
+    @]]' indicates that the alternatives may occur in any order, but each may
+    appear at most once unless marked by a star.
+  \item The notation for results is the same as for functions.
+  \end{itemize}
+  For example, the notation at the head of this example describes syntax
+  for @|let|.
+\end{describe}
+
+\begin{describe}{cls}{example-class (direct-super other-direct-super) \&key
+    :initarg}
+  The synopsis for a class lists the class's direct superclasses, and the
+  acceptable initargs in the form of a lambda-list.  The initargs may be
+  passed to @|make-instance| when constructing an instance of the class or a
+  subclass of it.  If instances of the class may be reinitialized, or if
+  objects can be changed to be instances of the class, then these initargs
+  may also be passed to @|reinitialize-instance| and/or @|change-class| as
+  applicable; the class description will state explicitly when these
+  operations are allowed.
+\end{describe}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
index abbf94a..93ee8be 100644 (file)
     (when (or (specialized-on-p #'sod-parser:expand-parser-spec 1 symbol)
              (specialized-on-p #'sod-parser:expand-parser-form 1 symbol))
       (push :parser things))
+    (when (get symbol 'optparse::opthandler)
+      (push :opthandler things))
+    (when (get symbol 'optparse::optmacro)
+      (push :optmacro things))
     (nreverse things)))
 
 (defun categorize-symbols (paths package)
   (let* ((sod (asdf:find-system "sod"))
         (parser-files (files (by-name sod "parser")))
         (utilities (by-name sod "utilities"))
-        (sod-files (remove utilities (files sod))))
+        (sod-frontend (asdf:find-system "sod-frontend"))
+        (optparse (by-name sod-frontend "optparse"))
+        (frontend (by-name sod-frontend "frontend"))
+        (sod-files (set-difference (files sod) (list utilities))))
     (report-symbols (mapcar #'file-name sod-files) "SOD")
+    (report-symbols (mapcar #'file-name (list frontend)) "SOD-FRONTEND")
     (report-symbols (mapcar #'file-name parser-files) "SOD-PARSER")
+    (report-symbols (mapcar #'file-name (list optparse)) "OPTPARSE")
     (report-symbols (mapcar #'file-name (list utilities)) "SOD-UTILITIES"))))
diff --git a/doc/misc.tex b/doc/misc.tex
new file mode 100644 (file)
index 0000000..de62c8e
--- /dev/null
@@ -0,0 +1,534 @@
+%%% -*-latex-*-
+%%%
+%%% Miscellaneous functionality
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Miscellaneous functionality} \label{ch:misc}
+
+%%%--------------------------------------------------------------------------
+\section{Utilities} \label{sec:misc.utilities}
+
+These symbols are defined in the @|sod-utilities| package.
+
+\begin{describe}{mac}
+    {with-gensyms (@{ @<var> @! (@<var> @[@<name>@]) @}^*) \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {once-only (@[[ :environment @<env> @]]
+                @{ @<var> @! (@<var> @[@<value-form>@]) @}^*) \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {parse-body @<body> @> @<doc-string> @<declarations> @<body-forms>}
+\end{describe}
+
+\begin{describe}{cls}{loc}
+\end{describe}
+
+\begin{describe}{fun}{locp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{macro}{locf @<place> @> @<locative>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{ref @<locative> @> @<value>}
+     \dhead{fun}{setf (ref @<locative>) @<value>}}
+\end{describe*}
+
+\begin{describe}{mac}
+    {with-locatives
+        @{ @<var> @! (@{ @<var> @!
+                         (@<var> @[@<locative>@]) @}^*) @} \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{sym}{it}
+\end{describe}
+
+\begin{describe}{mac}{aif @<condition> @<consequent> @[@<alt>@]}
+\end{describe}
+
+\begin{describe}{mac}{awhen @<condition> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}{acond @{ (@<condition> @<form>^*) @}^*}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{mac}
+      {acase @<scrutinee> @{ (@{ @<case> @! (@<case>^*) @} @<form>^*) @}^*}
+     \dhead{mac}
+      {aecase @<scrutinee> @{ (@{ @<case> @! (@<case>^*) @} @<form>^*) @}^*}
+     \dhead{mac}{atypecase @<scrutinee> @{ (@<type> @<form>^*) @}^*}
+     \dhead{mac}{aetypecase @<scrutinee> @{ (@<type> @<form>^*) @}^*}}
+\end{describe*}
+
+\begin{describe}{mac}{asetf @{ @<place> @<value> @}^*}
+\end{describe}
+
+\begin{describe}{gf}{instance-initargs @<instance>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{copy-instance @<instance> \&rest @<initargs>}
+     \dhead{gf}{copy-instance-using-class @<class> @<instance>
+                                          \&rest @<initargs>}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{gf}{generic-function-methods @<generic-function> @> @<list>}
+     \dhead{gf}{method-specializers @<method> @> @<list>}
+     \dhead{cls}{eql-specializer}
+     \dhead{gf}{eql-specializer-object @<specializer> @> @<value>}}
+\end{describe*}
+
+\begin{describe}{fun}{make-list-builder \&optional @<initial> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-add @<builder> @<item> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-add-list @<builder> @<list> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-list @<builder> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}
+    {mappend @<function> @<list> \&rest @<more-lists> @> @<result-list>}
+\end{describe}
+
+\begin{describe}{cls}{inconsistent-merge-error (error) \&key :candidates}
+\end{describe}
+
+\begin{describe}{gf}{merge-error-candidates @<error> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}
+    {merge-lists @<lists> \&key :pick (:test \#'eql) @> @<list>}
+\end{describe}
+
+\begin{describe}{mac}
+    {categorize (\=@<item-var> @<items>
+                   @[[ :bind (@{ @<var> @! (@<var> @[@<value>@]) @}^*) @]])
+                                                                 \\ \ind\ind
+        (@{ @<cat-var> @<cat-predicate> @}^*) \- \\
+      @<body-form>^* \-
+     \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {frob-identifier @<string> \&key :swap-case :swap-hyphen
+      @> @<frobbed-string>}
+\end{describe}
+
+\begin{describe}{fun}{whitespace-char-p @<character> @> @<generic-function>}
+\end{describe}
+
+\begin{describe}{fun}
+    {update-position @<character> @<line> @<column>
+      @> @<new-line> @<new-column>}
+\end{describe}
+
+\begin{describe}{fun}
+    {backtrack-position @<character> @<line> @<column>
+      @> @<old-line> @<old-column>}
+\end{describe}
+
+\begin{describe}{fun}
+    {compose @<function> \&rest @<more-functions> @> @<function>}
+\end{describe}
+
+\begin{describe}{fun}{symbolicate \&rest @<symbols> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{mac}
+    {maybe-print-unreadable-object (@<object> @<stream>
+                                    @[[ :type @<type> @!
+                                        :identity @<identity> @]]) \\ \ind
+       @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {dosequence (@<var> @<sequence>
+                 @[[ :start @<start> @! :end @<end> @!
+                     :indexvar @<var> @]]) \\ \ind
+      @{ @<tag> @! @<body-form> @}^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {define-access-wrapper @<from> @<to>
+                           @[[ :read-only @<read-only-flag> @]]}
+\end{describe}
+
+\begin{describe}{mac}
+    {default-slot (@<instance> @<slot> @[@<slot-names>@]) \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {define-on-demand-slot @<class> @<slot> (@<instance>) \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Condition utilities} \label{sec:misc.condition}
+
+These symbols are defined in the @|sod-parser| package.
+
+\begin{describe}{cls}{enclosing-condition (condition) \&key :condition}
+\end{describe}
+
+\begin{describe}{gf}
+    {enclosed-condition @<enclosing-condition> @> @<condition>}
+\end{describe}
+
+\begin{describe}{fun}{cerror* @<datum> \&rest @<arguments>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Option parser} \label{sec:misc.optparse}
+
+These symbols are defined in the @!optparse| package.
+
+\begin{describe}{fun}{exit \&optional (@<code> 0) \&key :abrupt}
+\end{describe}
+
+\begin{describe}{var}{*program-name*}
+\end{describe}
+
+\begin{describe}{var}{*command-line*}
+\end{describe}
+
+\begin{describe}{fun}{set-command-line-arguments}
+\end{describe}
+
+\begin{describe}{fun}{moan @<format-string> \&rest @<format-args>}
+\end{describe}
+
+\begin{describe}{fun}{die @<format-string> \&rest @<format-args>}
+\end{describe}
+
+\begin{describe}{var}{*options*}
+\end{describe}
+
+\begin{describe}{cls}{option}
+\end{describe}
+
+\begin{describe}{fun}{optionp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-option \=@<long-name> @<short-name> \+ \\
+                   \&optional @<arg-name> \\
+                   \&key :tag :negated-tag :arg-optional-p :documentation \-
+      \nlret @<option>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{opt-short-name @<option> @> @<character-or-null>}
+     \dhead{fun}{setf (opt-short-name @<option>) @<character-or-null>}
+     \dhead{fun}{opt-long-name @<option> @> @<string-or-null>}
+     \dhead{fun}{setf (opt-long-name @<option>) @<string-or-null>}
+     \dhead{fun}{opt-tag @<option> @> @<tag>}
+     \dhead{fun}{setf (opt-tag @<option>) @<tag>}
+     \dhead{fun}{opt-negated-tag @<option> @> @<tag>}
+     \dhead{fun}{setf (opt-negated-tag @<option>) @<tag>}
+     \dhead{fun}{opt-arg-name @<option> @> @<string-or-null>}
+     \dhead{fun}{setf (opt-arg-name @<option>) @<string-or-null>}
+     \dhead{fun}{opt-optional-p @<option> @> @<generalized-boolean>}
+     \dhead{fun}{setf (opt-optional-p @<option>) @<generalized-boolean>}
+     \dhead{fun}{opt-documentation @<option> @> @<string-or-null>}
+     \dhead{fun}{setf (opt-documentation @<option>) @<string-or-null>}}
+\end{describe*}
+
+\begin{describe}{cls}{option-parser}
+\end{describe}
+
+\begin{describe}{fun}{option-parser-p @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-option-parser \&key \=:args :options :non-option :numericp \+ \\
+                              :negated-numeric-p long-only-p \-
+      \nlret @<option-parser>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{op-options @<option-parser> @> @<list>}
+     \dhead{fun}{setf (op-options @<option-parser>) @<list>}
+     \dhead{fun}{op-non-option @<option-parser> @> @<action>}
+     \dhead{fun}{setf (op-non-option @<option-parser>) @<action>}
+     \dhead{fun}{op-long-only-p @<option-parser> @> @<generalized-boolean>}
+     \dhead{fun}{setf (op-long-only-p @<option-parser>) @<generalized-boolean>}
+     \dhead{fun}{op-numeric-p @<option-parser> @> @<generalized-boolean>}
+     \dhead{fun}{setf (op-numeric-p @<option-parser>) @<generalized-boolean>}
+     \dhead{fun}{op-negated-numeric-p @<option-parser> @<generalized-boolean>}
+     \dhead{fun}{setf (op-negated-numeric-p @<option-parser>) @<generalized-boolean>}
+     \dhead{fun}{op-negated-p @<option-parser> @> @<generalized-boolean>}
+     \dhead{fun}{setf (op-negated-p @<option-parser>) @<generalized-boolean>}}
+\end{describe*}
+
+\begin{describe}{cls}
+    {option-parse-error (error simple-condition)
+      \&key :format-control :format-arguments}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-remainder @<option-parser>}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-return @<tag> \&optional @<argument>}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-next @<option-parser>}
+\end{describe}
+
+\begin{describe}{mac}{option-parse-try @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}{with-unix-error-reporting () @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {defopthandler @<name> (@<var> @[@<arg>@]) @<lambda-list> \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {invoke-option-handler @<handler> @<locative> @<arg> @<arguments>}
+\end{describe}
+
+\begin{describe}{opt}{set \&optional @<value>}
+\end{describe}
+
+\begin{describe}{opt}{clear \&optional @<value>}
+\end{describe}
+
+\begin{describe}{opt}{inc \&optional @<maximum> @<step>}
+\end{describe}
+
+\begin{describe}{opt}{dec \&optional <minimum> <step>}
+\end{describe}
+
+\begin{describe}{opt}{read}
+\end{describe}
+
+\begin{describe}{opt}{int \&key :radix :min :max}
+\end{describe}
+
+\begin{describe}{opt}{string}
+\end{describe}
+
+\begin{describe}{opt}{keyword \&optional @<valid>}
+\end{describe}
+
+\begin{describe}{opt}{list \&optional @<handler> \&rest @<handler-args>}
+\end{describe}
+
+\begin{describe}{mac}{defoptmacro @<name> @<lambda-list> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}{parse-option-form @<form>}
+\end{describe}
+
+\begin{describe}{mac}
+    {options @{ \=@<string> @! \+ \\
+                  @<option-macro> @! (@<option-macro> @<macro-arg>^*) @! \\
+                  (@[[ \=@<character> @! (:short-name @<character>) @! \+ \\
+                         @<string>^* @! @<symbol> @! @<rational> @!
+                         (:long-name @<string>) @! \\
+                         (@<string> @<format-arg>^+) @!
+                         (:doc @<string> @<format-arg>^*) @! \\
+                         (:opt-arg @<arg-name>) @! \\
+                         @<keyword> @! (:tag @<tag>) @!
+                                       (:negated-tag @<tag>) @! \\
+                         @{ (@<handler> @<var> @<handler-arg>^*) @}^* @]]) @}^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {simple-usage @<option-list> \&optional @<mandatory-args> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}{show-usage @<prog> @<usage> \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}
+    {show-help @<prog> @<usage> @<option-list> \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}{sanity-check-option-list @<option-list>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{var}{*help*}
+     \dhead{var}{*version*}
+     \dhead{var}{*usage*}}
+\end{describe*}
+
+\begin{describe}{fun}{do-usage \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}{die-usage}
+\end{describe}
+
+\begin{describe}{optmac}
+    {help-options \&key :short-help :short-version :short-usage}
+\end{describe}
+
+\begin{describe}{fun}
+    {define-program \&key \=:program-name \+ \\
+                            :help :version :usage :full-usage \\
+                            :options}
+\end{describe}
+
+\begin{describe}{mac}
+    {do-options (@[[ :parser @<option-parser> @]]) \\ \ind
+      @{ (@{ @<case> @! (@<case>^*)@} (@[@[@<opt-var>@] @<arg-var>@])
+          @<form>^*) @}^*}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Property sets} \label{sec:misc.pset}
+
+\begin{describe}{fun}{property-key @<name> @> @<keyword>}
+\end{describe}
+
+\begin{describe}{gf}{decode-property @<raw-value> @> @<type> @<value>}
+\end{describe}
+
+\begin{describe}{cls}{property}
+\end{describe}
+
+\begin{describe}{fun}{propertyp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-property @<name> @<raw-value> \&key :type :location :seenp}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{p-name @<property> @> @<name>}
+     \dhead{fun}{setf (p-name @<property>) @<name>}
+     \dhead{fun}{p-value @<property> @> @<value>}
+     \dhead{fun}{setf (p-value @<property>) @<value>}
+     \dhead{fun}{p-type @<property> @> @<type>}
+     \dhead{fun}{setf (p-type @<property>) @<type>}
+     \dhead{fun}{p-key @<property> @> @<symbol>}
+     \dhead{fun}{setf (p-key @<property>) @<symbol>}
+     \dhead{fun}{p-seenp @<property> @> @<boolean>}
+     \dhead{fun}{setf (p-seenp @<property>) @<boolean>}}
+\end{describe*}
+
+\begin{describe}{gf}{decode-property @<raw-value> @> @<type> @<value>}
+\end{describe}
+
+\begin{describe}{gf}
+    {coerce-property-value @<value> @<type> @<wanted> @> @<coerced-value>}
+\end{describe}
+
+\begin{describe}{cls}{pset}
+\end{describe}
+
+\begin{describe}{fun}{psetp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}{make-pset @> @<pset>}
+\end{describe}
+
+\begin{describe}{fun}{pset-get @<pset> @<key> @> @<property-or-nil>}
+\end{describe}
+
+\begin{describe}{fun}{pset-store @<pset> @<property> @> @<property>}
+\end{describe}
+
+\begin{describe}{fun}{pset-map @<func> @<pset>}
+\end{describe}
+
+\begin{describe}{mac}{with-pset-iterator (@<iter> @<pset>) @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {store-property @<pset> @<name> @<value> \&key :type :location
+      @> @<property>}
+\end{describe}
+
+\begin{describe}{fun}
+    {get-property @<pset> @<name> @<type> \&optional @<default>
+      @> @<value> @<floc-or-nil>}
+\end{describe}
+
+\begin{describe}{fun}
+    {add-property @<pset> @<name> @<value> \&key :type :location
+      @> @<property>}
+\end{describe}
+
+\begin{describe}{fun}{make-property-set \&rest @<plist> @> @<pset>}
+\end{describe}
+
+\begin{describe}{gf}{property-set @<thing> @> @<pset>}
+\end{describe}
+
+\begin{describe}{fun}{check-unused-properties @<pset>}
+\end{describe}
+
+\begin{describe}{mac}
+    {default-slot-from-property
+        (@<instance> @<slot> @[@<slot-names>@]) \\ \ind\ind
+        (@<pset> @<property> @<type> @[@<prop-var> @<convert-form>^*@]) \- \\
+      @<default-form>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {parse-property-set @<scanner>
+      @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Miscellaneous translator features} \label{sec:misc.pset}
+
+\begin{describe}{var}{*sod-version*}
+\end{describe}
+
+\begin{describe}{var}{*debugout-pathname*}
+\end{describe}
+
+\begin{describe}{fun}{test-module @<path> @<reason>}
+\end{describe}
+
+\begin{describe}{fun}{exercise}
+\end{describe}
+
+\begin{describe}{fun}{sod-frontend:main}
+\end{describe}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/output.tex b/doc/output.tex
new file mode 100644 (file)
index 0000000..29a8b4d
--- /dev/null
@@ -0,0 +1,116 @@
+%%% -*-latex-*-
+%%%
+%%% Output machinery
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{The output system} \label{ch:output}
+
+%%%--------------------------------------------------------------------------
+
+%% output for `h' files
+%%
+%% prologue
+%% guard start
+%% typedefs start
+%% typedefs
+%% typedefs end
+%% includes start
+%% includes
+%% includes end
+%% classes start
+%% CLASS banner
+%% CLASS islots start
+%% CLASS islots slots
+%% CLASS islots end
+%% CLASS vtmsgs start
+%% CLASS vtmsgs CLASS start
+%% CLASS vtmsgs CLASS slots
+%% CLASS vtmsgs CLASS end
+%% CLASS vtmsgs end
+%% CLASS vtables start
+%% CLASS vtables CHAIN-HEAD start
+%% CLASS vtables CHAIN-HEAD slots
+%% CLASS vtables CHAIN-HEAD end
+%% CLASS vtables end
+%% CLASS vtable-externs
+%% CLASS vtable-externs-after
+%% CLASS methods start
+%% CLASS methods
+%% CLASS methods end
+%% CLASS ichains start
+%% CLASS ichains CHAIN-HEAD start
+%% CLASS ichains CHAIN-HEAD slots
+%% CLASS ichains CHAIN-HEAD end
+%% CLASS ichains end
+%% CLASS ilayout start
+%% CLASS ilayout slots
+%% CLASS ilayout end
+%% CLASS conversions
+%% CLASS object
+%% classes end
+%% guard end
+%% epilogue
+
+%% output for `c' files
+%%
+%% prologue
+%% includes start
+%% includes
+%% includes end
+%% classes start
+%% CLASS banner
+%% CLASS direct-methods start
+%% CLASS direct-methods METHOD start
+%% CLASS direct-methods METHOD body
+%% CLASS direct-methods METHOD end
+%% CLASS direct-methods end
+%% CLASS effective-methods
+%% CLASS vtables start
+%% CLASS vtables CHAIN-HEAD start
+%% CLASS vtables CHAIN-HEAD class-pointer METACLASS
+%% CLASS vtables CHAIN-HEAD base-offset
+%% CLASS vtables CHAIN-HEAD chain-offset TARGET-HEAD
+%% CLASS vtables CHAIN-HEAD vtmsgs CLASS start
+%% CLASS vtables CHAIN-HEAD vtmsgs CLASS slots
+%% CLASS vtables CHAIN-HEAD vtmsgs CLASS end
+%% CLASS vtables CHAIN-HEAD end
+%% CLASS vtables end
+%% CLASS object prepare
+%% CLASS object start
+%% CLASS object CHAIN-HEAD ichain start
+%% CLASS object SUPER slots start
+%% CLASS object SUPER slots
+%% CLASS object SUPER vtable
+%% CLASS object SUPER slots end
+%% CLASS object CHAIN-HEAD ichain end
+%% CLASS object end
+%% classes end
+%% epilogue
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/parsing.tex b/doc/parsing.tex
new file mode 100644 (file)
index 0000000..58959c0
--- /dev/null
@@ -0,0 +1,765 @@
+%%% -*-latex-*-
+%%%
+%%% Description of the parsing machinery
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Parsing} \label{ch:parsing}
+
+%%%--------------------------------------------------------------------------
+\section{The parser protocol} \label{sec:parsing.proto}
+
+For the purpose of Sod's parsing library, \emph{parsing} is the process of
+reading a sequence of input items, in order, and computing an output value.
+
+A \emph{parser} is an expression which consumes zero or more input items and
+returns three values: a \emph{result}, a \emph{success flag}, and a
+\emph{consumed flag}.  The two flags are (generalized) booleans.  If the
+success flag is non-nil, then the parser is said to have \emph{succeeded},
+and the result is the parser's output.  If the success flag is nil then the
+parser is said to have \emph{failed}, and the result is a list of
+\emph{indicators}.  Finally, the consumed flag is non-nil if the parser
+consumed any input items.
+
+\begin{describe}{fun}{combine-parser-failures @<failures> @> @<list>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{File locations} \label{sec:parsing.floc}
+
+\begin{describe}{cls}{file-location}
+\end{describe}
+
+\begin{describe}{fun}{file-location-p @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+    {make-file-location @<filename> \&optional @<line> @<column>
+      @> @<file-location>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{file-location-filename @<floc> @> @<string-or-nil>}
+     \dhead{fun}{file-location-line @<floc> @> @<fixnum-or-nil>}
+     \dhead{fun}{file-location-column @<floc> @> @<fixnum-or-nil>}}
+\end{describe*}
+
+\begin{describe}{gf}{file-location @<object> @> @<floc>}
+  \begin{describe}{meth}{file-location (@<floc> file-location) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{file-location (@<stream> stream) @> @<floc>}
+  \end{describe}
+  \begin{describe}{meth}{file-location (@<any> t) @> @<floc>}
+  \end{describe}
+\end{describe}
+
+\begin{describe}{cls}{condition-with-location (condition) \&key :location}
+\end{describe}
+
+\begin{describe}{meth}
+    {file-location (@<condition> condition-with-location) @> @<floc>}
+\end{describe}
+
+\begin{describe*}
+    {\quad\=\quad\=\kill
+     \dhead{cls}
+      {error-with-location (condition-with-location error) \\ \>
+        \&key :location}
+    \dhead{cls}
+      {warning-with-location (condition-with-location warning) \\ \>
+        \&key :location}
+    \dhead{cls}
+      {enclosing-error-with-location
+          (enclosing-error-with-location error) \\ \>
+        \&key :condition :location}
+    \dhead{cls}
+      {enclosing-warning-with-location
+          (enclosing-condition-with-location warning) \\ \>
+        \&key :condition :location}
+     \dhead{cls}
+      {simple-condition-with-location
+          (condition-with-location simple-condition) \\ \>
+        \&key :format-control :format-arguments :location}
+     \dhead{cls}
+      {simple-error-with-location
+          (error-with-location simple-error) \\ \>
+        \&key :format-control :format-arguments :location}
+    \dhead{cls}
+      {simple-warning-with-location
+          (warning-with-location simple-warning) \\ \>
+        \&key :format-control :format-arguments :location}}
+\end{describe*}
+
+\begin{describe}{fun}
+    {make-condition-with-location @<default-type> @<floc>
+                                  @<datum> \&rest @<arguments>
+       \nlret @<condition-with-location>}
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{error-with-location @<floc> @<datum> \&rest @<arguments>}
+     \dhead{fun}{cerror-with-location @<floc> @<continue-string>
+                                      @<datum> \&rest @<arguments>}
+     \dhead{fun}{cerror*-with-location @<floc> @<datum> \&rest @<arguments>}
+     \dhead{fun}{warn-with-location @<floc> @<datum> \&rest @<arguments>}}
+\end{describe*}
+
+\begin{describe}{mac}
+    {with-default-error-location (@<floc>) @<body-form>^* @> @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {count-and-report-errors () @<body-form>^*
+      @> @<value> @<n-errors> @<n-warnings>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Scanners} \label{sec:parsing.scanner}
+
+A \emph{scanner} is an object which keeps track of a parser's progress as it
+works through its input.  There's no common base class for scanners: a
+scanner is simply any object which implements the scanner protocol described
+here.
+
+A scanner maintains a sequence of items to read.  It can step forwards
+through the items, one at a time, until it reaches the end (if, indeed, the
+sequence is finite, which it needn't be).  Until that point, there is a
+current item, though there's no protocol for accessing it at this level
+because the nature of the items is left unspecified.
+
+Some scanners support an additional \emph{place-capture} protocol which
+allows rewinding the scanner to an earlier point in the input so that it can
+be scanned again.
+
+\subsection{Basic scanner protocol} \label{sec:parsing.scanner.basic}
+
+The basic protocol supports stepping the scanner forward through its input
+sequence, and detecting the end of the sequence.
+
+\begin{describe}{gf}{scanner-step @<scanner>}
+  Advance the @<scanner> to the next item, which becomes current.
+
+  It is an error to step the scanner if the scanner is at end-of-file.
+\end{describe}
+
+\begin{describe}{gf}{scanner-at-eof-p @<scanner> @> @<generalized-boolean>}
+  Return non-nil if the scanner is at end-of-file, i.e., there are no more
+  items to read.
+
+  If nil is returned, there is a current item, and it is safe to step the
+  scanner again; otherwise, it is an error to query the current item or to
+  step the scanner.
+\end{describe}
+
+\subsection{Place-capture scanner protocol} \label{sec:parsing.scanner.place}
+
+The place-capture protocol allows rewinding to an earlier point in the
+sequence.  Not all scanners support the place-capture protocol.
+
+To rewind a scanner to a particular point, that point must be \emph{captured}
+as a \emph{place} when it's current -- so you must know in advance that this
+is an interesting place that's worth capturing.  The type of place returned
+depends on the type of scanner.  Given a captured place, the scanner can be
+rewound to the position held in it.
+
+Depending on how the scanner works, holding onto a captured place might
+consume a lot of memory or case poor performance.  For example, if the
+scanner is reading from an input stream, having a captured place means that
+data from that point on must be buffered in case the program needs to rewind
+the scanner and read that data again.  Therefore it's possible to
+\emph{release} a place when it turns out not to be needed any more.
+
+\begin{describe}{gf}{scanner-capture-place @<scanner> @> @<place>}
+  Capture the @<scanner>'s current position as a place, and return the place.
+\end{describe}
+
+\begin{describe}{gf}{scanner-restore-place @<scanner> @<place>}
+  Rewind the @<scanner> to the state it was in when @<place> was captured.
+  In particular, the item that was current when the @<place> was captured
+  becomes current again.
+
+  It is an error to restore a @<place> that has been released, or if the
+  @<place> wasn't captured from the @<scanner>.
+\end{describe}
+
+\begin{describe}{gf}{scanner-release-place @<scanner> @<place>}
+  Release the @<place>, to avoid having to maintaining the ability to restore
+  it after it's not needed any more..
+
+  It is an error if the @<place> wasn't captured from the @<scanner>.
+\end{describe}
+
+\begin{describe}{mac}
+    {with-scanner-place (@<place> @<scanner>) @<body-form>^* @> @<value>^*}
+  Capture the @<scanner>'s current position as a place, evaluate the
+  @<body-form>s as an implicit progn with the variable @<place> bound to the captured
+  place.  When control leaves the @<body-form>s, the place is released.  The return
+  values are the values of the final @<body-form>.
+\end{describe}
+
+\subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
+
+Some scanners participate in the file-location protocol
+(\xref{sec:parsing.floc}).  They implement a method on @|file-location| which
+collects the necessary information using scanner-specific functions described
+here.
+
+\begin{describe}{fun}{scanner-file-location @<scanner> @> @<file-location>}
+  Return a @|file-location| object describing the current position of the
+  @<scanner>.
+
+  This calls the @|scanner-filename|, @|scanner-line| and @|scanner-column|
+  generic functions on the scanner, and uses these to fill in an appropriate
+  @|file-location|.
+
+  Since there are default methods on these generic functions, it is not an
+  error to call @|scanner-file-location| on any kind of value, but it might
+  not be very useful.  This function exists to do the work of appropriately
+  specialized methods on @|file-location|.
+\end{describe}
+
+\begin{describe*}
+    {\dhead{gf}{scanner-filename @<scanner> @> @<string>}
+     \dhead{gf}{scanner-line @<scanner> @> @<integer>}
+     \dhead{gf}{scanner-column @<scanner> @> @<integer>}}
+  Return the filename, line and column components of the @<scanner>'s current
+  position, for use in assembling a @<file-location>: see the
+  @|scanner-file-location| function.
+
+  There are default methods on all three generic functions which simply
+  return nil.
+\end{describe*}
+
+\subsection{Character scanners} \label{sec:parsing.scanner.char}
+
+Character scanners are scanners which read sequences of characters.
+
+\begin{describe}{cls}{character-scanner () \&key}
+  Base class for character scanners.  This provides some very basic
+  functionality.
+
+  Not all character scanners are subclasses of @|character-scanner|.
+\end{describe}
+
+\begin{describe}{gf}{scanner-current-char @<scanner> @> @<character>}
+  Returns the current character.
+\end{describe}
+
+\begin{describe}{gf}{scanner-unread @<scanner> @<character>}
+  Rewind the @<scanner> by one step.  The @<chararacter> must be the previous
+  current character, and becomes the current character again.  It is an error
+  if: the @<scanner> has reached end-of-file; the @<scanner> is never been
+  stepped; or @<character> was not the previous current character.
+\end{describe}
+
+\begin{describe}{gf}
+    {scanner-interval @<scanner> @<place-a> \&optional @<place-b>
+        @> @<string>}
+  Return the characters in the @<scanner>'s input from @<place-a> up to (but
+  not including) @<place-b>.
+
+  The characters are returned as a string.  If @<place-b> is omitted, return
+  the characters up to (but not including) the current position.  It is an
+  error if @<place-b> precedes @<place-a> or they are from different
+  scanners.
+
+  This function is a character-scanner-specific extension to the
+  place-capture protocol; not all character scanners implement the
+  place-capture protocol, and some that do may not implement this function.
+\end{describe}
+
+\subsubsection{Stream access to character scanners}
+Sometimes it can be useful to apply the standard Lisp character input
+operations to the sequence of characters held by a character scanner.
+
+\begin{describe}{gf}{make-scanner-stream @<scanner> @> @<stream>}
+  Returns a fresh input @|stream| object which fetches input characters from
+  the character scanner object @<scanner>.  Reading characters from the
+  stream steps the scanner.  The stream will reach end-of-file when the
+  scanner reports end-of-file.  If the scanner implements the file-location
+  protocol then reading from the stream will change the file location in an
+  appropriate manner.
+
+  This is mostly useful for applying standard Lisp stream functions, most
+  particularly the @|read| function, in the middle of a parsing operation.
+\end{describe}
+
+\begin{describe}{cls}{character-scanner-stream (stream) \&key :scanner}
+  A Common Lisp input @|stream| object which works using the character
+  scanner protocol.  Any @<scanner> which implements the base scanner and
+  character scanner protocols is suitable.  See @|make-scanner-stream|.
+\end{describe}
+
+\subsection{String scanners} \label{sec:parsing.scanner.string}
+
+A \emph{string scanner} is a simple kind of character scanner which reads
+input from a string object.  String scanners implement the character scanner
+and place-capture protocols.
+
+\begin{describe}{cls}{string-scanner}
+  The class of string scanners.  The @|string-scanner| class is not a
+  subclass of @|character-scanner|.
+\end{describe}
+
+\begin{describe}{fun}{string-scanner-p @<value> @> @<generalized-boolean>}
+  Return non-nil if @<value> is a @|string-scanner| object; otherwise return
+  nil.
+\end{describe}
+
+\begin{describe}{fun}
+    {make-string-scanner @<string> \&key :start :end @> @<string-scanner>}
+  Construct and return a fresh @|string-scanner| object.  The new scanner
+  will read characters from @<string>, starting at index @<start> (which
+  defaults to zero), and continuing until it reaches index @<end> (defaults
+  to the end of the @<string>).
+\end{describe}
+
+\subsection{Character buffer scanners} \label{sec:parsing.scanner.charbuf}
+
+A \emph{character buffer scanner}, or \emph{charbuf scanner} for short, is an
+efficient scanner for reading characters from an input stream.  Charbuf
+scanners implements the basic scanner, character buffer, place-capture, and
+file-location protocols.
+
+\begin{describe}{cls}
+    {charbuf-scanner (character-scanner)
+        \&key :stream :filename :line :column}
+  The class of charbuf scanners.  The scanner will read characters from
+  @<stream>.  Charbuf scanners implement the file-location protocol: the
+  initial location is set from the given @<filename>, @<line> and @<column>;
+  the scanner will update the location as it reads its input.
+\end{describe}
+
+\begin{describe}{cls}{charbuf-scanner-place}
+  The class of place objects captured by a charbuf scanner.
+\end{describe}
+
+\begin{describe}{fun}
+    {charbuf-scanner-place-p @<value> @> @<generalized-boolean>}
+  Type predicate for charbuf scanner places: returns non-nil if @<value> is a
+  place captured by a charbuf scanner, and nil otherwise.
+\end{describe}
+
+\begin{describe}{gf}
+    {charbuf-scanner-map @<scanner> @<func> \&optional @<fail>
+      \nlret @<result> @<successp> @<consumedp>}
+  Read characters from the @<scanner>'s buffers.
+
+  This is intended to be an efficient and versatile interface for reading
+  characters from a scanner in bulk.  The function @<func> is invoked
+  repeatedly, as if by
+  \begin{prog}
+    (multiple-value-bind (@<donep> @<used>) \\ \ind\ind
+        (funcall @<func> @<buf> @<start> @<end>) \- \\
+      \textrm\ldots)
+  \end{prog}
+  The argument @<buf> is a simple string; @<start> and @<end> are two
+  nonnegative fixnums, indicating that the subsequence of @<buf> between
+  @<start> (inclusive) and @<end> (exclusive) should be processed.  If
+  @<func>'s return value @<donep> is nil then @<used> is ignored: the
+  function has consumed the entire buffer and wishes to read more.  If
+  @<donep> is non-nil, then it must be a fixnum such that $@<start> \le
+  @<used> \le @<end>$: the function has consumed the buffer as far as @<used>
+  (exclusive) and has completed successfully.
+
+  If end-of-file is encountered before @<func> completes successfully then it
+  fails: the @<fail> function is called with no arguments, and is expected to
+  return two values.  If omitted, @<fail> defaults to
+  \begin{prog}
+    (lambda () \\ \ind
+      (values nil nil))%
+  \end{prog}
+
+  The @|charbuf-scanner-map| function returns three values.  The first value
+  is the non-nil @<donep> value returned by @<func> if @|charbuf-scanner-map|
+  succeeded, or the first value returned by @<fail>; the second value is @|t|
+  on success, or the second value returned by @<fail>; the third value is
+  non-nil if @<func> consumed any input, i.e., it returned with @<donep> nil
+  at least once, or with $@<used> > @<start>$.
+\end{describe}
+
+\subsection{Token scanners} \label{sec:parsing.scanner.token}
+
+\begin{describe}{cls}
+    {token-scanner () \&key :filename (:line 1) (:column 0)}
+\end{describe}
+
+\begin{describe}{gf}{token-type @<scanner> @> @<type>}
+\end{describe}
+
+\begin{describe}{gf}{token-value @<scanner> @> @<value>}
+\end{describe}
+
+\begin{describe}{gf}{scanner-token @<scanner> @> @<type> @<value>}
+\end{describe}
+
+\begin{describe}{ty}{token-scanner-place}
+\end{describe}
+
+\begin{describe}{fun}
+    {token-scanner-place-p @<value> @> @<generalized-boolean>}
+\end{describe}
+
+\subsection{List scanners}
+
+\begin{describe}{ty}{list-scanner}
+\end{describe}
+
+\begin{describe}{fun}{list-scanner-p @<value> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}{make-list-scanner @<list> @> @<list-scanner>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Parsing syntax}
+
+\begin{describe}{gf}{expand-parser-spec @<context> @<spec> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+    {expand-parser-form @<context> @<head> @<tail> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{wrap-parser @<context> @<form> @> @<wrapped-form>}
+\end{describe}
+
+\begin{describe}{mac}
+    {defparse @<name> (@[[ :context (@<var> @<context-class>) @]]
+                       @<destructuring-lambda-list-item>^*) \\ \ind
+      @<body-form>^* \-
+     \nlret @<name>}
+\end{describe}
+
+\begin{describe}{mac}
+    {with-parser-context
+        (@<context-class> @{ @<init-keyword> @<value> @}^*) \\ \ind
+      @<body-form>^* \-
+     \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{lmac}
+    {parse @<parser> @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{gf}{parser-at-eof-p @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-step @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{sym}{it}
+\end{describe}
+
+\begin{describe}{mac}
+    {if-parse (@[[ \=:result @<result-var> @!
+                     :expected @<expected-var> @! \+ \\
+                     :consumedp @<consumed-var> @]]) \- \\ \ind\ind
+        @<parser> \- \\
+      @<consequent> \\
+      @[@<alternatve>@] \-
+     \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {when-parse (@[@<result-var>@]) @<parser> \\ \ind
+      @<body-form>^* \-
+     \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+    {cond-parse (@[[ \=:result @<result-var> @!
+                       :expected @<expected-var> @! \+ \\
+                       :consumedp @<consumed-var> @]]) \- \\ \ind
+      @{ (@<parser> @<form>^*) @}^* \-
+     \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{parse}{:eof}
+\end{describe}
+
+\begin{describe}{parseform}{lisp @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{label @<parser>}
+\end{describe}
+
+\begin{describe}{parse}{t}
+\end{describe}
+
+\begin{describe}{parseform}{t @<value>}
+\end{describe}
+
+\begin{describe}{parse}{nil}
+\end{describe}
+
+\begin{describe}{parseform}{nil @<indicator>}
+\end{describe}
+
+\begin{describe}{parseform}{when @<cond> @<parser>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {seq (@{ @<atomic-parser-spec> @! (@[@<var>@] @<parser>) @}^*) \\ \ind
+      @<body-form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{and @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{or @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{? @<parser> @[@<default>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {many (\=@<accumulator-var> @<init-form> @<update-form> \+ \\
+           @[[ \=:new @<new-var> @! :final @<final-form> @! \+ \\
+                 :min @<minimum> @! :max @<maximum> @! \\
+                 :commitp @<commitp> @]]) \-\- \\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {list (@[[ :min @<minimum> @! :max @<maximum> @!
+               :commitp @<commitp> @]])\\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+    {skip-many (@[[ :min @<minimum> @! :max @<maximum> @!
+                    :commitp @<commitp> @]])\\ \ind
+      @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{fun}{call-pluggable-parser @<symbol> \&rest @<args>}
+\end{describe}
+
+\begin{describe}{parseform}{plug @<symbol> @<arg>^*}
+\end{describe}
+
+\begin{describe}{fun}
+    {pluggable-parser-add @<symbol> @<tag> @<parser-function>}
+\end{describe}
+
+\begin{describe}{mac}
+    {define-pluggable-parser @<symbol> @<tag> @<lambda-list> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{gf}{parser-capture-place @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-restore-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-release-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+    {parser-places-must-be-released-p @<context> @> @<generalized-boolean>>}
+\end{describe}
+
+\begin{describe}{mac}
+    {with-parser-place (@<place-var> @<context>) @<body-form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{peek @<parser>}
+\end{describe}
+
+\begin{describe}{cls}{character-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-current-char @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {if-char (@[@<result-var>@]) @<condition> @<consequent> @<alternative>}
+\end{describe}
+
+\begin{describe}{parseform}{char @<character>}
+\end{describe}
+
+\begin{describe}[char]{parse}{@<character>}
+\end{describe}
+
+\begin{describe}[string]{parse}{@<string>}
+\end{describe}
+
+\begin{describe}{parse}{:any}
+\end{describe}
+
+\begin{describe}{parseform}{satisfies @<predicate>}
+\end{describe}
+
+\begin{describe}{parseform}{not @<character>}
+\end{describe}
+
+\begin{describe}{parseform}{filter @<predicate>}
+\end{describe}
+
+\begin{describe}{parse}{:whitespace}
+\end{describe}
+
+\begin{describe}{cls}{token-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-type @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-value @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}{token @<type> @[@<value>@] @[:peekp @<peek>@]}
+\end{describe}
+
+\begin{describe}[atom]{parse}{@<atom>}
+\end{describe}
+
+\begin{describe}[string]{parse}{@<string>}
+\end{describe}
+
+\begin{describe}{cls}{scanner-context () \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{parse-scanner @<context> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{cls}
+    {character-scanner-context (scanner-context character-parser-context)
+      \&key :scanner}
+\end{describe}
+
+\begin{describe}{cls}
+    {token-scanner-context (scanner-context token-parser-context)
+      \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{push-operator @<operator> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{push-value @<value> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{apply-operator @<operator> @<state>}
+\end{describe}
+
+\begin{describe}{gf}{operator-push-action @<left> @<right>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {expr \=(@[[ :nestedp @<nestedp-var> @]]) \+ \\
+            @<operand-parser> @<binop-parser>
+            @<preop-parser> @<postop-parser>}
+\end{describe}
+
+\begin{describe}{gf}{operator-left-precedence @<operator> @> @<prec>}
+\end{describe}
+
+\begin{describe}{gf}{operator-right-precedence @<operator> @> @<prec>}
+\end{describe}
+
+\begin{describe}{gf}{operator-associativity @<operator> @> @<assoc>}
+\end{describe}
+
+\begin{describe}{cls}{prefix-operator () \&key}
+\end{describe}
+
+\begin{describe}{cls}{simple-operator () \&key :name :function}
+\end{describe}
+
+\begin{describe}{cls}
+    {simple-unary-operator (simple-operator) \&key :name :function}
+\end{describe}
+
+\begin{describe*}
+    {\quad\=\kill
+     \dhead{cls}{simple-binary-operator (simple-operator) \\ \>
+                  \&key :name :function :lprec :rprec :associativity}
+     \dhead{cls}{simple-postfix-operator (simple-unary-operator) \\ \>
+                  \&key :name :function :lprec :rprec}
+     \dhead{cls}{simple-prefix-operator
+                    (prefix-operator simple-unary-operator) \\ \>
+                  \&key :name :function :rprec}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{mac}{preop @<name> (@<operand-var> @<lprec>)
+                  @<body-form>^*
+                  @> @<prefix-operator>}
+     \dhead{mac}{postop @<name>
+                     (@<operand-var> @<lprec> @[[ :rprec @<rprec> @]])
+                  @<body-form>^*
+                  @> @<postfix-operator>}
+     \dhead{mac}{binop @<name> (@<operand-var> @<lprec> @<rprec> @<assoc>)
+                  @<body-form>^*
+                  @> @<binary-operator>}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{cls}{parenthesis () \&key :tag}
+     \dhead{cls}{open-parenthesis (parenthesis prefix-operator) \&key :tag}
+     \dhead{cls}{close-parenthesis (parenthesis) \&key :tag}}
+\end{describe*}
+
+\begin{describe*}
+    {\dhead{fun}{lparen @<tag> @> @<open-paren>}
+     \dhead{fun}{rparen @<tag> @> @<close-paren>}}
+\end{describe*}
+
+%%%-------------------------------------------------------------------------
+\section{Lexical analyser}
+
+\begin{describe}{cls}
+    {sod-token-scanner (token-scanner)
+      \&key :filename (:line 1) (:column 0) :char-scanner}
+\end{describe}
+
+\begin{describe}{fun}{define-indicator @<indicator> @<description>}
+\end{describe}
+
+\begin{describe}{fun}{syntax-error @<scanner> @<expected> \&key :continuep}
+\end{describe}
+
+\begin{describe}{fun}
+    {lexer-error @<char-scanner> @<expected> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{parseform}
+    {skip-until (@[[ :keep-end @<keep-end-flag> @]]) @<token-type>^*}
+\end{describe}
+
+\begin{describe}{parseform}{error () @<sub-parser> @<recover-parser>}
+\end{describe}
+
+\begin{describe}{fun}
+    {scan-comment @<char-scanner>
+      @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/runtime.tex b/doc/runtime.tex
new file mode 100644 (file)
index 0000000..487bcee
--- /dev/null
@@ -0,0 +1,201 @@
+%%% -*-latex-*-
+%%%
+%%% The runtime library
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Simple Object Definition system.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{The runtime library} \label{ch:runtime}
+
+This chapter describes the runtime support macros and functions defined in
+the @|<sod/sod.h>| header file.  The corresponding types are defined in
+\xref{ch:structures}.
+
+The runtime support functionality defined here generally expects that
+instances and classes inherit from the standard @|SodObject| root object.
+While the translator can (at some effort) support alternative roots, they
+will require different run-time support machinery.
+
+%%%--------------------------------------------------------------------------
+\section{Infrastructure macros} \label{ch:runtime.infra}
+
+These macros are mostly intended for use in code generated by the Sod
+translator.  Others may find them useful for special effects, but they can be
+tricky to understand and use correctly and can't really be recommended for
+general use.
+
+\begin{describe}[SOD_XCHAIN]{mac}
+    {void *SOD_CHAIN(@<chead>, const @<cls> *@<obj>);}
+  Performs a `cross-chain upcast'.
+
+  Given a pointer @<obj> to an instance of a class of type @<cls> and the
+  nickname @<chead> of the least specific class in one of @<cls>'s superclass
+  chains which does not contain @<cls> itself, @|SOD_XCHAIN| returns the
+  address of that chain's storage within the instance layout as a raw
+  @|void~*| pointer.  (Note that @<cls> is not mentioned explicitly.)
+
+  This macro is used by the generated @|@<CLASS>{}__CONV_@<CLS>| conversion
+  macros, which you are encouraged to use instead where possible.
+\end{describe}
+
+\begin{describe}[SOD_OFFSETDIFF]{mac}
+    {ptrdiff_t SOD_OFFSETDIFF(@<type>, @<member>_1, @<member>_2);}
+  Returns the signed offset between two members of a structure or union type.
+
+  Given a structure or union type @<type>, and two member names @<member>_1
+  and @<member>_2, then @|SOD_OFFSETDIFF| gives the difference, in bytes,
+  between the addresses of objects @|$x$.@<member>_1| and @|$x$.@<member>_2|
+  for any object $x$ of type @<type>.
+
+  This macro is used internally when generating vtables and is not expected
+  to be very useful elsewhere.
+\end{describe}
+
+\begin{describe}[SOD_ILAYOUT]{mac}
+    {@<cls>{}__ilayout *SOD_ILAYOUT(@<cls>, @<chead>, const void *@<obj>);}
+  Recovers the instance layout base address from a pointer to one of its
+  instance chains.
+
+  Specifically, given a class name @<cls>, the nickname @<chead> of the least
+  specific class in one of @<cls>'s superclass chains, and a pointer @<obj>
+  to the instance storage for the chain containing @<chead> within a direct
+  instance of @<cls> (i.e., not an instance of any proper subclass),
+  @|SOD_ILAYOUT| returns the a pointer to the layout structure containing
+  @<obj>.
+
+  This macro is used internally in effective method bodies and is not
+  expected to be very useful elsewhere since it's unusual to have such
+  specific knowledge about the dynamic type of an instance.  The
+  @|SOD_INSTBASE| macro (described below) is more suited to general use.
+\end{describe}
+
+\begin{describe}[SOD_CAR]{mac} {@<arg> SOD_CAR(@<arg>, @<other-arg>^*);}
+  Accepts one or more arguments and expands to just its first argument,
+  discarding the others.
+
+  It is only defined if the C implementation advertises support for C99.  It
+  is used in the definitions of message convenience macros for messages which
+  accept a variable number of arguments but no required arguments, and is
+  exported because the author has found such a thing useful in other
+  contexts.
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Utility macros} \label{sec:runtime.utility}
+
+The following macros are expected to be useful in Sod method definitions and
+client code.
+
+\begin{describe}[SOD_CLASSOF]{mac}
+    {const void *SOD_CLASSOF(const @<cls> *@<obj>);}
+  Returns the class object describing an instance's dynamic class.
+
+  Given a pointer @<obj> to an instance, @|SOD_CLASSOF| returns a pointer to
+  @<obj>'s dynamic class, which (assuming @<obj> is typed correctly in the
+  first place) will be a subclass of @<cls>.  (If you wanted the class object
+  for @<cls> itself, it's called @|@<cls>{}__class|.)
+\end{describe}
+
+\begin{describe}[SOD_INSTBASE]{mac}{void *SOD_INSTBASE(const @<cls> *@<obj>)}
+  Finds the base address of an instance's layout.
+
+  Given a pointer @<obj> to an instance, @|SOD_INSTBASE| returns the base
+  address of the storage allocated to @<obj>.  This is useful if you want to
+  free a dynamically allocated instance, for example.
+
+  This macro needs to look up an offset in @<obj>'s vtable to do its work.
+  Compare @|SOD_ILAYOUT| above, which is faster but requires precise
+  knowledge of the instance's dynamic class.
+\end{describe}
+
+\begin{describe}[SOD_CONVERT]{mac}
+    {@<cls> *SOD_CONVERT(@<cls>, const void *@<obj>);}
+
+  Perform general conversions (up-, down-, and cross-casts) on instance
+  pointers.
+
+  Given a class name @<cls> and a pointer @<obj> to an instance,
+  @|SOD_CONVERT| returns an appropriately converted pointer to @<obj> if
+  @<obj> is indeed an instance of (some subclass of) @<cls>; otherwise it
+  returns a null pointer.
+
+  This macro is a simple wrapper around the @|sod_convert| function described
+  below, which is useful in the common case that the target class is known
+  statically.
+\end{describe}
+
+\begin{describe}[SOD_DECL]{mac}{SOD_DECL(@<cls>, @<var>);}
+  Declares and initializes an instance with automatic storage duration.
+
+  Given a class name @<cls> and an identifier @<var>, @|SOD_DECL| declares
+  @<var> to be a pointer to an instance of @<cls>.  The instance is
+  initialized in the sense that its vtable and class pointers have been set
+  up, and slots for which initializers are defined are set to the appropriate
+  initial values.
+
+  The instance has automatic storage duration: pointers to it will become
+  invalid when control exits the scope of the declaration.
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Functions} \label{sec:runtime.functions}
+
+The following functions are provided in @|libsod|.
+
+\begin{describe}[sod_subclassp]{fun}
+    {int sod_subclassp(const SodClass *sub, const SodClass *super);}
+
+  Decide whether one class @<sub> is actually a subclass of another class
+  @<super>.
+
+  The @<sod_subclassp> function returns nonzero if and only if
+  @<sub> is a subclass of @<super>.
+
+  This involves a run-time trawl through the class structures: while some
+  effort has been made to make it perform well it's still not very fast.
+\end{describe}
+
+\begin{describe}[sod_convert]{fun}
+    {void *sod_convert(const SodClass *cls, const void *obj);}
+  Performs general conversions (up-, down-, and cross-casts) on instance
+  pointers.
+
+  Given a class pointer @<cls> and an instance pointer @<obj>, @|sod_convert|
+  returns an appropriately converted pointer to @<obj> in the case that
+  @<obj> is an instance of (some subclass of) @<cls>; otherwise it returns
+  null.
+
+  This involves a run-time trawl through the class structures: while some
+  effort has been made to make it perform well it's still not very fast.  For
+  upcasts (where @<cls> is a superclass of the static type of @<obj>) the
+  automatically defined conversion macros should be used instead, because
+  they're much faster and can't fail.  When the target class is known
+  statically, it's slightly more convenient to use the @|SOD_CONVERT| macro
+  instead.
+\end{describe}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/sod-backg.tex b/doc/sod-backg.tex
deleted file mode 100644 (file)
index 0f19c7d..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-%%% -*-latex-*-
-%%%
-%%% Background philosophy
-%%%
-%%% (c) 2009 Straylight/Edgeware
-%%%
-
-%%%----- Licensing notice ---------------------------------------------------
-%%%
-%%% This file is part of the Simple Object Definition system.
-%%%
-%%% SOD is free software; you can redistribute it and/or modify
-%%% it under the terms of the GNU General Public License as published by
-%%% the Free Software Foundation; either version 2 of the License, or
-%%% (at your option) any later version.
-%%%
-%%% SOD is distributed in the hope that it will be useful,
-%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%%% GNU General Public License for more details.
-%%%
-%%% You should have received a copy of the GNU General Public License
-%%% along with SOD; if not, write to the Free Software Foundation,
-%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-\chapter{Philosophical background}
-
-%%%--------------------------------------------------------------------------
-\section{Superclass linearization}
-
-Before making any decisions about relationships between superclasses, Sod
-\emph{linearizes} them, i.e., imposes a total order consistent with the
-direct-subclass/superclass partial order.
-
-In the vague hope that we don't be completely bogged down in formalism by the
-end of this, let's introduce some notation.  We'll fix some class $z$ and
-consider its set of superclasses $S(z) = \{ a, b, \dots \}$.  We can define a
-relation $c \prec_1 d$ if $c$ is a direct subclass of $d$, and extend it by
-taking the reflexive, transitive closure: $c \preceq d$ if and only if
-\begin{itemize}
-\item $c = d$, or
-\item there exists some class $x$ such that $c \prec_1 x$ and $x \preceq d$.
-\end{itemize}
-This is the `is-subclass-of' relation we've been using so far.\footnote{%
-  In some object systems, notably Flavors, this relation is allowed to fail
-  to be a partial order because of cycles in the class graph.  I haven't
-  given a great deal of thought to how well Sod would cope with a cyclic
-  class graph.} %
-
-The problem comes when we try to resolve inheritance questions.  A class
-should inherit behaviour from its superclasses; but, in a world of multiple
-inheritance, which one do we choose?  We get a simple version of this problem
-when we try to resolve inheritance of slot initializers: only one initializer
-can be inherited.
-
-We start by collecting into a set~$I$ the classes which define an initializer
-for the slot.  If $I$ contains both a class $x$ and one of $x$'s superclasses
-then we should prefer $x$ and consider the superclass to be overridden.  So
-we should confine our attention to \emph{least} classes: a member $x$ of a
-set $I$ is least, with respect to a particular partial order, if $y \preceq
-x$ only when $x = y$.  If there is a single least class in our set the we
-have a winner.  Otherwise we want some way to choose among them.
-
-This is not uncontroversial.  Languages such as \Cplusplus\ refuse to choose
-among least classes; instead, any program in which such a choice must be made
-is simply declared erroneous.
-
-Simply throwing up our hands in horror at this situation is satisfactory when
-we only wanted to pick one `winner', as we do for slot initializers.
-However, method combination is a much more complicated business.  We don't
-want to pick just one winner: we want to order all of the applicable methods
-in some way.  Insisting that there is a clear winner at every step along the
-chain is too much of an imposition.  Instead, we \emph{linearize} the
-classes.
-
-%%%--------------------------------------------------------------------------
-\section{Invariance, covariance, contravariance}
-
-In Sod, at least with regard to the existing method combinations, method
-types are \emph{invariant}.  This is not an accident, and it's not due to
-ignorance.
-
-The \emph{signature} of a function, method or message describes its argument
-and return-value types.  If a method's arguments are an integer and a string,
-and it returns a character, we might write its signature as
-\[ (@|int|, @|string|) \to @|char| \]
-In Sod, a method's arguments have to match its message's arguments precisely,
-and the return type must either be @|void| -- for a dæmon method -- or again
-match the message's return type.  This is argument and return-type
-\emph{invariance}.
-
-Some object systems allow methods with subtly different signatures to be
-defined on a single message.  In particular, since the idea is that instances
-of a subclass ought to be broadly compatible~(see \xref{sec:phil.lsp}) with
-existing code which expects instances of a superclass, we might be able to
-get away with bending method signatures one way or another to permit this.
-
-\Cplusplus\ permits \emph{return-type covariance}, where a method's return
-type can be a subclass of the return type specified by a less-specific
-method.  Eiffel allows \emph{argument covariance}, where a method's arguments
-can be subclasses of the arguments specified by a less-specific
-method.\footnote{%
-  Attentive readers will note that I ought to be talking about pointers to
-  instances throughout.  I'm trying to limit the weight of the notation.
-  Besides, I prefer data models as found in Lisp and Python where all values
-  are held by reference.} %
-
-Eiffel's argument covariance is unsafe.\footnote{%
-  Argument covariance is correct if you're doing runtime dispatch based on
-  argument types.  Eiffel isn't: it's single dispatch, like Sod is.} %
-Suppose that we have two pairs of classes, $a \prec_1 b$ and $c \prec_1 d$.
-Class $b$ defines a message $m$ with signature $d \to @|int|$; class $a$
-defines a method with signature $c \to @|int|$.  This means that it's wrong
-to send $m$ to an instance $a$ carrying an argument of type $d$.  But of
-course, we can treat an instance of $a$ as if it's an instance of $b$,
-whereupon it appears that we are permitted to pass a~$c$ in our message.  The
-result is a well-known hole in the type system.  Oops.
-
-\Cplusplus's return-type covariance is fine.  Also fine is argument
-\emph{contravariance}.  If $b$ defined its message to have signature $c \to
-@|int|$, and $a$ were to broaden its method to $d \to @|int|$, there'd be no
-problem.  All $c$s are $d$s, so viewing an $a$ as a $b$ does no harm.
-
-All of this fiddling with types is fine as long as method inheritance or
-overriding is an all-or-nothing thing.  But Sod has method combinations,
-where applicable methods are taken from the instance's class and all its
-superclasses and combined.  And this makes everything very messy.
-
-It's possible to sort all of the mess out in the generated effective method
--- we'd just have to convert the arguments to the types that were expected by
-the direct methods.  This would require expensive run-time conversions of all
-of the non-invariant arguments and return values.  And we'd need some
-complicated rule so that we could choose sensible types for the method
-entries in our vtables.  Something like this:
-\begin{quote} \itshape
-  For each named argument of a message, there must be a unique greatest type
-  among the types given for that argument by the applicable methods; and
-  there must be a unique least type among all of the return types of the
-  applicable methods.
-\end{quote}
-I have visions of people wanting to write special no-effect methods whose
-only purpose is to guide the translator around the class graph properly.
-Let's not.
-
-%% things to talk about:
-%% Liskov substitution principle and why it's mad
-
-%%%----- That's all, folks --------------------------------------------------
-
-%%% Local variables:
-%%% mode: LaTeX
-%%% TeX-master: "sod.tex"
-%%% TeX-PDF-mode: t
-%%% End:
diff --git a/doc/sod.sty b/doc/sod.sty
new file mode 100644 (file)
index 0000000..56fc726
--- /dev/null
@@ -0,0 +1,205 @@
+%%% -*-latex-*-
+%%%
+%%% Styles and other hacking for the Sod manual
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\ProvidesPackage{sod}
+
+%% More reference types.
+\defxref{p}{part}
+
+%% Other languages with special typesetting.
+\def\Cplusplus{C\kern-\p@++}
+\def\Csharp{C\#}
+
+%% Special maths notation.
+\def\chain#1#2{\mathsf{ch}_{#1}(#2)}
+\def\chainhead#1#2{\mathsf{hd}_{#1}(#2)}
+\def\chaintail#1#2{\mathsf{tl}_{#1}(#2)}
+
+%% Other mathematical tweaks.
+\let\implies\Rightarrow
+\let\epsilon\varepsilon
+
+%% A table heading cell.  Clone and hack \multicolumn.
+\def\thd{\omit\@ifnextchar[\thd@{\thd@[l]}}
+\def\thd@[#1]#2{%
+  \begingroup
+    \tab@multicol \tab@initread \let\tab@looped\tab@err@multi
+    \tab@preamble{}\def\tab@midtext{\bfseries#2}\tab@readpreamble{#1}%
+    \the\tab@preamble
+  \endgroup \ignorespaces
+}
+
+%% Unix manpage references.
+\def\man#1#2{\textbf{#1}(#2)}
+
+%% Listings don't need to be small.
+\let\listingsize\relax
+
+%% Metavariables are italics without decoration.
+\def\syntleft{\normalfont\itshape}
+\let\syntright\empty
+
+%% Literal code is in sans face.
+\let\codeface\sffamily
+\def\code#1{\ifmmode\hbox\fi{\normalfont\codeface\/#1\/}}
+\def\ulitleft{\normalfont\codeface}
+\let\ulitright\empty
+
+%% Conditionally enter maths mode.  Can't use \ensuremath here because we
+%% aren't necessarily sure where the maths will actually end.
+\let\m@maybe@end\relax
+\def\m@maybe{\ifmmode\else$\let\m@maybe@end$\fi}
+
+%% Standard syntax shortcuts.
+\atdef <#1>{\synt{#1}\@scripts}
+\atdef "#1"{\lit*{#1}\@scripts}
+\atdef `#1'{\lit{#1}\@scripts}
+\atdef |#1|{\textsf{#1}\@scripts}
+
+%% A handy abbreviation; `\\' itself is too good to steal.
+\atdef \\{\textbackslash}
+
+%% Intercept grammar typesetting and replace the vertical bar with the
+%% maths-font version.
+\let\@@grammar\grammar
+\def\grammar{\def\textbar{\hbox{$|$}}\@@grammar}
+
+%% Collect super- and subscripts.  (Note that underscores are active for the
+%% most part.)  When we're done, end maths mode if we entered it
+%% conditionally.
+\def\@scripts{\futurelet\@ch\@scripts@i}
+\begingroup\lccode`\~=`\_\lowercase{\endgroup
+\def\@scripts@i{\if1\ifx\@ch~1\else\ifx\@ch^1\else0\fi\fi%
+  \expandafter\@scripts@ii\else\expandafter\m@maybe@end\fi}}
+\def\@scripts@ii#1#2{\m@maybe#1{#2}\@scripts}
+
+%% Doubling characters, maybe.  Either way, chain onto \@scripts.
+\def\dbl@maybe#1{\let\@tempa#1\futurelet\@ch\dbl@maybe@i}
+\def\dbl@maybe@i{\m@maybe\ifx\@ch\@tempa\@tempa\!\@tempa%
+  \expandafter\@firstoftwo\expandafter\@scripts%
+  \else\@tempa\expandafter\@scripts\fi}
+
+%% Extra syntax for Lisp templates.  These produce the maths-font versions of
+%% characters, which should contrast well against the sans face used for
+%% literals.
+\atdef [{\dbl@maybe[}
+\atdef ]{\dbl@maybe]}
+\atdef {{\m@maybe\{\@scripts}
+\atdef }{\m@maybe\}\@scripts}
+\atdef ({\m@maybe(\@scripts}
+\atdef ){\m@maybe)\@scripts}
+\atdef !{\m@maybe|\@scripts}
+\def\returns{\m@maybe\longrightarrow\m@maybe@end\hspace{0.5em}\ignorespaces}
+\atdef >{\leavevmode\unskip\hspace{0.5em}\returns}
+\atdef -#1{\if>#1{\ensuremath\rightarrow}\fi}
+
+%% Comment setting.
+\atdef ;#1\\{\normalfont\itshape;#1\\}
+
+%% Environment for setting programs.  Newlines are explicit, because
+%% otherwise I need comments in weird places to make the vertical spacing
+%% come out properly.  You can write `\obeylines' if you really want to.
+\def\prog{\codeface\quote\tabbing}
+\def\endprog{\endtabbing\endquote}
+\def\ind{\quad\=\+\kill}
+
+%% Put a chunk of text in a box.
+\newenvironment{boxy}[1][\q@]{%
+  \savenotes
+  \dimen@\linewidth\advance\dimen@-1.2pt\advance\dimen@-2ex%
+  \medskip%
+  \vbox\bgroup\hrule\hbox\bgroup\vrule%
+  \vbox\bgroup\vskip1ex\hbox\bgroup\hskip1ex\minipage\dimen@%
+  \def\@temp{#1}\ifx\@temp\q@\else\leavevmode{\headfam\bfseries#1\quad}\fi%
+}{%
+  \endminipage\hskip1ex\egroup\vskip1ex\egroup%
+  \vrule\egroup\hrule\egroup%
+  \medskip%
+  \spewnotes%
+}
+
+%% Lisp documentation machinery.
+\def\definedescribecategory#1#2{\@namedef{cat!#1}{#2}}
+\def\describecategoryname#1{%
+  \expandafter\let\expandafter\@tempa\csname cat!#1\endcsname%
+  \ifx\@tempa\relax#1\else\@tempa\fi}
+\definedescribecategory{sym}{symbol}
+\definedescribecategory{fun}{function}
+\definedescribecategory{gf}{generic function}
+\definedescribecategory{var}{variable}
+\definedescribecategory{const}{constant}
+\definedescribecategory{meth}{primary method}
+\definedescribecategory{ar-meth}{around method}
+\definedescribecategory{be-meth}{before method}
+\definedescribecategory{af-meth}{after method}
+\definedescribecategory{cls}{class}
+\definedescribecategory{ty}{type}
+\definedescribecategory{mac}{macro}
+\definedescribecategory{lmac}{local macro}
+\definedescribecategory{parse}{parser spec}
+\definedescribecategory{parseform}{parser form}
+\definedescribecategory{opt}{option handler}
+\definedescribecategory{optmac}{option macro}
+\def\nlret{\\\hspace{4em}\returns}
+
+\def\q@{\q@}
+\def\parse@dhd#1{\@ifnextchar[{\parse@dhd@a{#1}}{\parse@dhd@c{#1}}}
+\def\parse@dhd@a#1[#2]{#1{#2}}
+\def\parse@dhd@c#1#2#3{\parse@dhd@cc{#1}{#2}{#3}#3 \q@}
+\def\parse@dhd@cc#1#2#3#4 #5\q@{#1{#4}{#2}{#3}}
+
+\newif\if@dheadfirst
+\def\dhead{\parse@dhd\dhead@}
+\def\dhead@#1#2#3{%
+  \if@dheadfirst\global\@dheadfirstfalse\else\relax\\[\smallskipamount]\fi%
+  {\let\protect\@empty\def\@uscore{_\@gobble}\message{#2:#1}%
+   \def\@uscore{-\@gobble}\edef\@tempa{\noexpand\label{#2:#1}}\@tempa}%
+  \rlap{\rightline{\normalfont\bfseries[\describecategoryname{#2}]}}%
+  #3%
+}
+
+\def\desc@begin#1{%
+  \normalfont%
+  \if@nobreak\else\par\goodbreak\fi%
+  \global\@dheadfirsttrue%
+  \begingroup%
+    \codeface%
+    \let\@endparenv\relax%
+    \clubpenalty\@M \widowpenalty\@M \interlinepenalty50%
+    \tabbing#1\endtabbing%
+  \endgroup%
+  \penalty\@M\@afterheading%
+  \list{}{\rightmargin\z@\topsep\z@}\item%
+}
+\let\desc@end\endlist
+
+\@namedef{describe*}#1{\desc@begin{#1}}
+\expandafter\let\csname enddescribe*\endcsname\desc@end
+\def\describe{\parse@dhd\desc@}
+\def\desc@#1#2#3{\desc@begin{\dhead@{#1}{#2}{#3}}}
+\let\enddescribe\desc@end
+
+%%%----- That's all, folks --------------------------------------------------
+\endinput
index 8a46735..3ee1a5d 100644 (file)
-\documentclass[noarticle]{strayman}
+%%% -*-latex-*-
+%%%
+%%% Description of the internal class structure and protocol
+%%%
+%%% (c) 2009 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Simple Object Definition system.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\documentclass[noarticle, titlepage]{strayman}
+
+\errorcontextlines=999
 
 \usepackage[T1]{fontenc}
 \usepackage[utf8]{inputenc}
 \usepackage[palatino, helvetica, courier, maths=cmr]{mdwfonts}
+\usepackage{tikz}
 \usepackage{syntax}
 \usepackage{sverb}
 \usepackage{mdwtab}
+\usepackage[mdwmargin]{mdwthm}
+\usepackage{amssymb}
 \usepackage{footnote}
 \usepackage{at}
 \usepackage{mdwref}
 
+\usepackage{sod}
+
 \title{A Sensible Object Design for C}
 \author{Mark Wooding}
 
-\makeatletter
-
-\errorcontextlines999
-
-\def\syntleft{\normalfont\itshape}
-\let\syntright\empty
-
-\let\codeface\sffamily
-
-\def\ulitleft{\normalfont\codeface}
-\let\ulitright\empty
-
-\let\listingsize\relax
-
-\let\epsilon\varepsilon
-
-\atdef <#1>{\synt{#1}\@scripts}
-\atdef "#1"{\lit*{#1}\@scripts}
-\atdef `#1'{\lit{#1}\@scripts}
-\atdef |#1|{\textsf{#1}\@scripts}
-\def\dbl@maybe#1{\let\@tempa#1\futurelet\@ch\dbl@maybe@i}
-\def\dbl@maybe@i{\m@maybe\ifx\@ch\@tempa\@tempa\!\@tempa%
-  \expandafter\@firstoftwo\expandafter\@scripts%
-  \else\@tempa\expandafter\@scripts\fi}
-\atdef [{\dbl@maybe[}
-\atdef ]{\dbl@maybe]}
-\atdef {{\m@maybe\{\@scripts}
-\atdef }{\m@maybe\}\@scripts}
-\atdef ({\m@maybe(\@scripts}
-\atdef ){\m@maybe)\@scripts}
-\atdef !{\m@maybe|\@scripts}
-\atdef to{\leavevmode\unskip\quad\m@maybe\longrightarrow\m@maybe@end\quad}
-\let\m@maybe@end\relax
-\def\m@maybe{\ifmmode\else$\let\m@maybe@end$\fi}
-\def\@scripts{\futurelet\@ch\@scripts@i}
-
-\atdef ;#1\\{\normalfont\itshape;#1\\}
-\let\@@grammar\grammar
-\def\grammar{\def\textbar{\hbox{$|$}}\@@grammar}
-
-\begingroup\lccode`\~=`\_\lowercase{\endgroup
-\def\@scripts@i{\if1\ifx\@ch~1\else\ifx\@ch^1\else0\fi\fi%
-  \expandafter\@scripts@ii\else\expandafter\m@maybe@end\fi}}
-\def\@scripts@ii#1#2{\m@maybe#1{#2}\@scripts}
-
-\def\Cplusplus{C\kern-\p@++}
-\def\Csharp{C\#}
-\def\man#1#2{\textbf{#1}(#2)}
-
-\begingroup\lccode`\~=`\
-\lowercase{
-\endgroup
-\def\prog{%
-  \codeface%
-  \quote%
-  \let\old@nl\\%
-  \obeylines%
-  \tabbing%
-  \global\let~\\%
-  \global\let\\\textbackslash%
-}
-\def\endprog{%
-  \endtabbing%
-  \global\let\\\old@nl%
-  \endquote%
-}}
-
-\newenvironment{boxy}[1][\q@]{%
-  \dimen@\linewidth\advance\dimen@-1.2pt\advance\dimen@-2ex%
-  \medskip%
-  \vbox\bgroup\hrule\hbox\bgroup\vrule%
-  \vbox\bgroup\vskip1ex\hbox\bgroup\hskip1ex\minipage\dimen@%
-  \def\@temp{#1}\ifx\@temp\q@\else\leavevmode{\headfam\bfseries#1\quad}\fi%
-}{%
-  \endminipage\hskip1ex\egroup\vskip1ex\egroup%
-  \vrule\egroup\hrule\egroup%
-  \medskip%
-}
-
-\def\definedescribecategory#1#2{\@namedef{cat!#1}{#2}}
-\def\describecategoryname#1{%
-  \expandafter\let\expandafter\@tempa\csname cat!#1\endcsname%
-  \ifx\@tempa\relax#1\else\@tempa\fi}
-\definedescribecategory{fun}{function}
-\definedescribecategory{gf}{generic function}
-\definedescribecategory{var}{variable}
-\definedescribecategory{const}{constant}
-\definedescribecategory{meth}{primary method}
-\definedescribecategory{ar-meth}{around-method}
-\definedescribecategory{be-meth}{before-method}
-\definedescribecategory{af-meth}{after-method}
-\definedescribecategory{cls}{class}
-\definedescribecategory{ty}{type}
-\definedescribecategory{mac}{macro}
-
-\def\q@{\q@}
-\newenvironment{describe}[3][\q@]{%
-  \normalfont%
-  \par\goodbreak%
-  \vspace{\bigskipamount}%
-  \setbox\z@\hbox{\bfseries[\describecategoryname{#2}]}%
-  \dimen@\linewidth\advance\dimen@-\wd\z@%
-  \def\@temp##1 ##2\q@{\message{#2:##1}\label{#2:##1}}%
-  \def\@tempa{#1}\ifx\@tempa\q@\@temp#3 \q@\else\@temp{#1} \\\fi%
-  \edef\@temp{{\the\linewidth}{@{}p{\the\dimen@}%
-      @{\extracolsep{\fill}}l@{\extracolsep{0pt}}}}%
-  \noindent\csname tabular*\expandafter\endcsname\@temp%
-  \tabbing\codeface#3\endtabbing&\unhbox\z@\\\endtabular%
-%  \@afterheading%
-  \list{}{\rightmargin\z@}\item%
-}{%
-  \endlist%
-}
-
-\def\push{\quad\=\+\kill}
-
 \begin{document}
 
+\frontmatter
 \maketitle
 
-\include{sod-tut}
-
 %%%--------------------------------------------------------------------------
-\chapter{Internals}
 
-\section{Generated names}
+\tableofcontents
 
-The generated names for functions and objects related to a class are
-constructed systematically so as not to interfere with each other.  The rules
-on class, slot and message naming exist so as to ensure that the generated
-names don't collide with each other.
-
-The following notation is used in this section.
-\begin{description}
-\item[@<class>] The full name of the `focus' class: the one for which we are
-  generating name.
-\item[@<super-nick>] The nickname of a superclass.
-\item[@<head-nick>] The nickname of the chain-head class of the chain
-  in question.
-\end{description}
-
-\subsection{Instance layout}
+\mainmatter
 
 %%%--------------------------------------------------------------------------
-\section{Syntax}
-\label{sec:syntax}
-
-Fortunately, Sod is syntactically quite simple.  I've used a little slightly
-unusual notation in order to make the presentation easier to read.
-\begin{itemize}
-\item $\epsilon$ denotes the empty nonterminal:
-  \begin{quote}
-    $\epsilon$ ::=
-  \end{quote}
-\item @[@<item>@] means an optional @<item>:
-  \begin{quote}
-    \syntax{@[<item>@] ::= $\epsilon$ @! <item>}
-  \end{quote}
-\item @<item>^* means a sequence of zero or more @<item>s:
-  \begin{quote}
-    \syntax{@<item>^* ::= $\epsilon$ @! @<item>^* <item>}
-  \end{quote}
-\item @<item>^+ means a sequence of one or more @<item>s:
-  \begin{quote}
-    \syntax{@<item>^+ ::= <item> @<item>^*}
-  \end{quote}
-\item @<item-list> means a sequence of one or more @<item>s separated
-  by commas:
-  \begin{quote}
-    \syntax{<item-list> ::= <item> @! <item-list> "," <item>}
-  \end{quote}
-\end{itemize}
-
-\subsection{Lexical syntax}
-\label{sec:syntax.lex}
-
-Whitespace and comments are discarded.  The remaining characters are
-collected into tokens according to the following syntax.
-
-\begin{grammar}
-<token> ::= <identifier>
-\alt <reserved-word>
-\alt <string-literal>
-\alt <char-literal>
-\alt <integer-literal>
-\alt <punctuation>
-\end{grammar}
-
-This syntax is slightly ambiguous.  The following two rules serve to
-disambiguate:
-\begin{enumerate}
-\item Reserved words take precedence.  All @<reserved-word>s are
-  syntactically @<identifier>s; Sod resolves the ambiguity in favour of
-  @<reserved-word>.
-\item `Maximal munch'.  In other cases, at each stage we take the longest
-  sequence of characters which could be a token.
-\end{enumerate}
-
-\subsubsection{Identifiers} \label{sec:syntax.lex.id}
-
-\begin{grammar}
-<identifier> ::= <id-start-char> @<id-body-char>^*
-
-<id-start-char> ::= <alpha-char> | "_"
-
-<id-body-char> ::= <id-start-char> @! <digit-char>
-
-<alpha-char> ::= "A" | "B" | \dots\ | "Z"
-\alt "a" | "b" | \dots\ | "z"
-\alt <extended-alpha-char>
-
-<digit-char> ::= "0" | <nonzero-digit-char>
-
-<nonzero-digit-char> ::= "1" | "2" $| \cdots |$ "9"
-\end{grammar}
-
-The precise definition of @<alpha-char> is left to the function
-\textsf{alpha-char-p} in the hosting Lisp system.  For portability,
-programmers are encouraged to limit themselves to the standard ASCII letters.
-
-\subsubsection{Reserved words} \label{sec:syntax.lex.reserved}
-
-\begin{grammar}
-<reserved-word> ::=
-"char" | "class" | "code" | "const" | "double" | "enum" |
-"extern" | "float" | "import" | "int" | "lisp" | "load" | "long"
-| "restrict" | "short" | "signed" | "struct" | "typename" |
-"union" | "unsigned" | "void" | "volatile"
-\end{grammar}
-
-Many of these are borrowed from~C; however, some (e.g., @"import" and
-@"lisp") are not, and some C reserved words are not reserved (e.g.,
-@"static").
-
-\subsubsection{String and character literals} \label{sec:syntax.lex.string}
-
-\begin{grammar}
-<string-literal> ::= "\"" @<string-literal-char>^* "\""
-
-<char-literal> ::= "'" <char-literal-char> "'"
-
-<string-literal-char> ::= any character other than "\\" or "\""
-\alt "\\" <char>
-
-<char-literal-char> ::= any character other than "\\" or "'"
-\alt "\\" <char>
-
-<char> ::= any single character
-\end{grammar}
-
-The syntax for string and character literals differs from~C.  In particular,
-escape sequences such as @`\textbackslash n' are not recognized.  The use
-of string and character literals in Sod, outside of C~fragments, is limited,
-and the simple syntax seems adequate.  For the sake of future compatibility,
-the use of character sequences which resemble C escape sequences is
-discouraged.
-
-\subsubsection{Integer literals} \label{sec:syntax.lex.int}
-
-\begin{grammar}
-<integer-literal> ::= <decimal-integer>
-\alt <binary-integer>
-\alt <octal-integer>
-\alt <hex-integer>
-
-<decimal-integer> ::= <nonzero-digit-char> @<digit-char>^*
-
-<binary-integer> ::= "0" @("b"|"B"@) @<binary-digit-char>^+
-
-<binary-digit-char> ::= "0" | "1"
-
-<octal-integer> ::= "0" @["o"|"O"@] @<octal-digit-char>^+
-
-<octal-digit-char> ::= "0" | "1" $| \cdots |$ "7"
-
-<hex-integer> ::= "0" @("x"|"X"@) @<hex-digit-char>^+
-
-<hex-digit-char> ::= <digit-char>
-\alt "A" | "B" | "C" | "D" | "E" | "F"
-\alt "a" | "b" | "c" | "d" | "e" | "f"
-\end{grammar}
-
-Sod understands only integers, not floating-point numbers; its integer syntax
-goes slightly beyond C in allowing a @`0o' prefix for octal and @`0b' for
-binary.  However, length and signedness indicators are not permitted.
-
-\subsubsection{Punctuation} \label{sec:syntax.lex.punct}
-
-\begin{grammar}
-<punctuation> ::= any character other than "\"" or "'"
-\end{grammar}
-
-Due to the `maximal munch' rule, @<punctuation> tokens cannot be
-alphanumeric.
-
-\subsubsection{Comments} \label{sec:lex-comment}
-
-\begin{grammar}
-<comment> ::= <block-comment>
-\alt <line-comment>
-
-<block-comment> ::=
-  "/*"
-  @<not-star>^* @(@<star>^+ <not-star-or-slash> @<not-star>^*@)^*
-  @<star>^*
-  "*/"
-
-<star> ::= "*"
-
-<not-star> ::= any character other than "*"
-
-<not-star-or-slash> ::= any character other than "*" or  "/"
-
-<line-comment> ::= "//" @<not-newline>^* <newline>
-
-<newline> ::= a newline character
-
-<not-newline> ::= any character other than newline
-\end{grammar}
-
-Comments are exactly as in C99: both traditional block comments `\texttt{/*}
-\dots\ \texttt{*/}' and \Cplusplus-style `\texttt{//} \dots' comments are
-permitted and ignored.
-
-\subsection{Special nonterminals}
-\label{sec:special-nonterminals}
-
-Aside from the lexical syntax presented above (\xref{sec:lexical-syntax}),
-two special nonterminals occur in the module syntax.
-
-\subsubsection{S-expressions} \label{sec:syntax-sexp}
-
-\begin{grammar}
-<s-expression> ::= an S-expression, as parsed by the Lisp reader
-\end{grammar}
-
-When an S-expression is expected, the Sod parser simply calls the host Lisp
-system's \textsf{read} function.  Sod modules are permitted to modify the
-read table to extend the S-expression syntax.
-
-S-expressions are self-delimiting, so no end-marker is needed.
-
-\subsubsection{C fragments} \label{sec:syntax.lex.cfrag}
-
-\begin{grammar}
-<c-fragment> ::= a sequence of C tokens, with matching brackets
-\end{grammar}
-
-Sequences of C code are simply stored and written to the output unchanged
-during translation.  They are read using a simple scanner which nonetheless
-understands C comments and string and character literals.
-
-A C fragment is terminated by one of a small number of delimiter characters
-determined by the immediately surrounding context -- usually a closing brace
-or bracket.  The first such delimiter character which is not enclosed in
-brackets, braces or parenthesis ends the fragment.
-
-\subsection{Module syntax} \label{sec:syntax-module}
-
-\begin{grammar}
-<module> ::= @<definition>^*
-
-<definition> ::= <import-definition>
-\alt <load-definition>
-\alt <lisp-definition>
-\alt <code-definition>
-\alt <typename-definition>
-\alt <class-definition>
-\end{grammar}
-
-A module is the top-level syntactic item.  A module consists of a sequence of
-definitions.
-
-\subsection{Simple definitions} \label{sec:syntax.defs}
-
-\subsubsection{Importing modules} \label{sec:syntax.defs.import}
-
-\begin{grammar}
-<import-definition> ::= "import" <string> ";"
-\end{grammar}
-
-The module named @<string> is processed and its definitions made available.
-
-A search is made for a module source file as follows.
-\begin{itemize}
-\item The module name @<string> is converted into a filename by appending
-  @`.sod', if it has no extension already.\footnote{%
-    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
-    :type "SOD" :case :common))}, so exactly what this means varies
-    according to the host system.} %
-\item The file is looked for relative to the directory containing the
-  importing module.
-\item If that fails, then the file is looked for in each directory on the
-  module search path in turn.
-\item If the file still isn't found, an error is reported and the import
-  fails.
-\end{itemize}
-At this point, if the file has previously been imported, nothing further
-happens.\footnote{%
-  This check is done using \textsf{truename}, so it should see through simple
-  tricks like symbolic links.  However, it may be confused by fancy things
-  like bind mounts and so on.} %
-
-Recursive imports, either direct or indirect, are an error.
-
-\subsubsection{Loading extensions} \label{sec:syntax.defs.load}
-
-\begin{grammar}
-<load-definition> ::= "load" <string> ";"
-\end{grammar}
-
-The Lisp file named @<string> is loaded and evaluated.
-
-A search is made for a Lisp source file as follows.
-\begin{itemize}
-\item The name @<string> is converted into a filename by appending @`.lisp',
-  if it has no extension already.\footnote{%
-    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
-    :type "LISP" :case :common))}, so exactly what this means varies
-    according to the host system.} %
-\item A search is then made in the same manner as for module imports
-  (\xref{sec:syntax-module}).
-\end{itemize}
-If the file is found, it is loaded using the host Lisp's \textsf{load}
-function.
-
-Note that Sod doesn't attempt to compile Lisp files, or even to look for
-existing compiled files.  The right way to package a substantial extension to
-the Sod translator is to provide the extension as a standard ASDF system (or
-similar) and leave a dropping @"foo-extension.lisp" in the module path saying
-something like
-\begin{listing}
-(asdf:operate 'asdf:load-op :foo-extension)
-\end{listing}
-which will arrange for the extension to be compiled if necessary.
-
-(This approach means that the language doesn't need to depend on any
-particular system definition facility.  It's bad enough already that it
-depends on Common Lisp.)
-
-\subsubsection{Lisp escapes} \label{sec:syntax.defs.lisp}
-
-\begin{grammar}
-<lisp-definition> ::= "lisp" <s-expression> ";"
-\end{grammar}
-
-The @<s-expression> is evaluated immediately.  It can do anything it likes.
-
-\textbf{Warning!}  This means that hostile Sod modules are a security hazard.
-Lisp code can read and write files, start other programs, and make network
-connections.  Don't install Sod modules from sources that you don't
-trust.\footnote{%
-  Presumably you were going to run the corresponding code at some point, so
-  this isn't as unusually scary as it sounds.  But please be careful.} %
-
-\subsubsection{Declaring type names} \label{sec:syntax.defs.typename}
-
-\begin{grammar}
-<typename-definition> ::=
-  "typename" <identifier-list> ";"
-\end{grammar}
-
-Each @<identifier> is declared as naming a C type.  This is important because
-the C type syntax -- which Sod uses -- is ambiguous, and disambiguation is
-done by distinguishing type names from other identifiers.
-
-Don't declare class names using @"typename"; use @"class" forward
-declarations instead.
-
-\subsection{Literal code} \label{sec:syntax-code}
-
-\begin{grammar}
-<code-definition> ::=
-  "code" <identifier> ":" <identifier> @[<constraints>@]
-  "{" <c-fragment> "}"
-
-<constraints> ::= "[" <constraint-list> "]"
-
-<constraint> ::= @<identifier>^+
-\end{grammar}
-
-The @<c-fragment> will be output unchanged to one of the output files.
-
-The first @<identifier> is the symbolic name of an output file.  Predefined
-output file names are @"c" and @"h", which are the implementation code and
-header file respectively; other output files can be defined by extensions.
+\part{Tutorial} \label{p:tut}
 
-The second @<identifier> provides a name for the output item.  Several C
-fragments can have the same name: they will be concatenated together in the
-order in which they were encountered.
-
-The @<constraints> provide a means for specifying where in the output file
-the output item should appear.  (Note the two kinds of square brackets shown
-in the syntax: square brackets must appear around the constraints if they are
-present, but that they may be omitted.)  Each comma-separated @<constraint>
-is a sequence of identifiers naming output items, and indicates that the
-output items must appear in the order given -- though the translator is free
-to insert additional items in between them.  (The particular output items
-needn't be defined already -- indeed, they needn't be defined ever.)
-
-There is a predefined output item @"includes" in both the @"c" and @"h"
-output files which is a suitable place for inserting @"\#include"
-preprocessor directives in order to declare types and functions for use
-elsewhere in the generated output files.
-
-\subsection{Property sets} \label{sec:syntax.propset}
-
-\begin{grammar}
-<properties> ::= "[" <property-list> "]"
-
-<property> ::= <identifier> "=" <expression>
-\end{grammar}
-
-Property sets are a means for associating miscellaneous information with
-classes and related items.  By using property sets, additional information
-can be passed to extensions without the need to introduce idiosyncratic
-syntax.
-
-A property has a name, given as an @<identifier>, and a value computed by
-evaluating an @<expression>.  The value can be one of a number of types,
-though the only operators currently defined act on integer values only.
-
-\subsubsection{The expression evaluator} \label{sec:syntax.propset.expr}
-
-\begin{grammar}
-<expression> ::= <term> | <expression> "+" <term> | <expression> "-" <term>
-
-<term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor>
-
-<factor> ::= <primary> | "+" <factor> | "-" <factor>
-
-<primary> ::=
-     <integer-literal> | <string-literal> | <char-literal> | <identifier>
-\alt "?" <s-expression>
-\alt "(" <expression> ")"
-\end{grammar}
-
-The arithmetic expression syntax is simple and standard; there are currently
-no bitwise, logical, or comparison operators.
-
-A @<primary> expression may be a literal or an identifier.  Note that
-identifiers stand for themselves: they \emph{do not} denote values.  For more
-fancy expressions, the syntax
-\begin{quote}
-  @"?" @<s-expression>
-\end{quote}
-causes the @<s-expression> to be evaluated using the Lisp \textsf{eval}
-function.
-%%% FIXME crossref to extension docs
-
-\subsection{C types} \label{sec:syntax.c-types}
-
-Sod's syntax for C types closely mirrors the standard C syntax.  A C type has
-two parts: a sequence of @<declaration-specifier>s and a @<declarator>.  In
-Sod, a type must contain at least one @<declaration-specifier> (i.e.,
-`implicit @"int"' is forbidden), and storage-class specifiers are not
-recognized.
-
-\subsubsection{Declaration specifiers} \label{sec:syntax.c-types.declspec}
-
-\begin{grammar}
-<declaration-specifier> ::= <type-name>
-\alt "struct" <identifier> | "union" <identifier> | "enum" <identifier>
-\alt "void" | "char" | "int" | "float" | "double"
-\alt "short" | "long"
-\alt "signed" | "unsigned"
-\alt <qualifier>
-
-<qualifier> ::= "const" | "volatile" | "restrict"
-
-<type-name> ::= <identifier>
-\end{grammar}
-
-A @<type-name> is an identifier which has been declared as being a type name,
-using the @"typename" or @"class" definitions.
-
-Declaration specifiers may appear in any order.  However, not all
-combinations are permitted.  A declaration specifier must consist of zero or
-more @<qualifiers>, and one of the following, up to reordering.
-\begin{itemize}
-\item @<type-name>
-\item @"struct" @<identifier>, @"union" @<identifier>, @"enum" @<identifier>
-\item @"void"
-\item @"char", @"unsigned char", @"signed char"
-\item @"short", @"unsigned short", @"signed short"
-\item @"short int", @"unsigned short int", @"signed short int"
-\item @"int", @"unsigned int", @"signed int", @"unsigned", @"signed"
-\item @"long", @"unsigned long", @"signed long"
-\item @"long int", @"unsigned long int", @"signed long int"
-\item @"long long", @"unsigned long long", @"signed long long"
-\item @"long long int", @"unsigned long long int", @"signed long long int"
-\item @"float", @"double", @"long double"
-\end{itemize}
-All of these have their usual C meanings.
-
-\subsubsection{Declarators} \label{sec:syntax.c-types.declarator}
-
-\begin{grammar}
-<declarator>$[k]$ ::= @<pointer>^* <primary-declarator>$[k]$
-
-<primary-declarator>$[k]$ ::= $k$
-\alt "(" <primary-declarator>$[k]$ ")"
-\alt <primary-declarator>$[k]$ @<declarator-suffix>^*
-
-<pointer> ::= "*" @<qualifier>^*
-
-<declarator-suffix> ::= "[" <c-fragment> "]"
-\alt "(" <arguments> ")"
-
-<arguments> ::= $\epsilon$ | "..."
-\alt <argument-list> @["," "..."@]
-
-<argument> ::= @<declaration-specifier>^+ <argument-declarator>
-
-<argument-declarator> ::= <declarator>@[<identifier> @! $\epsilon$@]
-
-<simple-declarator> ::= <declarator>@[<identifier>@]
-
-<dotted-name> ::= <identifier> "." <identifier>
-
-<dotted-declarator> ::= <declarator>@[<dotted-name>@]
-\end{grammar}
-
-The declarator syntax is taken from C, but with some differences.
-\begin{itemize}
-\item Array dimensions are uninterpreted @<c-fragments>, terminated by a
-  closing square bracket.  This allows array dimensions to contain arbitrary
-  constant expressions.
-\item A declarator may have either a single @<identifier> at its centre or a
-  pair of @<identifier>s separated by a @`.'; this is used to refer to
-  slots or messages defined in superclasses.
-\end{itemize}
-The remaining differences are (I hope) a matter of presentation rather than
-substance.
-
-\subsection{Defining classes} \label{sec:syntax.class}
-
-\begin{grammar}
-<class-definition> ::= <class-forward-declaration>
-\alt <full-class-definition>
-\end{grammar}
-
-\subsubsection{Forward declarations} \label{sec:class.class.forward}
-
-\begin{grammar}
-<class-forward-declaration> ::= "class" <identifier> ";"
-\end{grammar}
-
-A @<class-forward-declaration> informs Sod that an @<identifier> will be used
-to name a class which is currently undefined.  Forward declarations are
-necessary in order to resolve certain kinds of circularity.  For example,
-\begin{listing}
-class Sub;
-
-class Super : SodObject {
-  Sub *sub;
-};
-
-class Sub : Super {
-  /* ... */
-};
-\end{listing}
-
-\subsubsection{Full class definitions} \label{sec:class.class.full}
-
-\begin{grammar}
-<full-class-definition> ::=
-  @[<properties>@]
-  "class" <identifier> ":" <identifier-list>
-  "{" @<class-item>^* "}"
-
-<class-item> ::= <slot-item> ";"
-\alt <message-item>
-\alt <method-item>
-\alt  <initializer-item> ";"
-\end{grammar}
-
-A full class definition provides a complete description of a class.
-
-The first @<identifier> gives the name of the class.  It is an error to
-give the name of an existing class (other than a forward-referenced class),
-or an existing type name.  It is conventional to give classes `MixedCase'
-names, to distinguish them from other kinds of identifiers.
-
-The @<identifier-list> names the direct superclasses for the new class.  It
-is an error if any of these @<identifier>s does not name a defined class.
-
-The @<properties> provide additional information.  The standard class
-properties are as follows.
-\begin{description}
-\item[@"lisp_class"] The name of the Lisp class to use within the translator
-  to represent this class.  The property value must be an identifier; the
-  default is @"sod_class".  Extensions may define classes with additional
-  behaviour, and may recognize additional class properties.
-\item[@"metaclass"] The name of the Sod metaclass for this class.  In the
-  generated code, a class is itself an instance of another class -- its
-  \emph{metaclass}.  The metaclass defines which slots the class will have,
-  which messages it will respond to, and what its behaviour will be when it
-  receives them.  The property value must be an identifier naming a defined
-  subclass of @"SodClass".  The default metaclass is @"SodClass".
-  %%% FIXME xref to theory
-\item[@"nick"] A nickname for the class, to be used to distinguish it from
-  other classes in various limited contexts.  The property value must be an
-  identifier; the default is constructed by forcing the class name to
-  lower-case.
-\end{description}
-
-The class body consists of a sequence of @<class-item>s enclosed in braces.
-These items are discussed on the following sections.
-
-\subsubsection{Slot items} \label{sec:sntax.class.slot}
-
-\begin{grammar}
-<slot-item> ::=
-  @[<properties>@]
-  @<declaration-specifier>^+ <init-declarator-list>
-
-<init-declarator> ::= <declarator> @["=" <initializer>@]
-\end{grammar}
-
-A @<slot-item> defines one or more slots.  All instances of the class and any
-subclass will contain these slot, with the names and types given by the
-@<declaration-specifiers> and the @<declarators>.  Slot declarators may not
-contain qualified identifiers.
-
-It is not possible to declare a slot with function type: such an item is
-interpreted as being a @<message-item> or @<method-item>.  Pointers to
-functions are fine.
-
-An @<initializer>, if present, is treated as if a separate
-@<initializer-item> containing the slot name and initializer were present.
-For example,
-\begin{listing}
-[nick = eg]
-class Example : Super {
-  int foo = 17;
-};
-\end{listing}
-means the same as
-\begin{listing}
-[nick = eg]
-class Example : Super {
-  int foo;
-  eg.foo = 17;
-};
-\end{listing}
-
-\subsubsection{Initializer items} \label{sec:syntax.class.init}
-
-\begin{grammar}
-<initializer-item> ::= @["class"@] <slot-initializer-list>
-
-<slot-initializer> ::= <qualified-identifier> "=" <initializer>
-
-<initializer> :: "{" <c-fragment> "}" | <c-fragment>
-\end{grammar}
-
-An @<initializer-item> provides an initial value for one or more slots.  If
-prefixed by @"class", then the initial values are for class slots (i.e.,
-slots of the class object itself); otherwise they are for instance slots.
-
-The first component of the @<qualified-identifier> must be the nickname of
-one of the class's superclasses (including itself); the second must be the
-name of a slot defined in that superclass.
-
-The initializer has one of two forms.
-\begin{itemize}
-\item A @<c-fragment> enclosed in braces denotes an aggregate initializer.
-  This is suitable for initializing structure, union or array slots.
-\item A @<c-fragment> \emph{not} beginning with an open brace is a `bare'
-  initializer, and continues until the next @`,' or @`;' which is not within
-  nested brackets.  Bare initializers are suitable for initializing scalar
-  slots, such as pointers or integers, and strings.
-\end{itemize}
-
-\subsubsection{Message items} \label{sec:syntax.class.message}
-
-\begin{grammar}
-<message-item> ::=
-  @[<properties>@]
-  @<declaration-specifier>^+ <declarator> @[<method-body>@]
-\end{grammar}
-
-\subsubsection{Method items} \label{sec:syntax.class.method}
-
-\begin{grammar}
-<method-item> ::=
-  @[<properties>@]
-  @<declaration-specifier>^+ <declarator> <method-body>
-
-<method-body> ::= "{" <c-fragment> "}" | "extern" ";"
-\end{grammar}
+\include{tutorial}
 
 %%%--------------------------------------------------------------------------
-\section{Class objects}
-
-\begin{listing}
-typedef struct SodClass__ichain_obj SodClass;
-
-struct sod_chain {
-  size_t n_classes;                     /* Number of classes in chain */
-  const SodClass *const *classes;       /* Vector of classes, head first */
-  size_t off_ichain;                    /* Offset of ichain from instance base */
-  const struct sod_vtable *vt;          /* Vtable pointer for chain */
-  size_t ichainsz;                      /* Size of the ichain structure */
-};
-
-struct sod_vtable {
-  SodClass *_class;                     /* Pointer to instance's class */
-  size_t _base;                         /* Offset to instance base */
-};
-
-struct SodClass__islots {
-
-  /* Basic information */
-  const char *name;                     /* The class's name as a string */
-  const char *nick;                     /* The nickname as a string */
-
-  /* Instance allocation and initialization */
-  size_t instsz;                        /* Instance layout size in bytes */
-  void *(*imprint)(void *);             /* Stamp instance with vtable ptrs */
-  void *(*init)(void *);                /* Initialize instance */
-
-  /* Superclass structure */
-  size_t n_supers;                      /* Number of direct superclasses */
-  const SodClass *const *supers;        /* Vector of direct superclasses */
-  size_t n_cpl;                         /* Length of class precedence list */
-  const SodClass *const *cpl;           /* Vector for class precedence list */
-
-  /* Chain structure */
-  const SodClass *link;                 /* Link to next class in chain */
-  const SodClass *head;                 /* Pointer to head of chain */
-  size_t level;                         /* Index of class in its chain */
-  size_t n_chains;                      /* Number of superclass chains */
-  const sod_chain *chains;              /* Vector of chain structures */
-
-  /* Layout */
-  size_t off_islots;                    /* Offset of islots from ichain base */
-  size_t islotsz;                       /* Size of instance slots */
-};
-
-struct SodClass__ichain_obj {
-  const SodClass__vt_obj *_vt;
-  struct SodClass__islots cls;
-};
-
-struct sod_instance {
-  struct sod_vtable *_vt;
-};
-\end{listing}
-
-\begin{listing}
-void *sod_convert(const SodClass *cls, const void *obj)
-{
-  const struct sod_instance *inst = obj;
-  const SodClass *real = inst->_vt->_cls;
-  const struct sod_chain *chain;
-  size_t i, index;
+\part{Reference} \label{p:ref}
 
-  for (i = 0; i < real->cls.n_chains; i++) {
-    chain = &real->cls.chains[i];
-    if (chain->classes[0] == cls->cls.head) {
-      index = cls->cls.index;
-      if (index < chain->n_classes && chain->classes[index] == cls)
-        return ((char *)cls - inst->_vt._base + chain->off_ichain);
-      else
-        return (0);
-    }
-  }
-  return (0);
-}
-\end{listing}
+\include{concepts}
+\include{cmdline}
+\include{syntax}
+\include{runtime}
+\include{structures}
 
 %%%--------------------------------------------------------------------------
-\section{Classes}
+\part{Lisp interface} \label{p:lisp}
+
+\include{lispintro}
+%% package.lisp
+%% sod.asd.in
+%% sod-frontend.asd.in
+%% auto.lisp.in
+
+\include{misc}
+%% utilities.lisp
+%% pset-impl.lisp
+%% pset-parse.lisp
+%% pset-proto.lisp
+%% optparse.lisp
+%% frontend.lisp
+%% final.lisp
+
+\include{parsing}
+%% package.lisp
+%% floc-impl.lisp
+%% floc-proto.lisp
+%% streams-impl.lisp
+%% streams-proto.lisp
+%% scanner-context-impl.lisp
+%% scanner-impl.lisp
+%% scanner-proto.lisp
+%% scanner-token-impl.lisp
+%% scanner-charbuf-impl.lisp
+%% parser-impl.lisp
+%% parser-proto.lisp
+%% parser-expr-impl.lisp
+%% parser-expr-proto.lisp
+%% lexer-impl.lisp
+%% lexer-proto.lisp
+
+\include{clang}
+%% c-types-class-impl.lisp
+%% c-types-impl.lisp
+%% c-types-parse.lisp
+%% c-types-proto.lisp
+%% codegen-impl.lisp
+%% codegen-proto.lisp
+%% fragment-parse.lisp
+
+\include{meta}
+%% classes.lisp
+%% class-utilities.lisp
+%% class-make-impl.lisp
+%% class-make-proto.lisp
+%% class-finalize-impl.lisp
+%% class-finalize-proto.lisp
+
+\include{layout}
+%% class-layout-impl.lisp
+%% class-layout-proto.lisp
+%% method-impl.lisp
+%% method-proto.lisp
+%% method-aggregate.lisp
+
+\include{module}
+%% module-impl.lisp
+%% module-parse.lisp
+%% module-proto.lisp
+%% builtin.lisp
+
+\include{output}
+%% output-impl.lisp
+%% output-proto.lisp
+%% class-output.lisp
+%% module-output.lisp
 
-\subsection{Classes and superclasses}
-
-A @<full-class-definition> must list one or more existing classes to be the
-\emph{direct superclasses} for the new class being defined.  We make the
-following definitions.
-\begin{itemize}
-\item The \emph{superclasses} of a class consist of the class itself together
-  with the superclasses of its direct superclasses.
-\item The \emph{proper superclasses} of a class are its superclasses other
-  than itself.
-\item If $C$ is a (proper) superclass of $D$ then $D$ is a (\emph{proper})
-  \emph{subclass} of $C$.
-\end{itemize}
-The predefined class @|SodObject| has no direct superclasses; it is unique in
-this respect.  All classes are subclasses of @|SodObject|.
-
-\subsection{The class precedence list}
-
-Let $C$ be a class.  The superclasses of $C$ form a directed graph, with an
-edge from each class to each of its direct superclasses.  This is the
-\emph{superclass graph of $C$}.
-
-In order to resolve inheritance of items, we define a \emph{class precedence
-  list} (or CPL) for each class, which imposes a total order on that class's
-superclasses.  The default algorithm for computing the CPL is the \emph{C3}
-algorithm \cite{fixme-c3}, though extensions may implement other algorithms.
-
-The default algorithm works as follows.  Let $C$ be the class whose CPL we
-are to compute.  Let $X$ and $Y$ be two of $C$'s superclasses.
-\begin{itemize}
-\item $C$ must appear first in the CPL.
-\item If $X$ appears before $Y$ in the CPL of one of $C$'s direct
-  superclasses, then $X$ appears before $Y$ in the $C$'s CPL.
-\item If the above rules don't suffice to order $X$ and $Y$, then whichever
-  of $X$ and $Y$ has a subclass which appears further left in the list of
-  $C$'s direct superclasses will appear earlier in the CPL.
-\end{itemize}
-This last rule is sufficient to disambiguate because if both $X$ and $Y$ are
-superclasses of the same direct superclass of $C$ then that direct
-superclass's CPL will order $X$ and $Y$.
-
-We say that \emph{$X$ is more specific than $Y$ as a superclass of $C$} if
-$X$ is earlier than $Y$ in $C$'s class precedence list.  If $C$ is clear from
-context then we omit it, saying simply that $X$ is more specific than $Y$.
-
-\subsection{Instances and metaclasses}
-
-A class defines the structure and behaviour of its \emph{instances}: run-time
-objects created (possibly) dynamically.  An instance is an instance of only
-one class, though structurally it may be used in place of an instance of any
-of that class's superclasses.  It is possible, with care, to change the class
-of an instance at run-time.
-
-Classes are themselves represented as instances -- called \emph{class
-  objects} -- in the running program.  Being instances, they have a class,
-called the \emph{metaclass}.  The metaclass defines the structure and
-behaviour of the class object.
-
-The predefined class @|SodClass| is the default metaclass for new classes.
-@|SodClass| has @|SodObject| as its only direct superclass.  @|SodClass| is
-its own metaclass.
-
-\subsection{Items and inheritance}
-
-A class definition also declares \emph{slots}, \emph{messages},
-\emph{initializers} and \emph{methods} -- collectively referred to as
-\emph{items}.  In addition to the items declared in the class definition --
-the class's \emph{direct items} -- a class also \emph{inherits} items from
-its superclasses.
-
-The precise rules for item inheritance vary according to the kinds of items
-involved.
-
-Some object systems have a notion of `repeated inheritance': if there are
-multiple paths in the superclass graph from a class to one of its
-superclasses then items defined in that superclass may appear duplicated in
-the subclass.  Sod does not have this notion.
-
-\subsubsection{Slots}
-A \emph{slot} is a unit of state.  In other object systems, slots may be
-called `fields', `member variables', or `instance variables'.
-
-A slot has a \emph{name} and a \emph{type}.  The name serves only to
-distinguish the slot from other direct slots defined by the same class.  A
-class inherits all of its proper superclasses' slots.  Slots inherited from
-superclasses do not conflict with each other or with direct slots, even if
-they have the same names.
-
-At run-time, each instance of the class holds a separate value for each slot,
-whether direct or inherited.  Changing the value of an instance's slot
-doesn't affect other instances.
-
-\subsubsection{Initializers}
-Mumble.
-
-\subsubsection{Messages}
-A \emph{message} is the stimulus for behaviour.  In Sod, a class must define,
-statically, the name and format of the messages it is able to receive and the
-values it will return in reply.  In this respect, a message is similar to
-`abstract member functions' or `interface member functions' in other object
-systems.
-
-Like slots, a message has a \emph{name} and a \emph{type}.  Again, the name
-serves only to distinguish the message from other direct messages defined by
-the same class.  Messages inherited from superclasses do not conflict with
-each other or with direct messages, even if they have the same name.
-
-At run-time, one sends a message to an instance by invoking a function
-obtained from the instance's \emph{vtable}: \xref{sec:fixme-vtable}.
-
-\subsubsection{Methods}
-A \emph{method} is a unit of behaviour.  In other object systems, methods may
-be called `member functions'.
-
-A method is associated with a message.  When a message is received by an
-instance, all of the methods associated with that message on the instance's
-class or any of its superclasses are \emph{applicable}.  The details of how
-the applicable methods are invoked are described fully in
-\xref{sec:fixme-method-combination}.
-
-\subsection{Chains and instance layout}
+%%%--------------------------------------------------------------------------
+\part{Appendices}
+\appendix
 
-\include{sod-backg}
-\include{sod-protocol}
+\include{cutting-room-floor}
 
+%%%----- That's all, folks --------------------------------------------------
 \end{document}
-\f
+
 %%% Local variables:
 %%% mode: LaTeX
 %%% TeX-PDF-mode: t
diff --git a/doc/structures.tex b/doc/structures.tex
new file mode 100644 (file)
index 0000000..561075b
--- /dev/null
@@ -0,0 +1,584 @@
+%%% -*-latex-*-
+%%%
+%%% In-depth exploration of the generated structures
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Simple Object Definition system.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Object structures} \label{ch:structures}
+
+This chapter describes the structure and layout of standard Sod objects,
+classes and associated metadata.  Note that Sod's object system is very
+flexible and it's possible for an extension to define a new root class which
+works very differently from the standard @|SodObject| described here.
+
+The concrete types described in \xref{sec:structures.common} and
+\ref{sec:structures.root} are declared by the header file @|<sod/sod.h>|.
+The definitions described in sections \ref{sec:structures.layout} are defined
+in the header file generated by the containing module.
+
+%%%--------------------------------------------------------------------------
+\section{Common instance structure} \label{sec:structures.common}
+
+As described below, a pointer to an instance actually points to an
+\emph{instance chain} structure within the instances overall layout
+structure.
+
+Instance chains contain slots and vtable pointers, as described below.  All
+instances have the basic structure of a @|struct sod_instance|.
+
+\begin{describe}[struct sod_instance]{type}
+    {struct sod_instance \{ \\ \ind
+       const struct sod_vtable *_vt; \- \\
+     \};}
+
+  The basic structure of all instances.  Members are as follows.
+  \begin{description} \let\makelabel\code
+  \item[_vt] A pointer to a \emph{vtable}, which has the basic structure of a
+    @|struct sod_vtable|, described below.
+  \end{description}
+\end{describe}
+
+\begin{describe}[struct sod_vtable]{type}
+    {struct sod_vtable \{ \\ \ind
+       const SodClass *_class; \\
+       size_t _base; \- \\
+     \};}
+
+  A vtable contains static metadata needed for efficient conversions and
+  message dispatch, and pointers to the instance's class.  Each chain points
+  to a different vtable.  All vtables have the basic structure of a @|struct
+  sod_vtable|, which has the following members.
+  \begin{description} \let\makelabel\code
+  \item[_class] A pointer to the instance's class object.
+  \item[_base] The offset of this chain structure above the start of the
+    overall instance layout, in bytes.  Subtracting @|_base| from the
+    instance chain pointer finds the layout base address.
+  \end{description}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Built-in root objects} \label{sec:structures.root}
+
+This section describes the built-in classes @|SodObject| and @|SodClass|,
+which are the standard roots of the inheritance and metaclass graphs
+respectively.  Specifically, @|SodObject| has no direct superclasses, and
+@|SodClass| is its own metaclass.  It is not possible to define root classes
+in module files because of circularities: @|SodObject| has @|SodClass| as its
+metaclass, and @|SodClass| is a subclass of @|SodObject|.  Extensions can
+define additional root classes, but this is tricky, and not really to be
+recommended.
+
+\subsection{The SodObject class} \label{sec:structures.root.sodobject}
+
+\begin{figure}[tbp]
+  \begin{tabular}{p{10pt}p{10pt}}
+    \begin{prog}
+      struct SodObject__ilayout \{ \\ \ind
+        union \{ \\ \ind
+          struct SodObject__ichain_obj \{ \\ \ind
+            const struct SodObject__vt_obj *_vt; \- \\
+          \}; \- \\
+        \} obj; \- \\
+      \};
+    \end{prog}
+    &
+    \begin{prog}
+      struct SodObject__vt_obj \{ \\ \ind
+        const SodClass *_class; \\
+        size_t _base; \- \\
+      \};
+    \end{prog} \\
+  \end{tabular}
+  \caption{Instance and vtable layout of @|SodObject|}
+  \label{fig:structures.root.sodobject}
+\end{figure}
+
+\begin{describe}[SodObject]{cls}
+    {[metaclass = SodClass, lisp_metaclass = sod_class] \\
+     class SodObject \{ \}}
+
+  The @|SodObject| class defines no slots or messages.  Because @|SodObject|
+  has no direct superclasses, there is only one chain, and no inherited
+  slots or messages, so the single chain contains only a vtable pointer.
+
+  Since there are no messages, and @|SodClass| also has only one chain, the
+  vtable contains only the standard class pointer and offset-to-base members.
+  In a direct instance of @|SodObject| (why would you want one?)  the class
+  pointer contains the address of @|SodObject__class| and the offset is zero.
+
+  The instance and vtable layout of @|SodObject| is shown in
+  \xref{fig:structures.root.sodobject}.
+\end{describe}
+
+\subsection{The SodClass class} \label{sec:structures.root.sodclass}
+
+\begin{describe}[SodClass]{cls}
+    {class SodClass : SodObject \{ \\ \ind
+       const char *name; \\
+       const char *nick; \\
+       size_t initsz; \\
+       void *(*imprint)(void *@<p>); \\
+       void *(*init)(void *@<p>); \\
+       size_t n_supers; \\
+       const SodClass *const *supers; \\
+       size_t n_cpl; \\
+       const SodClass *const *cpl; \\
+       const SodClass *link; \\
+       const SodClass *head; \\
+       size_t level; \\
+       size_t n_chains; \\
+       const struct sod_chain *chains; \\
+       size_t off_islots; \\
+       size_t islotsz; \- \\
+     \}}
+
+  The @|SodClass| class defines no messages, but there are a number of slots.
+  Its only direct superclass is @|SodObject| and so (like its superclass) its
+  vtable is trivial.
+
+  The slots defined are as follows.
+  \begin{description} \let\makelabel\code
+
+  \item[name] A pointer to the class's name.
+
+  \item[nick] A pointer to the class's nickname.
+
+  \item[initsz] The size in bytes required to store an instance of the class.
+
+  \item[imprint] A pointer to a function: given a pointer @<p> to at least
+    @<initsz> bytes of appropriately aligned memory, `imprint' this memory it
+    so that it becomes a minimally functional instance of the class: all of
+    the vtable and class pointers are properly initialized, but the slots are
+    left untouched.  The function returns its argument @<p>.
+
+  \item[init] A pointer to a function: given a pointer @<p> to at least
+    @<initsz> bytes of appropriately aligned memory, initialize an instance
+    of the class in it: all of the vtable and class pointers are initialized,
+    as are slots for which initializers are defined.  Other slots are left
+    untouched.  The function returns its argument @<p>.
+
+  \item[n_supers] The number of direct superclasses.  (This is zero exactly
+    in the case of @|SodObject|.)
+
+  \item[supers] A pointer to an array of @<n_supers> pointers to class
+    objects listing the class's direct superclasses, in the order in which
+    they were listed in the class definition.  If @<n_supers> is zero, then
+    this pointer is null.
+
+  \item[n_cpl] The number of superclasses in the class's class precedence
+    list.
+
+  \item[cpl] A pointer to an array of pointers to class objects listing all
+    of the class's superclasses, from most- to least-specific, starting with
+    the class itself, so $c@->@|cls|.@|cpl|[0] = c$ for all class objects
+    $c$.
+
+  \item[link] If the class is a chain head, then this is a null pointer;
+    otherwise it points to the class's distinguished link superclass (which
+    might or might not be a direct superclass).
+
+  \item[head] A pointer to the least-specific class in this class's chain; so
+    $c@->@|cls|.@|head|@->@|cls|.@|link|$ is always null, and either
+    $c@->@|cls|.@|link|$ is null (in which case $c@->@|cls|.@|head| = c$) or
+    $c@->@|cls|.@|head| = c@->@|cls|.@|link|@->@|cls|.@|head|$.
+
+  \item[level] The number of less specific superclasses in this class's
+    chain.  If $c@->@|cls|.@|link|$ is null then $c@->@|cls|.@|level|$ is
+    zero; otherwise $c@->@|cls|.@|level| =
+    c@->@|cls|.@|link|@->@|cls|.@|level| + 1$.
+
+  \item[n_chains] The number of chains formed by the class's superclasses.
+
+  \item[chains] A pointer to an array of @|struct sod_chain| structures (see
+    below) describing the class's superclass chains, in decreasing order of
+    specificity of their most specific classes.  It is always the case that
+    $c@->@|cls|.@|chains|[0].@|classes|[c@->@|cls|.@|level|] = c$.
+
+  \item[off_islots] The offset of the class's @|islots| structure relative to
+    its containing @|ichain| structure.  The class doesn't define any slots
+    if and only if this is zero.  (The offset can't be zero because the
+    vtable pointer is at offset zero.)
+
+  \item[islotsz] The size required to store the class's direct slots, i.e.,
+    the size of its @|islots| structure.  The class doesn't define any slots
+    if and only if this is zero.
+
+  \end{description}
+\end{describe}
+
+\begin{describe}[struct sod_chain]{type}
+    {struct sod_chain \{ \\ \ind
+       size_t n_classes; \\
+       const SodClass *const *classes; \\
+       size_t off_ichain; \\
+       const struct sod_vtable *vt; \\
+       size_t ichainsz; \- \\
+     \};}
+
+   The @|struct sod_chain| structure describes an individual chain of
+   superclasses.  It has the following members.
+   \begin{description} \let\makelabel\code
+
+   \item[n_classes] The number of classes in the chain.  This is always at
+     least one.
+
+   \item[classes] A pointer to an array of class pointers listing the classes
+     in the chain from least- to most-specific.  So
+     $@<classes>[i]@->@|cls|.@|head| = @<classes>[0]$ for all $0 \le i <
+     @<n_classes>$, $@<classes>[0]@->@|cls|.@|link|$ is always null, and
+     $@<classes>[i]@->@|cls|.@|link| = @<classes>[i - 1]$ if $1 \le i <
+     @<n_classes>$.
+
+   \item[off_ichain] The size of the @|ichain| structure for this chain.
+
+   \item[vt] The vtable for this chain.  (It is possible, therefore, to
+     partially duplicate the behaviour of the @<imprint> function by walking
+     the chain structure.\footnote{%
+       There isn't enough information readily available to fill in the class
+       pointers correctly.} %
+     The @<imprint> function is much faster, though.)
+
+   \item[ichainsz] The size of the @|ichain| structure for this chain.
+
+   \end{description}
+ \end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Class and vtable layout} \label{sec:structures.layout}
+
+The layout algorithms for Sod instances and vtables are nontrivial.  They are
+defined here in full detail, since they're effectively fixed by Sod's ABI
+compatibility guarantees, so they might as well be documented for the sake of
+interoperating programs.
+
+Unfortunately, the descriptions are rather complicated, and, for the most
+part not necessary to a working understanding of Sod.  The skeleton structure
+definitions shown should be more than enough for readers attempting to make
+sense of the generated headers and tables.
+
+In the description that follows, uppercase letters vary over class names,
+while the corresponding lowercase letters indicate the class nicknames.
+Throughout, we consider a class $C$ (therefore with nickname $c$).
+
+\subsection{Generic instance structure}
+\label{sec:structures.layout.instance}
+
+The entire state of an instance of $C$ is contained in a single structure of
+type @|struct $C$__ilayout|.
+
+\begin{prog}
+  struct $C$__ilayout \{ \\ \ind
+    union $C$__ichainu_$h$ \{ \\ \ind
+      struct $C$__ichain_$h$ \{ \\ \ind
+        const struct $C$__vt_$h$ *_vt; \\
+        struct $H$__islots $h$; \\
+        \quad$\vdots$ \\
+        struct $C$__islots \{ \\ \ind
+          @<type>_1 @<slot>_1; \\
+          \quad$\vdots$ \\
+          @<type>_n @<slot>_n; \- \\
+        \} $c$; \- \\
+      \} $c$; \\
+      struct $H$__ichain_$h$ $h$; \\
+      \quad$\vdots$ \- \\
+    \} $h$; \\
+    union $B$__ichainu_$i$ $i$; \\
+    \quad$\vdots$ \- \\
+  \};
+  \\[\bigskipamount]
+  typedef struct $C$__ichain_$h$ $C$;
+\end{prog}
+
+The set of superclasses of $C$, including itself, can be partitioned into
+chains by following their distinguished superclass links.  (Formally, the
+chains are the equivalence classes determined by the reflexive, symmetric,
+transitive closure of the `links to' relation.)  Chains are identified by
+naming their least specific classes; the least specific class in a chain is
+called the \emph{chain head}.  Suppose that the chain head of the chain
+containing $C$ itself is named $H$ (though keep in mind that it's possible
+that .$H$ is in fact $C$ itself.)
+
+\subsubsection{The ilayout structure}
+The @|ilayout| structure contains one member for each of $C$'s superclass
+chains.  The first such member is
+\begin{prog}
+  union $C$__ichainu_$h$ $h$;
+\end{prog}
+described below; this is followed by members
+\begin{prog}
+  union $B$__ichainu_$i$ $i$;
+\end{prog}
+for each other chain, where $I$ is the head and $B$ the tail (most-specific)
+class of the chain.  The members are in decreasing order of the specificity
+of the chains' most-specific classes.  (Note that all but the first of these
+unions has already been defined as part of the definition of the
+corresponding $B$.)
+
+\subsubsection{The ichainu union}
+The @|ichainu| union contains a member for each class in the chain.  The
+first is
+\begin{prog}
+  struct $C$__ichain_$h$ $c$;
+\end{prog}
+and this is followed by corresponding members
+\begin{prog}
+  struct $A$__ichain_$h$ $a$;
+\end{prog}
+for each of $C$'s superclasses $A$ in the same chain in some (unimportant)
+order.
+
+\subsubsection{The ichain structure}
+The
+@|ichain|
+structure contains (in order), a pointer
+\begin{prog}
+  const struct $C$__vt_$h$ *_vt;
+\end{prog}
+followed by a structure
+\begin{prog}
+  struct $A$__islots $a$;
+\end{prog}
+for each superclass $A$ of $C$ in the same chain which defines slots, from
+least- to most-specific; if $C$ defines any slots, then the last member is
+\begin{prog}
+  struct $C$__islots $c$;
+\end{prog}
+A `pointer to $C$' is always assumed (and, indeed, defined in C's
+type system) to be a pointer to the @|struct $C$__ichain_$h$|.
+
+\subsubsection{The islots structure}
+Finally, the @|islots| structure simply contains one member for each slot
+defined by $C$ in the order they appear in the class definition.
+
+\subsection{Generic vtable structure} \label{sec:structures.layout.vtable}
+
+As described above, each @|ichain| structure of an instance's storage has a
+vtable pointer
+\begin{prog}
+  const struct $C$__vt_$h$ *_vt;
+\end{prog}
+In general, the vtables for the different chains will have \emph{different}
+structures.
+
+The instance layout split neatly into disjoint chains.  This is necessary
+because each @|ichain| must have as a prefix the @|ichain| for each
+superclass in the same chain, and each slot must be stored in exactly one
+place.  The layout of vtables doesn't have this second requirement: it
+doesn't matter that there are multiple method entry pointers for the same
+effective method as long as they all work correctly.  Indeed, it's essential
+that they do, because each chain's method entry function will need to apply a
+different offset to the receiver pointer before invoking the effective
+method.
+
+A vtable for a class $C$ with chain head $H$ has the following general
+structure.
+\begin{prog}
+  union $C$__vtu_$h$ \{ \\ \ind
+    struct $C$__vt_$h$ \{ \\ \ind
+      const $P$ *_class; \\
+      size_t _base; \\
+      \quad$\vdots$ \\
+      const $Q$ *_cls_$j$; \\
+      \quad$\vdots$ \\
+      ptrdiff_t _off_$i$; \\
+      \quad$\vdots$ \\
+      struct $C$__vtmsgs_$a$ \{ \\ \ind
+        @<type> (*@<msg>)($C$ *, $\dots$); \\
+        \quad$\vdots$ \- \\
+      \} $a$; \\
+      \quad$\vdots$ \- \\
+    \} $c$; \- \\
+  \};
+  \\[\bigskipamount]
+  extern const union $C$__vtu_$h$ $C$__vtable_$h$;
+\end{prog}
+
+\subsubsection{The vtu union}
+The outer layer is a @|union $C$__vtu_$h$| containing a member
+\begin{prog}
+  struct $A$__vt_$h$ $a$;
+\end{prog}
+for each of $C$'s superclasses $A$ in the same chain, with $C$ itself listed
+first.
+
+This is mostly an irrelevant detail,
+whose purpose is to defend against malicious compilers:
+pointers are always to one of the inner
+@|vt|
+structures.
+It's important only because it's the outer
+@|vtu|
+union which is exported by name.
+Specifically, for each chain of
+$C$'s
+superclasses
+there is an external object
+\begin{prog}
+  const union $A$__vtu_$i$ $C$__vtable_$i$;
+\end{prog}
+where $A$ and $I$ are respectively the most and least specific classes in the
+chain.
+
+\subsubsection{The vt structure}
+The first member in the @|vt| structure is the \emph{root class pointer}
+\begin{prog}
+  const $P$ *_class;
+\end{prog}
+Among the superclasses of $C$ there must be exactly one class $O$ which
+itself has no direct superclasses; this is the \emph{root superclass} of $C$.
+(This is a rule enforced by the Sod translator.)  The metaclass $R$ of $O$ is
+then the \emph{root metaclass} of $C$.  The @|_class| member points to the
+@|ichain| structure of most specific superclass $P$ of $M$ in the same chain
+as $R$.
+
+This is followed by the \emph{base offset}
+\begin{prog}
+  size_t _base;
+\end{prog}
+which is simply the offset of the @|ichain| structure from the instance base.
+
+The rest of the vtable structure is populated by walking the superclass chain
+containing $C$ as follows.  For each such superclass $B$, in increasing order
+of specificity, walk the class precedence list of $B$, again starting with
+its least-specific superclass.  (This complex procedure guarantees that the
+vtable structure for a class is a prefix of the vtable structure for any of
+its subclasses in the same chain.)
+
+So, let $A$ be some superclass of $C$ which has been encountered during this
+traversal.
+
+\begin{itemize}
+
+\item Let $N$ be the metaclass of $A$.  Examine the superclass chains of $N$
+  in order of decreasing specificity of their most-specific classes.  Let $J$
+  be the chain head of such a chain, and let $Q$ be the most specific
+  superclass of $M$ in the same chain as $J$.  Then, if there is currently no
+  class pointer of type $Q$, then add a member
+  \begin{prog}
+    const $Q$ *_cls_$j$;
+  \end{prog}
+  to the vtable pointing to the appropriate @|islots| structure within $M$'s
+  class object.
+
+\item Examine the superclass chains of $A$ in order of decreasing specificity
+  of their most-specific classes.  Let $I$ be the chain head of such a chain.
+  If there is currently no member @|_off_$i$| then add a member
+  \begin{prog}
+    ptrdiff_t _off_$i$;
+  \end{prog}
+  to the vtable, containing the (signed) offset from the @|ichain| structure
+  of the chain headed by $h$ to that of the chain headed by $i$ within the
+  instance's layout.
+
+\item If class $A$ defines any messages, and there is currently no member
+  $a$, then add a member
+  \begin{prog}
+    struct $C$__vtmsgs_$a$ $a$;
+  \end{prog}
+  to the vtable.  See below.
+
+\end{itemize}
+
+\subsubsection{The vtmsgs structure}
+Finally, the @|vtmsgs| structures contain pointers to the effective method
+entry functions for the messages defined by a superclass.  There may be more
+than one method entry for a message, but all of the entry pointers for a
+message appear together, and entry pointers for separate messages appear in
+the order in which the messages are defined.  If the receiver class has no
+applicable primary method for a message then it's usual for the method entry
+pointer to be null (though, as with a lot of things in Sod, extensions may do
+something different).
+
+For a standard message which takes a fixed number of arguments, defined as
+\begin{prog}
+  @<type>_0 $m$(@<type>_1 @<arg>_1, $\ldots$, @<type>_n @<arg>_n);
+\end{prog}
+there is always a `main' entry point,
+\begin{prog}
+  @<type>_0 $m$($C$ *me, @<type>_1 @<arg>_1, $\ldots$, @<type>_n @<arg>_n);
+\end{prog}
+
+For a standard message which takes a variable number of arguments,
+defined as
+\begin{prog}
+  @<type>_0 $m$(@<type>_1 @<arg>_1, $\ldots$, @<type>_n @<arg>_n, \dots);
+\end{prog}
+two entry points are defined: the usual `main' entry point which accepts a
+variable number of arguments, and a `valist' entry point which accepts an
+argument of type @|va_list| in place of the variable portion of the argument
+list.
+\begin{prog}
+  @<type>_0 $m$($C$ *me, @<type>_1 @<arg>_1, $\ldots$,
+                @<type>_n @<arg>_n, \dots); \\
+  @<type>_0 $m$__v($C$ *me, @<type>_1 @<arg>_1, $\ldots$,
+                   @<type>_n @<arg>_n, va_list sod__ap);
+\end{prog}
+
+\subsection{Additional definitions} \label{sec:structures.additional}
+
+In addition to the instance and vtable structures described above, the
+following definitions are made for each class $C$.
+
+For each message $m$ directly defined by $C$ there is a macro definition
+\begin{prog}
+  \#define $C$_$m$(@<me>, $\ldots$) @<me>@->_vt@->$c$.$m$(@<me>, $\ldots$)
+\end{prog}
+which makes sending the message $m$ to an instance of (any subclass of) $C$
+somewhat less ugly.
+
+If $m$ takes a variable number of arguments, the macro is more complicated
+and is only available in compilers advertising C99 support, but the effect is
+the same.  For each variable-argument message, there is also an additional
+macro for calling the `valist' entry point.
+\begin{prog}
+  \#define $C$_$m$__v(@<me>, $\ldots$, @<sod__ap>)
+    @<me>@->_vt@->$c$.$m$__v(@<me>, $\ldots$, @<sod__ap>)
+\end{prog}
+
+For each proper superclass $A$ of $C$, there is a macro defined
+\begin{prog}
+  $A$ *$C$__CONV_$a$($C$ *_obj);
+\end{prog}
+(named in \emph{upper case}) which converts a (static-type) pointer to $C$ to
+a pointer to the same actual instance, but statically typed as a pointer to
+$A$.  This is most useful when $A$ is not in the same chain as $C$ since
+in-chain upcasts are both trivial and rarely needed, but the full set is
+defined for the sake of completeness.
+
+Finally, the class object is defined as
+\begin{prog}
+  extern const struct $R$__ilayout $C$__classobj; \\
+  \#define $C$__class (\&$C$__classobj.$j$.$r$)
+\end{prog}
+The exported symbol @|$C$__classobj| contains the entire class instance.
+This is usually rather unwieldy.  The macro @|$C$__class| is usable as a
+pointer of type @|const $R$~*|, where $R$ is the root metaclass of $C$, i.e.,
+the metaclass of the least specific superclass of $C$; usually this is
+@|const SodClass~*|.
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
diff --git a/doc/syntax.tex b/doc/syntax.tex
new file mode 100644 (file)
index 0000000..336f4bc
--- /dev/null
@@ -0,0 +1,667 @@
+%%% -*-latex-*-
+%%%
+%%% Module syntax
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble Object Design, an object system for C.
+%%%
+%%% SOD is free software; you can redistribute it and/or modify
+%%% it under the terms of the GNU General Public License as published by
+%%% the Free Software Foundation; either version 2 of the License, or
+%%% (at your option) any later version.
+%%%
+%%% SOD is distributed in the hope that it will be useful,
+%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+%%% GNU General Public License for more details.
+%%%
+%%% You should have received a copy of the GNU General Public License
+%%% along with SOD; if not, write to the Free Software Foundation,
+%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+\chapter{Module syntax} \label{ch:syntax}
+
+%%%--------------------------------------------------------------------------
+
+Fortunately, Sod is syntactically quite simple.  I've used a little slightly
+unusual notation in order to make the presentation easier to read.  For any
+nonterminal $x$:
+\begin{itemize}
+\item $\epsilon$ denotes the empty nonterminal:
+  \begin{quote}
+    $\epsilon$ ::=
+  \end{quote}
+\item @[$x$@] means an optional $x$:
+  \begin{quote}
+    \syntax{@[$x$@] ::= $\epsilon$ @! $x$}
+  \end{quote}
+\item $x^*$ means a sequence of zero or more $x$s:
+  \begin{quote}
+    \syntax{$x^*$ ::= $\epsilon$ @! $x^*$ $x$}
+  \end{quote}
+\item $x^+$ means a sequence of one or more $x$s:
+  \begin{quote}
+    \syntax{$x^+$ ::= $x$ $x^*$}
+  \end{quote}
+\item $x$@<-list> means a sequence of one or more $x$s separated
+  by commas:
+  \begin{quote}
+    \syntax{$x$<-list> ::= $x$ @! $x$<-list> "," $x$}
+  \end{quote}
+\end{itemize}
+
+\subsection{Lexical syntax}
+\label{sec:syntax.lex}
+
+Whitespace and comments are discarded.  The remaining characters are
+collected into tokens according to the following syntax.
+
+\begin{grammar}
+<token> ::= <identifier>
+\alt <string-literal>
+\alt <char-literal>
+\alt <integer-literal>
+\alt <punctuation>
+\end{grammar}
+
+This syntax is slightly ambiguous, and is disambiguated by the \emph{maximal
+munch} rule: at each stage we take the longest sequence of characters which
+could be a token.
+
+\subsubsection{Identifiers} \label{sec:syntax.lex.id}
+
+\begin{grammar}
+<identifier> ::= <id-start-char> @<id-body-char>^*
+
+<id-start-char> ::= <alpha-char> | "_"
+
+<id-body-char> ::= <id-start-char> @! <digit-char>
+
+<alpha-char> ::= "A" | "B" | \dots\ | "Z"
+\alt "a" | "b" | \dots\ | "z"
+\alt <extended-alpha-char>
+
+<digit-char> ::= "0" | <nonzero-digit-char>
+
+<nonzero-digit-char> ::= "1" | "2" $| \cdots |$ "9"
+\end{grammar}
+
+The precise definition of @<alpha-char> is left to the function
+\textsf{alpha-char-p} in the hosting Lisp system.  For portability,
+programmers are encouraged to limit themselves to the standard ASCII letters.
+
+There are no reserved words at the lexical level, but the higher-level syntax
+recognizes certain identifiers as \emph{keywords} in some contexts.  There is
+also an ambiguity (inherited from C) in the declaration syntax which is
+settled by distinguishing type names from other identifiers at a lexical
+level.
+
+\subsubsection{String and character literals} \label{sec:syntax.lex.string}
+
+\begin{grammar}
+<string-literal> ::= "\"" @<string-literal-char>^* "\""
+
+<char-literal> ::= "'" <char-literal-char> "'"
+
+<string-literal-char> ::= any character other than "\\" or "\""
+\alt "\\" <char>
+
+<char-literal-char> ::= any character other than "\\" or "'"
+\alt "\\" <char>
+
+<char> ::= any single character
+\end{grammar}
+
+The syntax for string and character literals differs from~C.  In particular,
+escape sequences such as @`\textbackslash n' are not recognized.  The use
+of string and character literals in Sod, outside of C~fragments, is limited,
+and the simple syntax seems adequate.  For the sake of future compatibility,
+the use of character sequences which resemble C escape sequences is
+discouraged.
+
+\subsubsection{Integer literals} \label{sec:syntax.lex.int}
+
+\begin{grammar}
+<integer-literal> ::= <decimal-integer>
+\alt <binary-integer>
+\alt <octal-integer>
+\alt <hex-integer>
+
+<decimal-integer> ::= <nonzero-digit-char> @<digit-char>^*
+
+<binary-integer> ::= "0" @("b"|"B"@) @<binary-digit-char>^+
+
+<binary-digit-char> ::= "0" | "1"
+
+<octal-integer> ::= "0" @["o"|"O"@] @<octal-digit-char>^+
+
+<octal-digit-char> ::= "0" | "1" $| \cdots |$ "7"
+
+<hex-integer> ::= "0" @("x"|"X"@) @<hex-digit-char>^+
+
+<hex-digit-char> ::= <digit-char>
+\alt "A" | "B" | "C" | "D" | "E" | "F"
+\alt "a" | "b" | "c" | "d" | "e" | "f"
+\end{grammar}
+
+Sod understands only integers, not floating-point numbers; its integer syntax
+goes slightly beyond C in allowing a @`0o' prefix for octal and @`0b' for
+binary.  However, length and signedness indicators are not permitted.
+
+\subsubsection{Punctuation} \label{sec:syntax.lex.punct}
+
+\begin{grammar}
+<punctuation> ::= any nonalphanumeric character other than "_", "\"" or "'"
+\end{grammar}
+
+\subsubsection{Comments} \label{sec:lex-comment}
+
+\begin{grammar}
+<comment> ::= <block-comment>
+\alt <line-comment>
+
+<block-comment> ::=
+  "/*"
+  @<not-star>^* @(@<star>^+ <not-star-or-slash> @<not-star>^*@)^*
+  @<star>^*
+  "*/"
+
+<star> ::= "*"
+
+<not-star> ::= any character other than "*"
+
+<not-star-or-slash> ::= any character other than "*" or  "/"
+
+<line-comment> ::= "//" @<not-newline>^* <newline>
+
+<newline> ::= a newline character
+
+<not-newline> ::= any character other than newline
+\end{grammar}
+
+Comments are exactly as in C99: both traditional block comments `\texttt{/*}
+\dots\ \texttt{*/}' and \Cplusplus-style `\texttt{//} \dots' comments are
+permitted and ignored.
+
+\subsection{Special nonterminals}
+\label{sec:special-nonterminals}
+
+Aside from the lexical syntax presented above (\xref{sec:lexical-syntax}),
+two special nonterminals occur in the module syntax.
+
+\subsubsection{S-expressions} \label{sec:syntax-sexp}
+
+\begin{grammar}
+<s-expression> ::= an S-expression, as parsed by the Lisp reader
+\end{grammar}
+
+When an S-expression is expected, the Sod parser simply calls the host Lisp
+system's \textsf{read} function.  Sod modules are permitted to modify the
+read table to extend the S-expression syntax.
+
+S-expressions are self-delimiting, so no end-marker is needed.
+
+\subsubsection{C fragments} \label{sec:syntax.lex.cfrag}
+
+\begin{grammar}
+<c-fragment> ::= a sequence of C tokens, with matching brackets
+\end{grammar}
+
+Sequences of C code are simply stored and written to the output unchanged
+during translation.  They are read using a simple scanner which nonetheless
+understands C comments and string and character literals.
+
+A C fragment is terminated by one of a small number of delimiter characters
+determined by the immediately surrounding context -- usually a closing brace
+or bracket.  The first such delimiter character which is not enclosed in
+brackets, braces or parenthesis ends the fragment.
+
+\subsection{Module syntax} \label{sec:syntax-module}
+
+\begin{grammar}
+<module> ::= @<definition>^*
+
+<definition> ::= <import-definition>
+\alt <load-definition>
+\alt <lisp-definition>
+\alt <code-definition>
+\alt <typename-definition>
+\alt <class-definition>
+\end{grammar}
+
+A module is the top-level syntactic item.  A module consists of a sequence of
+definitions.
+
+\subsection{Simple definitions} \label{sec:syntax.defs}
+
+\subsubsection{Importing modules} \label{sec:syntax.defs.import}
+
+\begin{grammar}
+<import-definition> ::= "import" <string> ";"
+\end{grammar}
+
+The module named @<string> is processed and its definitions made available.
+
+A search is made for a module source file as follows.
+\begin{itemize}
+\item The module name @<string> is converted into a filename by appending
+  @`.sod', if it has no extension already.\footnote{%
+    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
+    :type "SOD" :case :common))}, so exactly what this means varies
+    according to the host system.} %
+\item The file is looked for relative to the directory containing the
+  importing module.
+\item If that fails, then the file is looked for in each directory on the
+  module search path in turn.
+\item If the file still isn't found, an error is reported and the import
+  fails.
+\end{itemize}
+At this point, if the file has previously been imported, nothing further
+happens.\footnote{%
+  This check is done using \textsf{truename}, so it should see through simple
+  tricks like symbolic links.  However, it may be confused by fancy things
+  like bind mounts and so on.} %
+
+Recursive imports, either direct or indirect, are an error.
+
+\subsubsection{Loading extensions} \label{sec:syntax.defs.load}
+
+\begin{grammar}
+<load-definition> ::= "load" <string> ";"
+\end{grammar}
+
+The Lisp file named @<string> is loaded and evaluated.
+
+A search is made for a Lisp source file as follows.
+\begin{itemize}
+\item The name @<string> is converted into a filename by appending @`.lisp',
+  if it has no extension already.\footnote{%
+    Technically, what happens is \textsf{(merge-pathnames name (make-pathname
+    :type "LISP" :case :common))}, so exactly what this means varies
+    according to the host system.} %
+\item A search is then made in the same manner as for module imports
+  (\xref{sec:syntax-module}).
+\end{itemize}
+If the file is found, it is loaded using the host Lisp's \textsf{load}
+function.
+
+Note that Sod doesn't attempt to compile Lisp files, or even to look for
+existing compiled files.  The right way to package a substantial extension to
+the Sod translator is to provide the extension as a standard ASDF system (or
+similar) and leave a dropping @"foo-extension.lisp" in the module path saying
+something like
+\begin{quote}
+  \textsf{(asdf:load-system :foo-extension)}
+\end{quote}
+which will arrange for the extension to be compiled if necessary.
+
+(This approach means that the language doesn't need to depend on any
+particular system definition facility.  It's bad enough already that it
+depends on Common Lisp.)
+
+\subsubsection{Lisp escapes} \label{sec:syntax.defs.lisp}
+
+\begin{grammar}
+<lisp-definition> ::= "lisp" <s-expression> ";"
+\end{grammar}
+
+The @<s-expression> is evaluated immediately.  It can do anything it likes.
+
+\begin{boxy}[Warning!]
+  This means that hostile Sod modules are a security hazard.  Lisp code can
+  read and write files, start other programs, and make network connections.
+  Don't install Sod modules from sources that you don't trust.\footnote{%
+    Presumably you were going to run the corresponding code at some point, so
+    this isn't as unusually scary as it sounds.  But please be careful.} %
+\end{boxy}
+
+\subsubsection{Declaring type names} \label{sec:syntax.defs.typename}
+
+\begin{grammar}
+<typename-definition> ::=
+  "typename" <identifier-list> ";"
+\end{grammar}
+
+Each @<identifier> is declared as naming a C type.  This is important because
+the C type syntax -- which Sod uses -- is ambiguous, and disambiguation is
+done by distinguishing type names from other identifiers.
+
+Don't declare class names using @"typename"; use @"class" forward
+declarations instead.
+
+\subsection{Literal code} \label{sec:syntax-code}
+
+\begin{grammar}
+<code-definition> ::=
+  "code" <identifier> ":" <identifier> @[<constraints>@]
+  "{" <c-fragment> "}"
+
+<constraints> ::= "[" <constraint-list> "]"
+
+<constraint> ::= @<identifier>^+
+\end{grammar}
+
+The @<c-fragment> will be output unchanged to one of the output files.
+
+The first @<identifier> is the symbolic name of an output file.  Predefined
+output file names are @"c" and @"h", which are the implementation code and
+header file respectively; other output files can be defined by extensions.
+
+The second @<identifier> provides a name for the output item.  Several C
+fragments can have the same name: they will be concatenated together in the
+order in which they were encountered.
+
+The @<constraints> provide a means for specifying where in the output file
+the output item should appear.  (Note the two kinds of square brackets shown
+in the syntax: square brackets must appear around the constraints if they are
+present, but that they may be omitted.)  Each comma-separated @<constraint>
+is a sequence of identifiers naming output items, and indicates that the
+output items must appear in the order given -- though the translator is free
+to insert additional items in between them.  (The particular output items
+needn't be defined already -- indeed, they needn't be defined ever.)
+
+There is a predefined output item @"includes" in both the @"c" and @"h"
+output files which is a suitable place for inserting @"\#include"
+preprocessor directives in order to declare types and functions for use
+elsewhere in the generated output files.
+
+\subsection{Property sets} \label{sec:syntax.propset}
+
+\begin{grammar}
+<properties> ::= "[" <property-list> "]"
+
+<property> ::= <identifier> "=" <expression>
+\end{grammar}
+
+Property sets are a means for associating miscellaneous information with
+classes and related items.  By using property sets, additional information
+can be passed to extensions without the need to introduce idiosyncratic
+syntax.
+
+A property has a name, given as an @<identifier>, and a value computed by
+evaluating an @<expression>.  The value can be one of a number of types,
+though the only operators currently defined act on integer values only.
+
+\subsubsection{The expression evaluator} \label{sec:syntax.propset.expr}
+
+\begin{grammar}
+<expression> ::= <term> | <expression> "+" <term> | <expression> "-" <term>
+
+<term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor>
+
+<factor> ::= <primary> | "+" <factor> | "-" <factor>
+
+<primary> ::=
+     <integer-literal> | <string-literal> | <char-literal> | <identifier>
+\alt "?" <s-expression>
+\alt "(" <expression> ")"
+\end{grammar}
+
+The arithmetic expression syntax is simple and standard; there are currently
+no bitwise, logical, or comparison operators.
+
+A @<primary> expression may be a literal or an identifier.  Note that
+identifiers stand for themselves: they \emph{do not} denote values.  For more
+fancy expressions, the syntax
+\begin{quote}
+  @"?" @<s-expression>
+\end{quote}
+causes the @<s-expression> to be evaluated using the Lisp \textsf{eval}
+function.
+%%% FIXME crossref to extension docs
+
+\subsection{C types} \label{sec:syntax.c-types}
+
+Sod's syntax for C types closely mirrors the standard C syntax.  A C type has
+two parts: a sequence of @<declaration-specifier>s and a @<declarator>.  In
+Sod, a type must contain at least one @<declaration-specifier> (i.e.,
+`implicit @"int"' is forbidden), and storage-class specifiers are not
+recognized.
+
+\subsubsection{Declaration specifiers} \label{sec:syntax.c-types.declspec}
+
+\begin{grammar}
+<declaration-specifier> ::= <type-name>
+\alt "struct" <identifier> | "union" <identifier> | "enum" <identifier>
+\alt "void" | "char" | "int" | "float" | "double"
+\alt "short" | "long"
+\alt "signed" | "unsigned"
+\alt <qualifier>
+
+<qualifier> ::= "const" | "volatile" | "restrict"
+
+<type-name> ::= <identifier>
+\end{grammar}
+
+A @<type-name> is an identifier which has been declared as being a type name,
+using the @"typename" or @"class" definitions.
+
+Declaration specifiers may appear in any order.  However, not all
+combinations are permitted.  A declaration specifier must consist of zero or
+more @<qualifiers>, and one of the following, up to reordering.
+\begin{itemize}
+\item @<type-name>
+\item @"struct" @<identifier>, @"union" @<identifier>, @"enum" @<identifier>
+\item @"void"
+\item @"char", @"unsigned char", @"signed char"
+\item @"short", @"unsigned short", @"signed short"
+\item @"short int", @"unsigned short int", @"signed short int"
+\item @"int", @"unsigned int", @"signed int", @"unsigned", @"signed"
+\item @"long", @"unsigned long", @"signed long"
+\item @"long int", @"unsigned long int", @"signed long int"
+\item @"long long", @"unsigned long long", @"signed long long"
+\item @"long long int", @"unsigned long long int", @"signed long long int"
+\item @"float", @"double", @"long double"
+\end{itemize}
+All of these have their usual C meanings.
+
+\subsubsection{Declarators} \label{sec:syntax.c-types.declarator}
+
+\begin{grammar}
+<declarator>$[k]$ ::= @<pointer>^* <primary-declarator>$[k]$
+
+<primary-declarator>$[k]$ ::= $k$
+\alt "(" <primary-declarator>$[k]$ ")"
+\alt <primary-declarator>$[k]$ @<declarator-suffix>^*
+
+<pointer> ::= "*" @<qualifier>^*
+
+<declarator-suffix> ::= "[" <c-fragment> "]"
+\alt "(" <arguments> ")"
+
+<arguments> ::= $\epsilon$ | "..."
+\alt <argument-list> @["," "..."@]
+
+<argument> ::= @<declaration-specifier>^+ <argument-declarator>
+
+<argument-declarator> ::= <declarator>@[<identifier> @! $\epsilon$@]
+
+<simple-declarator> ::= <declarator>@[<identifier>@]
+
+<dotted-name> ::= <identifier> "." <identifier>
+
+<dotted-declarator> ::= <declarator>@[<dotted-name>@]
+\end{grammar}
+
+The declarator syntax is taken from C, but with some differences.
+\begin{itemize}
+\item Array dimensions are uninterpreted @<c-fragments>, terminated by a
+  closing square bracket.  This allows array dimensions to contain arbitrary
+  constant expressions.
+\item A declarator may have either a single @<identifier> at its centre or a
+  pair of @<identifier>s separated by a @`.'; this is used to refer to
+  slots or messages defined in superclasses.
+\end{itemize}
+The remaining differences are (I hope) a matter of presentation rather than
+substance.
+
+\subsection{Defining classes} \label{sec:syntax.class}
+
+\begin{grammar}
+<class-definition> ::= <class-forward-declaration>
+\alt <full-class-definition>
+\end{grammar}
+
+\subsubsection{Forward declarations} \label{sec:class.class.forward}
+
+\begin{grammar}
+<class-forward-declaration> ::= "class" <identifier> ";"
+\end{grammar}
+
+A @<class-forward-declaration> informs Sod that an @<identifier> will be used
+to name a class which is currently undefined.  Forward declarations are
+necessary in order to resolve certain kinds of circularity.  For example,
+\begin{listing}
+class Sub;
+
+class Super : SodObject {
+  Sub *sub;
+};
+
+class Sub : Super {
+  /* ... */
+};
+\end{listing}
+
+\subsubsection{Full class definitions} \label{sec:class.class.full}
+
+\begin{grammar}
+<full-class-definition> ::=
+  @[<properties>@]
+  "class" <identifier> ":" <identifier-list>
+  "{" @<class-item>^* "}"
+
+<class-item> ::= <slot-item> ";"
+\alt <message-item>
+\alt <method-item>
+\alt  <initializer-item> ";"
+\end{grammar}
+
+A full class definition provides a complete description of a class.
+
+The first @<identifier> gives the name of the class.  It is an error to
+give the name of an existing class (other than a forward-referenced class),
+or an existing type name.  It is conventional to give classes `MixedCase'
+names, to distinguish them from other kinds of identifiers.
+
+The @<identifier-list> names the direct superclasses for the new class.  It
+is an error if any of these @<identifier>s does not name a defined class.
+
+The @<properties> provide additional information.  The standard class
+properties are as follows.
+\begin{description}
+\item[@"lisp_class"] The name of the Lisp class to use within the translator
+  to represent this class.  The property value must be an identifier; the
+  default is @"sod_class".  Extensions may define classes with additional
+  behaviour, and may recognize additional class properties.
+\item[@"metaclass"] The name of the Sod metaclass for this class.  In the
+  generated code, a class is itself an instance of another class -- its
+  \emph{metaclass}.  The metaclass defines which slots the class will have,
+  which messages it will respond to, and what its behaviour will be when it
+  receives them.  The property value must be an identifier naming a defined
+  subclass of @"SodClass".  The default metaclass is @"SodClass".
+  %%% FIXME xref to theory
+\item[@"nick"] A nickname for the class, to be used to distinguish it from
+  other classes in various limited contexts.  The property value must be an
+  identifier; the default is constructed by forcing the class name to
+  lower-case.
+\end{description}
+
+The class body consists of a sequence of @<class-item>s enclosed in braces.
+These items are discussed on the following sections.
+
+\subsubsection{Slot items} \label{sec:sntax.class.slot}
+
+\begin{grammar}
+<slot-item> ::=
+  @[<properties>@]
+  @<declaration-specifier>^+ <init-declarator-list>
+
+<init-declarator> ::= <declarator> @["=" <initializer>@]
+\end{grammar}
+
+A @<slot-item> defines one or more slots.  All instances of the class and any
+subclass will contain these slot, with the names and types given by the
+@<declaration-specifiers> and the @<declarators>.  Slot declarators may not
+contain qualified identifiers.
+
+It is not possible to declare a slot with function type: such an item is
+interpreted as being a @<message-item> or @<method-item>.  Pointers to
+functions are fine.
+
+An @<initializer>, if present, is treated as if a separate
+@<initializer-item> containing the slot name and initializer were present.
+For example,
+\begin{listing}
+[nick = eg]
+class Example : Super {
+  int foo = 17;
+};
+\end{listing}
+means the same as
+\begin{listing}
+[nick = eg]
+class Example : Super {
+  int foo;
+  eg.foo = 17;
+};
+\end{listing}
+
+\subsubsection{Initializer items} \label{sec:syntax.class.init}
+
+\begin{grammar}
+<initializer-item> ::= @["class"@] <slot-initializer-list>
+
+<slot-initializer> ::= <qualified-identifier> "=" <initializer>
+
+<initializer> :: "{" <c-fragment> "}" | <c-fragment>
+\end{grammar}
+
+An @<initializer-item> provides an initial value for one or more slots.  If
+prefixed by @"class", then the initial values are for class slots (i.e.,
+slots of the class object itself); otherwise they are for instance slots.
+
+The first component of the @<qualified-identifier> must be the nickname of
+one of the class's superclasses (including itself); the second must be the
+name of a slot defined in that superclass.
+
+The initializer has one of two forms.
+\begin{itemize}
+\item A @<c-fragment> enclosed in braces denotes an aggregate initializer.
+  This is suitable for initializing structure, union or array slots.
+\item A @<c-fragment> \emph{not} beginning with an open brace is a `bare'
+  initializer, and continues until the next @`,' or @`;' which is not within
+  nested brackets.  Bare initializers are suitable for initializing scalar
+  slots, such as pointers or integers, and strings.
+\end{itemize}
+
+\subsubsection{Message items} \label{sec:syntax.class.message}
+
+\begin{grammar}
+<message-item> ::=
+  @[<properties>@]
+  @<declaration-specifier>^+ <declarator> @[<method-body>@]
+\end{grammar}
+
+\subsubsection{Method items} \label{sec:syntax.class.method}
+
+\begin{grammar}
+<method-item> ::=
+  @[<properties>@]
+  @<declaration-specifier>^+ <declarator> <method-body>
+
+<method-body> ::= "{" <c-fragment> "}" | "extern" ";"
+\end{grammar}
+
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
similarity index 86%
rename from doc/sod-tut.tex
rename to doc/tutorial.tex
index cff9859..afc6109 100644 (file)
@@ -23,8 +23,7 @@
 %%% along with SOD; if not, write to the Free Software Foundation,
 %%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
-\chapter{Tutorial}
-\label{ch:tut}
+\chapter{Tutorial} \label{ch:tutorial}
 
 This chapter provides a tutorial introduction to the Sod object system.  It
 intentionally misses out nitty-gritty details.  If you want those, the
@@ -35,7 +34,7 @@ You'll have to bear with him.  If you think you can do a better job, I'm sure
 that he'll be grateful for your contribution.
 
 %%%--------------------------------------------------------------------------
-\section{Introduction} \label{sec:tut.intro}
+\section{Introduction} \label{sec:tutorial.intro}
 
 Sod is an object system for the C~programming language.  Because it doesn't
 have enough already.  Actually, that's not right: it's got plenty already.
@@ -68,7 +67,7 @@ means that is has the following features.
 There's a good chance that half of that didn't mean anything to you.  Bear
 with me, though, because we'll explain it all eventually.
 
-\subsection{Building programs with Sod} \label{sec:tut.intro.build}
+\subsection{Building programs with Sod} \label{sec:tutorial.intro.build}
 
 Sod is basically a fancy preprocessor, in the same vein as Lex and Yacc.  It
 reads source files written in a vaguely C-like language.  It produces output
@@ -84,8 +83,8 @@ The main consequences of this are as follows.
 \item Sod hasn't made any attempt to improve C's syntax.  It's just as
   hostile to object-oriented programming as it ever was.  This means that
   you'll end up writing ugly things like
-  \begin{prog}%
-    thing->_vt->foo.frob(thing, mumble);%
+  \begin{prog}
+    thing->_vt->foo.frob(thing, mumble);
   \end{prog}
   fairly frequently.  This can be made somewhat less painful using macros,
   but we're basically stuck with C.  The upside is that you know exactly what
@@ -96,12 +95,12 @@ The main consequences of this are as follows.
 \end{itemize}
 Of course, this means that your build system needs to become more
 complicated.  If you use \man{make}{1}, then something like
-\begin{prog}%
-  SOD = sod
-
-  .SUFFIXES: .sod .c .h
-  .sod.c:; \$(SOD) -gc -o \$@@ \$<
-  .sod.h:; \$(SOD) -gh -o \$@@ \$< %
+\begin{prog}
+  SOD = sod \\
+  \\
+  .SUFFIXES: .sod .c .h \\
+  .sod.c:; \$(SOD) -tc \$< \\
+  .sod.h:; \$(SOD) -th \$<
 \end{prog}
 ought to do the job.
 
@@ -109,48 +108,47 @@ ought to do the job.
 \section{A traditional trivial introduction}
 
 The following is a simple Sod input file.
-\begin{prog}\quad\=\quad\=\kill%
-/* -*-sod-*- */
-
-code c : includes \{
-\#include "greeter.h"
-\}
-
-code h : includes \{
-\#include <stdio.h>
-\#include <sod.h>
+\begin{prog}
+/* -*-sod-*- */ \\
+\\
+code c : includes \{ \\
+\#include "greeter.h" \\
+\} \\
+\\
+code h : includes \{ \\
+\#include <stdio.h> \\
+\#include <sod/sod.h> \\
+\} \\
+\\
+class Greeter : SodObject \{ \\ \ind
+  void greet(FILE *fp) \{ \\ \ind
+    fputs("Hello, world!\textbackslash n", fp); \- \\
+  \} \- \\
 \}
-
-class Greeter : SodObject \{ \+
-  void greet(FILE *fp) \{ \+
-    fputs("Hello, world!\textbackslash n", fp); \-
-  \} \-
-\} %
 \end{prog}
 Save it as @"greeter.sod", and run
-\begin{prog}%
-sod --gc --gh greeter %
+\begin{prog}
+sod --gc --gh greeter
 \end{prog}
 This will create files @"greeter.c" and @"greeter.h" in the current
 directory.  Here's how we might use such a simple thing.
-\begin{prog}\quad\=\kill%
-\#include "greeter.h"
-
-int main(void)
-\{ \+
-  struct Greeter__ilayout g_obj;
-  Greeter *g = Greeter__class->cls.init(\&g_obj);
-
-  g->_vt.greeter.greet(g, stdout);
-  return (0); \-
-\} %
+\begin{prog}
+\#include "greeter.h" \\
+\\
+int main(void) \\
+\{ \\ \ind
+  SOD_DECL(Greeter, g); \\
+  \\
+  Greeter_greet(g, stdout); \\
+  return (0); \- \\
+\}
 \end{prog}
 Compare this to the traditional
-\begin{prog}\quad\=\kill%
-\#include <stdio.h>
-
-int main(void) \+
-  \{ fputs("Hello, world\\n", stdout); return (0); \} %
+\begin{prog}
+\#include <stdio.h> \\
+\\
+int main(void) \\ \ind
+  \{ fputs("Hello, world@\\n", stdout); return (0); \}
 \end{prog}
 and I'm sure you'll appreciate the benefits of using Sod already -- mostly to
 do with finger exercise.  Trust me, it gets more useful.
@@ -161,13 +159,13 @@ it (after the comment which tells Emacs how to cope with it).
 The first part consists of the two @"code" stanzas.  Both of them define
 gobbets of raw C code to copy into output files.  The first one, @"code~:
 c"~\ldots, says that
-\begin{prog}%
-  \#include "greeter.h" %
+\begin{prog}
+  \#include "greeter.h"
 \end{prog}
 needs to appear in the generated @|greeter.c| file; the second says that
-\begin{prog}%
-  \#include <stdio.h>
-  \#include <sod.h> %
+\begin{prog}
+  \#include <stdio.h> \\
+  \#include <sod/sod.h>
 \end{prog}
 needs to appear in the header file @|greeter.h|.  The generated C files need
 to get declarations for external types and functions (e.g., @"FILE" and
@@ -176,10 +174,10 @@ declarations from the corresponding @".h" file.  Sod takes a very simple
 approach to all of this: it expects you, the programmer, to deal with it.
 
 The basic syntax for @"code" stanzas is
-\begin{prog}\quad\=\kill%
-  code @<file-label> : @<section> \{
-  \>  @<code>
-  \} %
+\begin{prog}
+  code @<file-label> : @<section> \{ \\ \ind
+    @<code> \- \\
+  \}
 \end{prog}
 The @<file-label> is either @"c" or @"h", and says which output file the code
 wants to be written to.  The @<section> is a name which explains where in the
@@ -193,13 +191,13 @@ message.
 
 So far, so good.  The C code, which we thought we understood, contains some
 bizarre looking runes.  Let's take it one step at a time.
-\begin{prog}%
-  struct Greeter__ilayout g_obj; %
+\begin{prog}
+  struct Greeter__ilayout g_obj;
 \end{prog}
 allocates space for an instance of class @"Greeter".  We're not going to use
 this space directly.  Instead, we do this frightening looking thing.
-\begin{prog}%
-  Greeter *g = Greeter__class->cls.init(\&g_obj); %
+\begin{prog}
+  Greeter *g = Greeter__class->cls.init(\&g_obj);
 \end{prog}
 Taking it slowly: @"Greeter__class" is a pointer to the object that
 represents our class @"Greeter".  This object contains a member, named
@@ -209,8 +207,8 @@ the instance, which we use in preference to grovelling about in the
 @"ilayout" structure.
 
 Having done this, we `send the instance a message':
-\begin{prog}%
-  g->_vt->greeter.greet(g, stdout); %
+\begin{prog}
+  g->_vt->greeter.greet(g, stdout);
 \end{prog}
 This looks horrific, and seems to repeat itself quite unnecessarily.  The
 first @"g" is the recipient of our `message'.  The second is indeed a copy of
index 6aefc9d..bc181ee 100644 (file)
@@ -192,11 +192,13 @@ has no direct superclasses,
 and
 .B SodClass
 is its own metaclass.
-It is not possible to define root classes because of circularities:
+It is not possible to define root classes in module files
+because of circularities:
 .B SodObject
 has
 .B SodClass
-as its metaclass, and
+as its metaclass,
+and
 .B SodClass
 is a subclass of
 .BR SodObject .
@@ -546,7 +548,8 @@ and this is followed by corresponding members
 .IB a ;
 .PP
 for each of
-.IR C 's superclasses
+.IR C 's
+superclasses
 .IR A
 in the same chain in some (unimportant) order.
 A `pointer to
@@ -617,13 +620,17 @@ each
 .B ichain
 must have as a prefix the
 .B ichain
-for each superclass in the same chain, and
-each slot must be stored in exactly one place.
+for each superclass in the same chain,
+and each slot must be stored in exactly one place.
 The layout of vtables doesn't have this second requirement:
 it doesn't matter that there are
 multiple method entry pointers
 for the same effective method
 as long as they all work correctly.
+Indeed, it's essential that they do,
+because each chain's method entry function
+will need to apply a different offset to the receiver pointer
+before invoking the effective method.
 .PP
 A vtable for a class
 .I C
@@ -655,10 +662,8 @@ extern const union \fIC\fB__vtu_\fIh\fB \fIC\fB__vtable_\fIh\fB;
 .fi
 .PP
 The outer layer is a
-.IP
 .B union
 .IB C __vtu_ h
-.PP
 containing a member
 .IP
 .B struct
@@ -718,7 +723,7 @@ of
 The metaclass
 .I R
 of
-.IR O .
+.I O
 is then the
 .I root metaclass
 of
@@ -781,7 +786,7 @@ be the most specific superclass of
 in the same chain as
 .IR J .
 Then, if there is currently no class pointer of type
-.I Q
+.IR Q ,
 then add a member
 .RS
 .IP
@@ -825,7 +830,7 @@ If class
 .I A
 defines any messages,
 and there is currently no member
-.I a
+.IR a ,
 then add a member
 .RS
 .IP
index 4a0f6e2..ed65110 100644 (file)
 (export '(c-function-type c-function-arguments))
 (defclass c-function-type (c-type)
   ((subtype :initarg :subtype :type c-type :reader c-type-subtype)
-   (arguments :initarg :arguments :type list :reader c-function-arguments))
+   (arguments :type list :reader c-function-arguments))
   (:documentation
    "C function types.  The subtype is the return type, as implied by the C
     syntax for function declarations."))
 
+(defmethod shared-initialize :after
+    ((type c-function-type) slot-names &key (arguments nil argsp))
+  (declare (ignore slot-names))
+  (when argsp
+    (setf (slot-value type 'arguments)
+         (if (and arguments
+                  (null (cdr arguments))
+                  (not (eq (car arguments) :ellipsis))
+                  (eq (argument-type (car arguments)) c-type-void))
+             nil
+             arguments))))
+
 ;; Constructor function.
 
 (export 'make-function-type)
 (defun make-function-type (subtype arguments)
   "Return a new function type, returning SUBTYPE and accepting ARGUMENTS."
   (make-instance 'c-function-type :subtype subtype
-                :arguments (if (and arguments
-                                    (null (cdr arguments))
-                                    (not (eq (car arguments) :ellipsis))
-                                    (eq (argument-type (car arguments))
-                                        c-type-void))
-                               nil
-                               arguments)))
+                :arguments arguments))
 
 ;; Comparison protocol.
 
index b9b61bf..edadd64 100644 (file)
    "Produce a `commentified' version of the argument.
 
    The default behaviour is that temporary argument names are simply omitted
-   (NIL is returned); otherwise, `/*...*/' markers are wrapped around the
+   (nil is returned); otherwise, `/*...*/' markers are wrapped around the
    printable representation of the argument.")
   (:method ((name null)) nil)
   (:method ((name t)) (format nil "/*~A*/" name)))
index 878f813..29a30c1 100644 (file)
 ;;;--------------------------------------------------------------------------
 ;;; Classes.
 
+(defun maximum (items order what)
+  "Return a maximum item according to the non-strict partial ORDER."
+  (reduce (lambda (best this)
+           (cond ((funcall order best this) best)
+                 ((funcall order this best) this)
+                 (t (error "Unable to choose best ~A." what))))
+         items))
+
 (defmethod guess-metaclass ((class sod-class))
   "Default metaclass-guessing function for classes.
 
    Return the most specific metaclass of any of the CLASS's direct
    superclasses."
-  (do ((supers (sod-class-direct-superclasses class) (cdr supers))
-       (meta nil (let ((candidate (sod-class-metaclass (car supers))))
-                  (cond ((null meta) candidate)
-                        ((sod-subclass-p meta candidate) meta)
-                        ((sod-subclass-p candidate meta) candidate)
-                        (t (error "Unable to choose metaclass for `~A'"
-                                  class))))))
-      ((endp supers) meta)))
+  (maximum (mapcar #'sod-class-metaclass
+                  (sod-class-direct-superclasses class))
+          #'sod-subclass-p
+          (format nil "metaclass for `~A'" class)))
 
 (defmethod shared-initialize :after ((class sod-class) slot-names &key pset)
   "Specific behaviour for SOD class initialization.
@@ -66,7 +70,8 @@
   ;; If no metaclass, guess one in a (Lisp) class-specific way.
   (default-slot-from-property (class 'metaclass slot-names)
       (pset :metaclass :id meta (find-sod-class meta))
-    (guess-metaclass class))
+    (and (sod-class-direct-superclasses class)
+        (guess-metaclass class)))
 
   ;; If no chain-link, then start a new chain here.
   (default-slot-from-property (class 'chain-link slot-names)
index c04727c..8b024bd 100644 (file)
 
   (with-default-error-location (location)
     (let* ((pset (property-set pset))
-          (class (make-instance (get-property pset :lisp-metaclass :symbol
-                                              'sod-class)
+          (best-class (or (get-property pset :lisp-metaclass :symbol nil)
+                          (if superclasses
+                              (maximum (mapcar #'class-of superclasses)
+                                       #'subtypep
+                                       (format nil "Lisp metaclass for ~A"
+                                               name))
+                              'sod-class)))
+          (class (make-instance best-class
                                 :name name
                                 :superclasses superclasses
                                 :location (file-location location)
index 170f4a8..d988b12 100644 (file)
   ((in-use-p :initarg :in-use-p :initform nil
             :type boolean :accessor var-in-use-p)))
 
+(define-module-var *temporary-index* 0
+  "Index for temporary name generation.
+
+   This is automatically reset to zero before the output functions are
+   invoked to write a file.  This way, we can ensure that the same output
+   file is always produced from the same input.")
+
+(define-clear-the-decks reset-codegen-index
+  (setf *temporary-index* 0))
+
 (defmethod commentify-argument-name ((name temporary-name))
   nil)
 
 ;; package.  The `definst' machinery will symbolicate the various associated
 ;; methods correctly despite this subterfuge.
 
-(definst if (stream :export t) (#1=#:condition consequent alternative)
-  (format-compound-statement (stream consequent alternative)
+(definst if (stream :export t) (#1=#:cond conseq alt)
+  (format-compound-statement (stream conseq alt)
     (format stream "if (~A)" #1#))
-  (when alternative
-    (format-compound-statement (stream alternative)
+  (when alt
+    (format-compound-statement (stream alt)
       (write-string "else" stream))))
 
-(definst while (stream :export t) (#1=#:condition body)
+(definst while (stream :export t) (#1=#:cond body)
   (format-compound-statement (stream body)
     (format stream "while (~A)" #1#)))
 
-(definst do-while (stream :export t) (body #1=#:condition)
+(definst do-while (stream :export t) (body #1=#:cond)
   (format-compound-statement (stream body :space)
     (write-string "do" stream))
   (format stream "while (~A);" #1#))
index 535839c..6b1f947 100644 (file)
   (:documentation
    "Base class for temporary variable and argument names."))
 
-;; Important variables.
-
-(defparameter *temporary-index* 0
-  "Index for temporary name generation.
-
-   This is automatically reset to zero before the output functions are
-   invoked to write a file.  This way, we can ensure that the same output
-   file is always produced from the same input.")
-
-(define-clear-the-decks reset-codegen-index
-  (setf *temporary-index* 0))
-
 ;; Important temporary names.
 
 (export '(*sod-ap* *sod-master-ap*))
index 5df72f1..fe07cc8 100644 (file)
 (cl:in-package #:sod)
 
 ;;;--------------------------------------------------------------------------
+;;; Miscellaneous details.
+
+(export '*sod-version*)
+(defparameter *sod-version* sod-sysdef:*version*
+  "The version of the SOD translator system, as a string.")
+
+;;;--------------------------------------------------------------------------
 ;;; Debugging utilities.
 
 (export '*debugout-pathname*)
index 98652ec..0336d1a 100644 (file)
@@ -25,7 +25,7 @@
 
 (cl:defpackage #:sod-frontend
   (:use #:common-lisp #:optparse #:sod #:sod-parser)
-  (:shadowing-import-from #:optparse "INT"))
+  (:shadowing-import-from #:optparse #:int))
 
 (cl:in-package #:sod-frontend)
 
diff --git a/src/lexer-bits.lisp b/src/lexer-bits.lisp
deleted file mode 100644 (file)
index b671164..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-(cl:in-package #:sod)
-
-(defun play-fetch-token (string)
-  (with-parser-context (string-parser :string string)
-    (labels ((digit (radix)
-              (parse (filter (lambda (ch)
-                               (digit-char-p ch radix)))))
-            (number (radix &optional (initial 0))
-              (parse (many (a initial (+ (* radix a) it))
-                       (digit radix))))
-            (numeric (radix sigil)
-              (parse (seq ((first (peek (seq ((nil (funcall sigil))
-                                              (d (digit radix)))
-                                          d)))
-                           (result (number radix first)))
-                       result))))
- (multiple-value-call #'values
-    (loop
-       (parse :whitespace)
-
-       (cond-parse ()
-
-        ;; Give up at end-of-file.
-        (:eof
-         (return (values :eof nil)))
-
-        ;; Pick out comments.
-        ((peek (and #\/ #\*))
-         (parse (skip-many ()          ; this may fail at eof; don't worry
-                  (and (skip-many () (not #\*))
-                       (skip-many (:min 1) #\*))
-                  (not #\/)))
-         (if-parse :eof ()
-           (cerror* "Unterminated comment")
-           (parse :any)))
-        ((and (peek (seq (#\/ #\/)))
-              (skip-many () (not #\newline))
-              (or :eof #\newline)))
-
-        ;; Quoted strings and characters.
-        ((or #\' #\")
-         (let ((quote it)
-               (out (make-string-output-stream)))
-           (parse (skip-many ()
-                    (or (seq ((ch (satisfies (lambda (ch)
-                                               (and (char/= ch #\\)
-                                                    (char/= ch quote))))))
-                          (write-char ch out))
-                        (seq (#\\ (ch :any))
-                          (write-char ch out)))))
-           (if-parse :eof ()
-             (cerror* "Unterminated ~:[string~;character~] constant"
-                      (char= quote #\'))
-             (parse :any))
-           (let ((string (get-output-stream-string out)))
-             (ecase quote
-               (#\" (return (values :string string)))
-               (#\' (case (length string)
-                      (0 (cerror* "Empty character constant")
-                         (return (values :char #\?)))
-                      (1 (return (values :char (char string 0))))
-                      (t (cerror* "Multiple characters in ~
-                                   character constant")
-                         (return (values :char (char string 0))))))))))
-
-        ;; Identifiers.
-        ((seq ((first (satisfies (lambda (ch)
-                                   (or (char= ch #\_)
-                                       (alpha-char-p ch)))))
-               (ident (many (out (let ((s (make-string-output-stream)))
-                                   (write-char first s)
-                                   s)
-                                 (progn (write-char it out) out)
-                             :final (get-output-stream-string out))
-                        (satisfies (lambda (ch)
-                                     (or (char= ch #\_)
-                                         (alphanumericp ch)))))))
-           (return (values :id ident))))
-
-        ;; Numbers -- uses the machinery in the labels above.
-        ((or (seq (#\0
-                   (i (or (numeric 8 (parser () (or #\o #\O)))
-                          (numeric 16 (parser () (or #\x #\X)))
-                          (number 8))))
-               i)
-             (seq ((first (digit 10))
-                   (rest (number 10 first)))
-               rest))
-         (return (values :integer it)))
-
-        ;; Special separator tokens.
-        ("..."
-         (return (values :ellipsis :ellipsis)))
-
-        ;; Anything else is a standalone delimiter character.
-        (:any
-         (return (values it it)))))
-    (parse (list () :any))))))
index d2181e1..b7653b4 100644 (file)
@@ -99,6 +99,7 @@
                (scanner-current-char char-scanner))
           (and consumedp (file-location char-scanner))))
 
+(export 'skip-until)
 (defparse skip-until (:context (context token-scanner-context)
                      (&key (keep-end nil keep-end-p))
                      &rest token-types)
               :keep-end ,(if keep-end-p keep-end
                              (> (length token-types) 1))))
 
+(export 'error)
 (defparse error (:context (context token-scanner-context)
                 (&key) sub &optional (recover t))
   "Try to parse SUB; if it fails then report an error, and parse RECOVER.
 ;;;--------------------------------------------------------------------------
 ;;; Lexical analysis utilities.
 
+(export 'scan-comment)
 (defun scan-comment (char-scanner)
   "Scan a comment (either `/* ... */' or `// ...') from CHAR-SCANNER.
 
index fe6b545..08679ce 100644 (file)
 ;;;--------------------------------------------------------------------------
 ;;; Code fragments.
 
-(export 'c-fragment)
+(export '(c-fragment c-fragment-text))
 (defclass c-fragment ()
-  ((location :initarg :location :type file-location
-            :accessor c-fragment-location)
-   (text :initarg :text :type string :accessor c-fragment-text))
+  ((location :initarg :location :type file-location :reader file-location)
+   (text :initarg :text :type string :reader c-fragment-text))
   (:documentation
    "Represents a fragment of C code to be written to an output file.
 
 
 (defmethod print-object ((fragment c-fragment) stream)
   (let ((text (c-fragment-text fragment))
-       (location (c-fragment-location fragment)))
+       (location (file-location fragment)))
     (if *print-escape*
        (print-unreadable-object (fragment stream :type t)
          (when location
index 70bb012..a2ac290 100644 (file)
   (do-case2-like 'ecase vform clauses))
 
 ;;;--------------------------------------------------------------------------
-;;; Locatives.
-
-(export '(loc locp))
-(defstruct (loc (:predicate locp) (:constructor make-loc (reader writer)))
-  "Locative data type.  See `locf' and `ref'."
-  (reader nil :type function)
-  (writer nil :type function))
-
-(export 'locf)
-(defmacro locf (place &environment env)
-  "Slightly cheesy locatives.
-
-   (locf PLACE) returns an object which, using the `ref' function, can be
-   used to read or set the value of PLACE.  It's cheesy because it uses
-   closures rather than actually taking the address of something.  Also,
-   unlike Zetalisp, we don't overload `car' to do our dirty work."
-  (multiple-value-bind
-      (valtmps valforms newtmps setform getform)
-      (get-setf-expansion place env)
-    `(let* (,@(mapcar #'list valtmps valforms))
-       (make-loc (lambda () ,getform)
-                (lambda (,@newtmps) ,setform)))))
-
-(export 'ref)
-(declaim (inline ref (setf ref)))
-(defun ref (loc)
-  "Fetch the value referred to by a locative."
-  (funcall (loc-reader loc)))
-(defun (setf ref) (new loc)
-  "Store a new value in the place referred to by a locative."
-  (funcall (loc-writer loc) new))
-
-(export 'with-locatives)
-(defmacro with-locatives (locs &body body)
-  "Evaluate BODY with implicit locatives.
-
-   LOCS is a list of items of the form (SYM [LOC-EXPR]), where SYM is a
-   symbol and LOC-EXPR evaluates to a locative.  If LOC-EXPR is omitted, it
-   defaults to SYM.  As an abbreviation for a common case, LOCS may be a
-   symbol instead of a list.
-
-   The BODY is evaluated in an environment where each SYM is a symbol macro
-   which expands to (ref LOC-EXPR) -- or, in fact, something similar which
-   doesn't break if LOC-EXPR has side-effects.  Thus, references, including
-   `setf' forms, fetch or modify the thing referred to by the LOC-EXPR.
-   Useful for covering over where something uses a locative."
-  (setf locs (mapcar (lambda (item)
-                      (cond ((atom item) (list item item))
-                            ((null (cdr item)) (list (car item) (car item)))
-                            (t item)))
-                    (if (listp locs) locs (list locs))))
-  (let ((tt (mapcar (lambda (l) (declare (ignore l)) (gensym)) locs))
-       (ll (mapcar #'cadr locs))
-       (ss (mapcar #'car locs)))
-    `(let (,@(mapcar (lambda (tmp loc) `(,tmp ,loc)) tt ll))
-       (symbol-macrolet (,@(mapcar (lambda (sym tmp)
-                                    `(,sym (ref ,tmp))) ss tt))
-        ,@body))))
-
-;;;--------------------------------------------------------------------------
 ;;; Standard error-reporting functions.
 
 (export 'moan)
index d6e47f4..4ae7da7 100644 (file)
@@ -30,8 +30,4 @@
 
 (cl:in-package #:sod)
 
-(export '*sod-version*)
-(defparameter *sod-version* sod-sysdef:*version*
-  "The version of the SOD translator system, as a string.")
-
 ;;;----- That's all, folks --------------------------------------------------
index 5ae4035..41c154f 100644 (file)
          (let ((head (car opstack)))
            (cond ((not (typep head 'open-parenthesis))
                   (apply-operator head state))
-                 ((not (eq (slot-value head 'tag) tag))
+                 ((not (eql (slot-value head 'tag) tag))
                   (fail))
                  (t
                   (return)))
index ec35445..929e85a 100644 (file)
@@ -41,7 +41,7 @@
   (:documentation
    "Push VALUE onto the STATE's value stack.
 
-   The default message just does that without any fuss.  It's unlikely that
+   The default method just does that without any fuss.  It's unlikely that
    this will need changing unless you invent some really weird values."))
 
 (export 'apply-operator)
index d458e70..4bd1ae4 100644 (file)
@@ -77,6 +77,7 @@
 ;;;--------------------------------------------------------------------------
 ;;; Utilities.
 
+(export 'combine-parser-failures)
 (defun combine-parser-failures (failures)
   "Combine the failure indicators listed in FAILURES.
 
index 1919b69..f9cd792 100644 (file)
    and wishes to read more.  If DONEP is true then the condition (<= START
    USED END) must hold; the FUNC has consumed the buffer as far as USED
    (exclusive) and has completed successfully; the values DONEP and `t' are
-   returned as the result of `charbuf-scanner-map'.
+   returned as the result of `charbuf-scanner-map', along with a CONSUMEDP
+   flag.
 
    If end-of-file is encountered before FUNC completes successfully then FAIL
-   is called with no arguments, and `charbuf-scanner-map' returns whatever
-   FAIL returns.
+   is called with no arguments and expected to return two values, and
+   `charbuf-scanner-map' returns these values, along with a CONSUMEDP flag.
 
    Observe that, if FAIL returns a second value of nil, then
    `charbuf-scanner-map' is usable as a parser expression."))
 (defmethod charbuf-scanner-map
     ((scanner charbuf-scanner) func &optional fail)
   (with-slots (buf index size) scanner
-    (flet ((offer (buf start end)
-
-            ;; Pass the buffer to the function, and see what it thought.
-            (multiple-value-bind (donep used) (funcall func buf start end)
-
-              ;; Update the position as far as the function read.
-              (with-slots (line column) scanner
-                (let ((l line) (c column) (limit (if donep used end)))
-                  (do ((i start (1+ i)))
-                      ((>= i limit))
-                    (setf (values l c)
-                          (update-position (char buf i) l c)))
-                  (setf line l column c)))
-
-              ;; If the function is finished then update our state and
-              ;; return.
-              (when donep
-                (setf index used)
-                (when (>= index size)
-                  (charbuf-scanner-fetch scanner))
-                (return-from charbuf-scanner-map (values donep t))))))
-
-      ;; If there's anything in the current buffer, offer it to the function.
-      (when (< index size)
-       (offer buf index size))
-
-      ;; Repeatedly fetch new buffers and offer them to the function.
-      ;; Because the buffers are fresh, we know that we must process them
-      ;; from the beginning.  Note that `offer' will exit if FUNC has
-      ;; finished, so we don't need to worry about that.
-      (loop
-       (unless (charbuf-scanner-fetch scanner)
-         (return (if fail (funcall fail) (values nil nil))))
-       (offer buf 0 size)))))
+    (let ((consumedp nil))
+      (flet ((offer (buf start end)
+
+              ;; Pass the buffer to the function, and see what it thought.
+              (multiple-value-bind (donep used) (funcall func buf start end)
+
+                ;; Update the position as far as the function read.
+                (with-slots (line column) scanner
+                  (let ((l line) (c column) (limit (if donep used end)))
+                    (do ((i start (1+ i)))
+                        ((>= i limit))
+                      (setf (values l c)
+                            (update-position (char buf i) l c)))
+                    (setf line l column c)))
+
+                ;; If the function is finished then update our state and
+                ;; return.
+                (when donep
+                  (setf index used)
+                  (when (>= index size)
+                    (charbuf-scanner-fetch scanner))
+                  (return-from charbuf-scanner-map
+                    (values donep t (or consumedp (> used start)))))
+
+                ;; We've definitely used that buffer.
+                (setf consumedp t))))
+
+       ;; If there's anything in the current buffer, offer it to the
+       ;; function.
+       (when (< index size)
+         (offer buf index size))
+
+       ;; Repeatedly fetch new buffers and offer them to the function.
+       ;; Because the buffers are fresh, we know that we must process them
+       ;; from the beginning.  Note that `offer' will exit if FUNC has
+       ;; finished, so we don't need to worry about that.
+       (loop
+         (unless (charbuf-scanner-fetch scanner)
+           (return (if fail
+                       (multiple-value-bind (result win) (funcall fail)
+                         (values result win consumedp))
+                       (values nil nil consumedp))))
+         (offer buf 0 size))))))
 
 ;;;--------------------------------------------------------------------------
 ;;; Initialization.
     (unless end (setf end (length seq)))
     (let ((i start) (n (- end start)))
       (labels ((copy (i buf start end)
-                (do ((j i (1+ j))
-                     (k start (1+ k)))
-                    ((>= k end))
-                  (setf (char seq j) (schar buf k))))
+                (replace seq buf :start1 i :start2 start :end2 end))
               (snarf (buf start end)
                 (let ((m (- end start)))
                   (cond ((< m n)
       (flet ((snarf (buf start end)
               (let ((pos (position #\newline buf :start start :end end)))
                 (push (make-charbuf-slice buf start (or pos end)) slices)
-                (if pos
-                    (values (concatenate-charbuf-slices (nreverse slices))
-                            (1+ pos))
-                    (values nil 0))))
-            (fail ()
-              (values (concatenate-charbuf-slices (nreverse slices)) t)))
-       (charbuf-scanner-map scanner #'snarf #'fail)))))
+                (values pos (and pos (1+ pos))))))
+       (multiple-value-bind (result eofp consumedp)
+           (charbuf-scanner-map scanner #'snarf)
+         (declare (ignore result consumedp))
+         (values (concatenate-charbuf-slices (nreverse slices))) eofp)))))
 
 ;;;----- That's all, folks --------------------------------------------------
index 2abdff4..4909be9 100644 (file)
   (with-slots ((string %string) index) scanner
     (subseq string place-a (or place-b index))))
 
+(defmethod make-scanner-stream ((scanner string-scanner))
+  (make-instance 'character-scanner-stream :scanner scanner))
+
 ;;;--------------------------------------------------------------------------
 ;;; List scanner.
 
-(export 'list-scanner)
+(export '(list-scanner list-scanner-p make-list-scanner))
 (defstruct (list-scanner
             (:constructor make-list-scanner (list &aux (%list list))))
   "Simple token scanner for lists.
index e58a928..332bcef 100644 (file)
 (defun pset-get (pset key)
   "Look KEY up in PSET and return what we find.
 
-   If there's no property by that name, return NIL."
+   If there's no property by that name, return nil."
   (values (gethash key (%pset-hash pset))))
 
 (defun pset-store (pset prop)
          ((endp list) pset)
        (add-property pset (funcall name list) (funcall value list))))))
 
-(export 'check--unused-properties)
+(export 'check-unused-properties)
 (defun check-unused-properties (pset)
   "Issue errors about unused properties in PSET."
   (when pset
 ;;; Utility macros.
 
 (defmacro default-slot-from-property
-    ((instance slot slot-names)
+    ((instance slot &optional (slot-names t))
      (pset property type
       &optional (pvar (gensym "PROP-"))
       &rest convert-forms)
index 98d314a..d1755da 100644 (file)
            body)))
 
 ;;;--------------------------------------------------------------------------
+;;; Locatives.
+
+(export '(loc locp))
+(defstruct (loc (:predicate locp) (:constructor make-loc (reader writer)))
+  "Locative data type.  See `locf' and `ref'."
+  (reader nil :type function)
+  (writer nil :type function))
+
+(export 'locf)
+(defmacro locf (place &environment env)
+  "Slightly cheesy locatives.
+
+   (locf PLACE) returns an object which, using the `ref' function, can be
+   used to read or set the value of PLACE.  It's cheesy because it uses
+   closures rather than actually taking the address of something.  Also,
+   unlike Zetalisp, we don't overload `car' to do our dirty work."
+  (multiple-value-bind
+      (valtmps valforms newtmps setform getform)
+      (get-setf-expansion place env)
+    `(let* (,@(mapcar #'list valtmps valforms))
+       (make-loc (lambda () ,getform)
+                (lambda (,@newtmps) ,setform)))))
+
+(export 'ref)
+(declaim (inline ref (setf ref)))
+(defun ref (loc)
+  "Fetch the value referred to by a locative."
+  (funcall (loc-reader loc)))
+(defun (setf ref) (new loc)
+  "Store a new value in the place referred to by a locative."
+  (funcall (loc-writer loc) new))
+
+(export 'with-locatives)
+(defmacro with-locatives (locs &body body)
+  "Evaluate BODY with implicit locatives.
+
+   LOCS is a list of items of the form (SYM [LOC-EXPR]), where SYM is a
+   symbol and LOC-EXPR evaluates to a locative.  If LOC-EXPR is omitted, it
+   defaults to SYM.  As an abbreviation for a common case, LOCS may be a
+   symbol instead of a list.
+
+   The BODY is evaluated in an environment where each SYM is a symbol macro
+   which expands to (ref LOC-EXPR) -- or, in fact, something similar which
+   doesn't break if LOC-EXPR has side-effects.  Thus, references, including
+   `setf' forms, fetch or modify the thing referred to by the LOC-EXPR.
+   Useful for covering over where something uses a locative."
+  (setf locs (mapcar (lambda (item)
+                      (cond ((atom item) (list item item))
+                            ((null (cdr item)) (list (car item) (car item)))
+                            (t item)))
+                    (if (listp locs) locs (list locs))))
+  (let ((tt (mapcar (lambda (l) (declare (ignore l)) (gensym)) locs))
+       (ll (mapcar #'cadr locs))
+       (ss (mapcar #'car locs)))
+    `(let (,@(mapcar (lambda (tmp loc) `(,tmp ,loc)) tt ll))
+       (symbol-macrolet (,@(mapcar (lambda (sym tmp)
+                                    `(,sym (ref ,tmp))) ss tt))
+        ,@body))))
+
+;;;--------------------------------------------------------------------------
 ;;; Anaphorics.
 
 (export 'it)
            `((defun (setf ,from) (value object)
                (setf (,to object) value))))))
 
-(export 'define-on-demand-slot)
-(defmacro define-on-demand-slot (class slot (instance) &body body)
-  "Defines a slot which computes its initial value on demand.
-
-   Sets up the named SLOT of CLASS to establish its value as the implicit
-   progn BODY, by defining an appropriate method on `slot-unbound'."
-  (with-gensyms (classvar slotvar)
-    `(defmethod slot-unbound
-        (,classvar (,instance ,class) (,slotvar (eql ',slot)))
-       (declare (ignore ,classvar))
-       (setf (slot-value ,instance ',slot) (progn ,@body)))))
-
 ;;;--------------------------------------------------------------------------
 ;;; CLOS hacking.
 
        (setf (slot-value ,instance ,slot)
             (progn ,@value)))))
 
+(export 'define-on-demand-slot)
+(defmacro define-on-demand-slot (class slot (instance) &body body)
+  "Defines a slot which computes its initial value on demand.
+
+   Sets up the named SLOT of CLASS to establish its value as the implicit
+   progn BODY, by defining an appropriate method on `slot-unbound'."
+  (with-gensyms (classvar slotvar)
+    `(defmethod slot-unbound
+        (,classvar (,instance ,class) (,slotvar (eql ',slot)))
+       (declare (ignore ,classvar))
+       (setf (slot-value ,instance ',slot) (progn ,@body)))))
+
 ;;;----- That's all, folks --------------------------------------------------