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