But not motivation to code.
Since my last post, the following changes have been made to Affe:
- The AffeCompiler class has been split into two classes. AffeCompiler stores information about the configuration (host type and symbol table) and passes copies to AffeCompilerState for actual compilation. This allows the host class information to be cached when compiling repeatedly against the same class, and for changes to the symbol table to be retained.
- The parse tree is no longer immutable. It became apparent that to perform optimizations and other tweaks to the compiler output changing the tree is desired.
- Added type system. Expressions are automatically cast between required types. Methods and fields on the host class can now accept and return any type.
- Added support for string literals.
- Moved the tree classes into their own namespace.
- Transform methods have been improved. The AffeTransform attribute now takes a Type instead of an int. This type specifies the “return type” (actually the type of the object left on top of the stack). This allows for a primitive form of vararg methods, and the method can simply throw an exception if the count of expressions is incorrect.
- Refactored the DefineLocals tree of calls into an AnalyzeTree tree, which not only finds locals but adds casts where required and does some other nifty optimizations.
- All tree classes except Root now inherit from Node, which provides a property for accessing the node’s location in the input text.
- Added better error support. Exceptions now contain the Node causing the error. Combined with the Node’s property this allows the location of the error to be displayed.
- Added TypeSymbol, which maps an identifier to a Type.
- Added support for method, field, and property access, both for objects (instance invocation) and types (static invocation).
Type systems can be complex. jchambers summed it up pretty well:
12:33 < SerajewelKS> whew, writing compilers is easy until you decide to add support for types besides float
12:34 <@jchambers> until then I think you just have a calculator.
Look for the next post, where hopefully I’ll have typed variable declaration and a customizable default variable type. After that there are a few fringe cases I might address such as invoking members on value types, which require special treatment in IL.