1[This is the README from an early prototype of the gen-nodes tool.  It
2 is quite out of date with regard to the details, but the general
3 ideas still apply.]
4
5This is a demonstration of my ideas about an extensible framework for
6representing an abstract syntax tree (actually a graph).
7
8The goal is to be able to specify a hierachy of node types and define
9`generic' functions on them.  A generic function can have different
10implementations for different types.  These implementations are called
11the methods of a generic function.  The decision which method to
12invoke when a generic functions is called is made at run-time.
13
14We want to be able to define new generic functions without changing
15the definition of the types that they work on.  Therefore, we can not
16use the virtual functions of C++.  A virtual function is part of the
17type it works on and it is therefore necessary to change the type
18itself when adding new virtual functions.  This means frequent and
19inconvenient recompilation.
20
21Furthermore, such changes to the type definitions have to be carefully
22coordinated when more than one party wants to make some.
23
24
25My proposed solution to this dilemma is to design a new, minimal OOP
26model and implement it in C++.  To make it useable, we need a tool
27that generates most of the boilerplate code for us.
28
29The demonstration uses Scheme (a Lisp dialect) for implementing the
30boilerplate generating tool and Scheme syntax for specifying the input
31to it.  I know that this is not the most popular thing to do, but it
32was easiest for me.  Therefore...
33
34*   You need to have Guile installed to play with the tool.  Version  *
35*   1.2 should work fine.  You can find it on your local GNU mirror.  *
36
37
38- How it works
39
40The node features are defined in `chunks'.  Each chunk can contain new
41node type definitions and generic functions with their methods.  You
42can also extend node types with new attributes.
43
44The chunks are independent from one-another.  That is, you can mix and
45match chunks at link time without having to recompile them.
46
47The cornerstone of the system is `gen-nodes'.  This is the tool that
48reads the description of a number of chunks and outputs C++ code for
49their implementation.
50
51- The chunk descriptions.
52
53The files that gen-nodes reads contain the description of the chunks
54in Scheme syntax.
55
56A chunk is started with this statement:
57
58    (chunk NAME OPTS..)
59
60it ends at the end of input or when the next chunk begins.  NAME
61should be a valid C++ identifier and unique among all chunks.
62
63You can define new node types:
64
65    (defnode NAME (BASE)
66       SLOTS...
67       OPTS...)
68
69The NAME is the name of the node type and should be a valid and unique
70C++ identifier.  BASE is the name of a previously defined node type
71that will be used as the base for the new type.  You can omit BASE
72(but not the parentheses around it).
73
74LINKS-AND-ATTRS can specify links to other nodes
75
76    (link NODE LINK-NAME)
77
78where NODE is the type of the node that is pointed to by the link
79named LINK-NAME.  The generated C++ struct will have a member that is
80a pointer to a struct generated for NODE.
81
82You can also specify attributes
83
84    (attr TYPE ATTR-NAME)
85
86where TYPE is string enclosed in double quotes that is a valid C++
87type, such as "char*" or "int".  The generated C++ struct will have a
88member with name ATTR-NAME and type TYPE.
89
90
91Generic functions are specified with
92
93    (defgeneric RET-TYPE GENERIC-NAME EXTRA-ARGS)
94
95This will generate a C++ function named GENERIC-NAME with return type
96RET-TYPE (which should be a string just like a attribute type).  The
97first argument of this function is a pointer to a node struct.  The
98run-time type of this node is used to dispatch to one of the methods
99of this generic function, see below.  The rest of the arguments of the
100function are specified by EXTRA-ARGS.  This should be a list like
101
102    ((TYPE ARG-NAME) (TYPE ARG-NAME) ...)
103
104When the generic function should not be global but be contained in a
105class, you specify the qualified name of it (i.e. including the class
106name) as a list of symbols.  The qualified name
107"outer_class::inner_class::func" would be written as
108
109    (outer_class inner_class func)
110
111Methods are defined with
112
113    (defmethods GENERIC-NAME NODES...)
114
115For each of the node types listed in NODES, an individual method is
116defined.  Methods are translated into ordinary C++ functions whose
117name is formed by concatenating the string "m_" and the GENERIC-NAME.
118Their first parameter is a pointer to the node type they belong to and
119the rest is specified by the EXTRA-ARGS of the generic declaration.
120
121When a generic function is invoked on a node type that has no method
122defined for it, the method for the nearest base type that has a method
123is invoked.  When no such base type exists, the program is aborted.
124
125
126You can extend existing nodes with
127
128    (extnode NODE
129       ATTRS...)
130
131NODE is the name of the node that you want to extend and ATTRS is a
132list of attribute definitions, just like for defnode.  For every
133specified attribute a function will be generated according to this
134template:
135
136    TYPE& NAME (NODE*);
137
138TYPE is the type of the attribute, NAME is the name of the attribute
139and NODE is the struct generated for the extended node.  The function
140will return a reference to the storage reserved for the attribute.
141
142
143You can add arbitary lines to the generated output with
144
145    (header-add LINES...)
146
147and
148
149    (impl-add LINES)
150
151You can split the chunk definitions into several files and use
152
153    (include FILE)
154
155to include them.
156
157
158- Invoking gen-nodes
159
160    gen-nodes CMD CHUNK IN-FILE OUT-FILE
161
162Gen-nodes reads the IN-FILE (which should contain the descriptions in
163the format explained above) and generates output for CHUNK in
164OUT-FILE, according to CMD.
165
166When CMD is `header', gen-nodes writes a header file to OUT-FILE that
167should be included by the users of the CHUNK.  When it is `impl', it
168writes the implementation of CHUNK.
169