Mercurial > lcfOS
view python/libs/compiler/modules.py @ 71:5351594349b0
Moved error to core
author | windel |
---|---|
date | Fri, 02 Nov 2012 14:05:00 +0100 |
parents | 32078200cdd6 |
children |
line wrap: on
line source
import struct from .errors import Error from .nodes import * from .builtin import integer, real, char, boolean, void import os.path """ File format for compiled modules. * [11] magic identifier * [STR] mod name * [STR] signature, a md5 signature of the module. * [I32] size of code * code image * [I32] entrypoint for initcode * imported modules ** [I32] num of imported modules *** [STR] name of module *** signature of the module *** [I32] offset in the process image where the interface symbols must be placed * public interface ** [I32] num of interface elements *** [STR] proc name *** [I32] offset in code image *** [type] return type *** [I32] number of parameters **** parameter ***** parameter kind ***** parameter name ***** parameter type """ MAGIC = b'LCFOSMODC' loadedModules = [] def loadModule(modname): """ returns a Module object specified by a name """ # Check if the module was already loaded: for mod in loadedModules: if mod.name == modname: return mod # Try to load the module from file: srcfilename = modname + '.mod' binfilename = modname + '.bin' sourceExists = os.path.exists(srcfilename) if os.path.exists(binfilename): if sourceExists: compileModule() else: return loadModuleFromFile(binfilename) else: Error("Cannot load module '{0}'!".format(modname)) def loadModuleFromFile(filename): f = open(filename, 'rb') magic = f.read(len(MAGIC)) assert(magic == MAGIC) # Helper functions: def readI32(): int32, = struct.unpack('<I', f.read(4)) return int32 def readSTR(): length = readI32() b = f.read(length) return b.decode(encoding='ascii') def readType(): code, = f.read(1) basetypes = {0x11:integer, 0x12:real, 0x13:char,0x14:boolean, 0x15:void} if code in list(basetypes.keys()): return basetypes[code] elif code == 0x20: dimension, elementType = readI32(), readType() return ArrayType(dimension, elementType) elif code == 0x21: returntype = readType() numparams = readI32() parameters = [] kinds = {0x1:'value', 0x2:'var', 0x3:'const'} for i in range(numparams): byt, = f.read(1) kind = kinds[byt] name, typ = readSTR(), readType() parameters.append(Parameter(kind, name, typ)) return ProcedureType(parameters, returntype) else: Error('Reading of this typ not supported') # Begin of actual loading modname = readSTR() modsignature = readSTR() codesize = readI32() image = f.read(codesize) initcodeentry = readI32() # Check which modules this module loads: numimports = readI32() imports = [] for i in range(numimports): modname = readSTR() signature = readSTR() symname = readSTR() offset = readI32() impsym = ImportedSymbol(modname, symname) impsym.signature = signature impsym.offset = offset imports.append(impsym) # Modules exported interface: numexports = readI32() exports = [] for i in range(numexports): name = readSTR() imageoffset = readI32() # Offset in image where symbol is located typ = readType() export = ExportedSymbol(name, typ) export.imageoffset = imageoffset exports.append(export) f.close() # Construct imported module object: module = Module(modname) module.signature = modsignature module.exports = exports # Symbols provided to other modules module.imports = imports # Symbols of others used by this module. module.initcodeentry = initcodeentry module.image = image # The binary blob global loadedModules loadedModules.append(module) return module def storeModule(mod, filename): """ Class to store a module in a file """ f = open(filename, 'wb') def writeI32(int32): f.write( struct.pack('<I', int32) ) def writeSTR(s): writeI32(len(s)) f.write(bytes(s, encoding='ascii')) def writeType(typ): if type(typ) is BaseType: basetypecode = {'integer': 0x11, 'real': 0x12, 'char': 0x13, 'boolean':0x14, 'void':0x15} code = basetypecode[typ.name] f.write( bytes([code])) elif type(typ) is ArrayType: f.write(bytes([0x20])) writeI32(typ.dimension) writeType(typ.elementType) elif type(typ) is ProcedureType: f.write(bytes([0x21])) writeType(typ.returntype) writeI32(len(typ.parameters)) for parameter in typ.parameters: kinds = {'value': 0x1, 'var': 0x2, 'const': 0x3} kind = kinds[parameter.kind] f.write(bytes([kind])) writeSTR(parameter.name) writeType(parameter.typ) else: Error('Type storage not implemented {0}'.format(typ)) # Begin of actual storage function f.write(MAGIC) writeSTR(mod.name) writeSTR(mod.signature) writeI32(len(mod.image)) f.write(bytes(mod.image)) writeI32(mod.initcodeentry) # modules imported symbols: writeI32(len(mod.imports)) for imp in mod.imports: writeSTR(imp.modname) writeSTR(imp.signature) writeSTR(imp.name) writeI32(imp.offset) # modules provided interface writeI32(len(mod.exports)) # Store exported symbols: for sym in mod.exports: writeSTR(sym.name) # proc name writeI32(sym.imageoffset) # proc entry point writeType(sym.typ) # Procedure type f.close() storeModuleInCache(mod) def storeModuleInCache(newmod): global loadedModules for mod in loadedModules: if newmod.name == mod.name: return loadedModules.append(newmod)