After a long haul, and diversions into other more important projects — including starting a family — OWL BASIC today produced its first executable. Its not much. In fact its hardly anything. Just 2048 bytes of Windows PE executable containing the global variable declarations from Acornsoft’s 1982 Sphinx Adventure. Each file of BASIC source code will be converted to a single .NET static class, with the global variables as private static fields.
Above you can see the executable loaded up into .NET Reflector, which can be used to introspect the executable, and in this case attempt to disassemble it into C#. Now we see what makes .NET such a great platform for compiler construction; below is the IronPython source code for the embryonic assembly generation function. It clocks in at fewer than ten lines of code to create an assembly, create a module, create a class, add one private static field to it for each global variable, and save the result as an
def generateAssembly(name, global_symbols): domain = Thread.GetDomain() assembly_name = AssemblyName(name) assembly_builder = domain.DefineDynamicAssembly(assembly_name, AssemblyBuilderAccess.RunAndSave) module_builder = assembly_builder.DefineDynamicModule(name + ".exe") type_builder = module_builder.DefineType(name, TypeAttributes.Class | TypeAttributes.Public, object().GetType()) # Add global variables to the class for symbol in global_symbols.symbols.values(): field_builder = type_builder.DefineField(symbol.name, ctsType(symbol), FieldAttributes.Private | FieldAttributes.Static) result = type_builder.CreateType() assembly_builder.Save(name + ".exe")
global_symbols is the global symbol table constructed during traversal of the Abstract Syntax Tree and the Control Flow Graph and the
ctsType function maps OWL BASIC types to their equivalent Common Type System types for .NET. Everything else is provided by Reflection.Emit and other parts of .NET.
Its interesting that no validation was applied to the variable names supplied to
Reflection.Emit. As you can see, the variable names still include the sigil suffixes for variable typing (e.g. $ for string) and Reflector happily dissassembles these into invalid C# identifiers. For the final version these names will need to be mangled (Hungarian notation?), or merely de-sigiled if no conflicts result, for compatibility with other .NET languages and tools.