def resolve_type(library, repo, parser_module, tag): if '(' in tag: # has modifiers. mod, args = parse_tag(tag) if mod in ('pointer', 'reference'): # pointer and reference have the same handling return ctypes.POINTER(resolve_type(library, repo, parser_module, args[0])) elif mod == 'Func': return library.types.Closure # TODO: specialized funcs! else: raise SorryError('Unknown tag: %r' % tag) else: # just a name. module = library.get_module(parser_module.path) # search in current module if hasattr(module, tag): # yay! return getattr(module, tag) else: # nay. # types? Since lang/* modules are imported automatically anyway, # it's no problem to look through them before looking through # explicitly imported modules. Right? (TODO) # The other way round, it will cause problems because we'd have # `String` defined multiple times. TODO anyway. if hasattr(library.types, tag): return getattr(library.types, tag) # TODO: namespaced imports for import_path in parser_module.global_imports: if hasattr(library.get_module(import_path), tag): return getattr(library.get_module(import_path), tag) raise SorryError('Unknown type: %r' % tag)
def resolve_tag(self, tag, cb=lambda x:x): if '(' in tag: mod, args = parse_tag(tag) if mod == 'pointer': return self.resolve_tag(translate(args[0]), cb) + '*' elif mod == 'reference': return self.resolve_tag(translate(args[0]), cb) + '@' elif mod == 'multi': return '(' + ', '.join(self.resolve_tag(translate(arg), cb) for arg in args) + ')' elif mod == 'Func': return cb('Func') # TODO: specialized functions else: return 'dunno' else: return cb(tag)
def analyze_function(library, repo, parser_module, cls_entity, entity): # arguments. arguments = [] for arg in entity.arguments: if (arg.tag in entity.generic_types or (cls_entity and arg.tag in cls_entity.generic_types)): # generic. arguments.append(arg.tag) else: arguments.append(resolve_type(library, repo, parser_module, arg.tag)) # return type. if entity.return_type is None: return_type = None elif entity.return_type.startswith('multi('): # multi-return ... return_type = [] for rtype in parse_tag(entity.return_type)[1]: if (rtype in entity.generic_types or (cls_entity and rtype in cls_entity.generic_types)): return_type.append(rtype) else: return_type.append(resolve_type(library, repo, parser_module, rtype)) return_type = tuple(return_type) elif (entity.return_type in entity.generic_types or (cls_entity and entity.return_type in cls_entity.generic_types)): return_type = entity.return_type else: return_type = resolve_type(library, repo, parser_module, entity.return_type) # modifiers. # well, i think only `static` has any effect here. right? static = 'static' in entity.modifiers return { 'name': entity.name, 'arguments': arguments, 'generic_types': entity.generic_types, 'return_type': return_type, 'generic_return_type': isinstance(return_type, basestring), 'static': static, }