Details
-
New Feature
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
None
-
None
-
None
Description
Boilerplater is a small compiler which supports a vtable-based object model.
The output is C code which adheres to the design that Dave Balmain and I
hammered out a while back; the input is a collection of ".bp" header files.
Our original intent was to pepper traditional C ".h" header files with no-op
macros to define each class's interface; the code generator would understand
these macros but the C compiler would ignore them. C source code files would
then pound-include both the ".h" header and the auxiliary, generated ".bp"
file.
The problem with this approach is that C syntax is too constraining. Because
C does not support namespacing, every symbol has to be prepended with a prefix
to avoid conflicts. Futhermore, adding metadata to declarations (such as
default values for arguments, or whether NULL is an acceptable value) is
awkward. The result is ".h" header files that are excessively verbose,
cumbersome to edit, and challenging to parse visually and to grok.
The solution is to make the ".bp" file the master header file, and write it in
a small, purpose-built, declaration-only language. The
code-generator/compiler chews this ".bp" file and spits out a single ".h"
header file for pound-inclusion in ".c" source code files.
This isn't really that great a divergence from the original plan. There's no
fixed point at which a "code generator" becomes a "compiler", and while the
declaration-only header language has a few conventions that core developers
will have to familiarize themselves with, the same was true for the no-op
macro scheme. Furthermore, the Boilerplater compiler itself is merely an
implementation detail; it is not publicly exposed and thus can be modified at
will. Users who access Lucy via Perl, Ruby, Java, etc will never see it.
Even Lucy's C users will never see it, because the public C API itself will be
defined by a lightweight binding and generated documentation.
The important thing for us to focus on is the output code generated by
Boilerplater. We must nail the object model. It has to be fast. It has to
live happily as a symbiote within each host. It has to support callbacks into
the host language, so that users may define custom subclasses and override
methods easily. It has to present a robust ABI that makes it possible to
recompile an updated core without breaking compiled extensions (like Java,
unlike C++).
The present implementation of the Boilerplater compiler is a collection of
Perl modules: Boilerplater::Type, Boilerplater::Variable,
Boilerplater::Method, Boilerplater::Class, and so on. One CPAN module is
required, Parse::RecDescent; however, only core developers will need either
Perl or Parse::RecDescent, since public distributions of Lucy will
contain pre-generated code. Some of Boilerplater's modules have kludgy
internals, but on the whole they seem to do a good job of throwing errors rather
than failing subtly.
I expect to submit individual Boilerplater modules using JIRA sub-issues which
reference this one, to allow room for adequate commentary.