*.out
*.log
*.dvi
+*.toc
*.aux
+_region_.tex
Makefile.in
/COPYING
/COPYING.LIB
/autom4te.cache/
/config/
/configure
-/doc/SYMBOLS
## The runtime support library.
SUBDIRS += lib
+## The manual.
+SUBDIRS += doc
+
## The tests and examples.
SUBDIRS += test
## sod
EXTRA_DIST += debian/sod.install
+## sod-doc
+EXTRA_DIST += debian/sod-doc.install
+
## sod-dev
EXTRA_DIST += debian/sod-dev.install
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 =
###--------------------------------------------------------------------------
### Subdirectories to build
-SUBDIRS = src lib test
+SUBDIRS = src lib doc test
###--------------------------------------------------------------------------
### Package-configuration file.
#! /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>.
#
# 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=''
# 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]...
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
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.
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 $@
# Define the identity of the package.
PACKAGE='sod'
- VERSION='0.2.0-30-g58a9'
+ VERSION='0.2.0-86-g67d1'
cat >>confdefs.h <<_ACEOF
## 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#*-}
-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
# 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
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\\"
"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;;
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 --------------------------------------------------
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
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
#! /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
--- /dev/null
+usr/share/doc/sod/* /usr/share/doc/sod-doc/
--- /dev/null
+### -*-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 --------------------------------------------------
--- /dev/null
+# 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:
--- /dev/null
+-----------------------------------------------------------------------------
+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
+
%%% -*-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| \- \\
@|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.
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.
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.
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>.
@<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
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
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
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}
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}
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
\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
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}
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
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
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}
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).
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).
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>.
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
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:
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
(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"))))
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
+++ /dev/null
-%%% -*-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:
--- /dev/null
+%%% -*-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
-\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
--- /dev/null
+%%% -*-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:
--- /dev/null
+%%% -*-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:
%%% 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
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.
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
\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
\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.
\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.
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
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
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
@"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
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 .
.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
.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
.fi
.PP
The outer layer is a
-.IP
.B union
.IB C __vtu_ h
-.PP
containing a member
.IP
.B struct
The metaclass
.I R
of
-.IR O .
+.I O
is then the
.I root metaclass
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
.I A
defines any messages,
and there is currently no member
-.I a
+.IR a ,
then add a member
.RS
.IP
(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.
"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)))
;;;--------------------------------------------------------------------------
;;; 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.
;; 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)
(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)
((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#))
(: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*))
(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.
(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)
+++ /dev/null
-(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))))))
(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.
;;;--------------------------------------------------------------------------
;;; 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
"Like `case2', but signals an error if no clause matches the SCRUTINEE."
(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.
(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 --------------------------------------------------
(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)))
(: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)
;;;--------------------------------------------------------------------------
;;; Utilities.
+(export 'combine-parser-failures)
(defun combine-parser-failures (failures)
"Combine the failure indicators listed in FAILURES.
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 --------------------------------------------------
(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.
(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)
(and decls (list (cons 'declare decls)))
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.
`((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 --------------------------------------------------