def test_unique(): m = NameManager() sn = m.seennames check = [ m.uniquename("something0"), m.uniquename("something", with_number=True), m.uniquename("something", with_number=True), m.uniquename("something2", with_number=True), m.uniquename("something1"), m.uniquename("something1_1"), ] assert check == ["something0", "something0_1", "something1", "something2_0", "something1_1", "something1_1_1"]
def test_unique(): m = NameManager() sn = m.seennames check = [ m.uniquename('something0'), m.uniquename('something', with_number=True), m.uniquename('something', with_number=True), m.uniquename('something2', with_number=True), m.uniquename('something1'), m.uniquename('something1_1'), ] assert check == ['something0', 'something0_1', 'something1', 'something2_0', 'something1_1', 'something1_1_1']
class GenSqueak: def __init__(self, sqdir, translator, modname=None): self.sqdir = sqdir self.translator = translator self.modname = (modname or translator.graphs[0].name) self.name_manager = NameManager(number_sep="") self.unique_name_mapping = {} self.pending_nodes = [] self.generated_nodes = set() self.constant_insts = {} def gen(self): graph = self.translator.graphs[0] self.pending_nodes.append(FunctionNode(self, graph)) self.filename = '%s.st' % graph.name file = self.sqdir.join(self.filename).open('w') self.gen_source(file) self.pending_nodes.append(SetupNode(self, self.constant_insts)) self.gen_source(file) file.close() return self.filename def gen_source(self, file): while self.pending_nodes: node = self.pending_nodes.pop() self.gen_node(node, file) def gen_node(self, node, f): for dep in node.dependencies(): if dep not in self.generated_nodes: self.pending_nodes.append(node) self.schedule_node(dep) return self.generated_nodes.add(node) for line in node.render(): print >> f, line print >> f, "" def schedule_node(self, node): if node not in self.generated_nodes: if node in self.pending_nodes: # We move the node to the front so we can enforce # the generation of dependencies. self.pending_nodes.remove(node) self.pending_nodes.append(node) def unique_func_name(self, funcgraph, schedule=True): function = funcgraph.func squeak_func_name = self.unique_name(function, function.__name__) if schedule: self.schedule_node(FunctionNode(self, funcgraph)) return squeak_func_name def unique_method_name(self, INSTANCE, method_name, schedule=True): # XXX it's actually more complicated than that because of # inheritance ... squeak_method_name = self.unique_name( (INSTANCE, method_name), method_name) if schedule: self.schedule_node(MethodNode(self, INSTANCE, method_name)) return squeak_method_name def unique_class_name(self, INSTANCE): class_node = self.schedule_node(ClassNode(self, INSTANCE)) if isinstance(INSTANCE, Record): # XXX quick hack class_name = "Record" else: class_name = INSTANCE._name.split(".")[-1] squeak_class_name = self.unique_name(INSTANCE, class_name) return "Py%s" % squeak_class_name def unique_field_name(self, INSTANCE, field_name, schedule=True): # XXX nameclashes with superclasses must be considered, too. while not INSTANCE._fields.has_key(field_name): # This is necessary to prevent a field from having different # unique names in different subclasses. INSTANCE = INSTANCE._superclass if schedule: # Generating getters and setters for all fields by default which # is potentially a waste, but easier for now. self.schedule_node(SetterNode(self, INSTANCE, field_name)) self.schedule_node(GetterNode(self, INSTANCE, field_name)) return self.unique_name( (INSTANCE, "field", field_name), field_name) def unique_var_name(self, variable): return self.unique_name(variable, variable.name) def unique_name(self, key, basename): # XXX should account for squeak keywords here if self.unique_name_mapping.has_key(key): unique = self.unique_name_mapping[key] else: camel_basename = camel_case(basename) unique = self.name_manager.uniquename(camel_basename) self.unique_name_mapping[key] = unique return unique
class SourceGenerator: one_source_file = True def __init__(self, database, preimplementationlines=[]): self.database = database self.preimpl = preimplementationlines self.extrafiles = [] self.path = None self.namespace = NameManager() def set_strategy(self, path, split=True): all_nodes = list(self.database.globalcontainers()) # split off non-function nodes. We don't try to optimize these, yet. funcnodes = [] othernodes = [] for node in all_nodes: if node.nodekind == 'func': funcnodes.append(node) else: othernodes.append(node) # for now, only split for stand-alone programs. #if self.database.standalone: if split: self.one_source_file = False self.funcnodes = funcnodes self.othernodes = othernodes self.path = path def uniquecname(self, name): assert name.endswith('.c') return self.namespace.uniquename(name[:-2]) + '.c' def makefile(self, name): log.writing(name) filepath = self.path.join(name) if name.endswith('.c'): self.extrafiles.append(filepath) return filepath.open('w') def getextrafiles(self): return self.extrafiles def getothernodes(self): return self.othernodes[:] def getbasecfilefornode(self, node, basecname): # For FuncNode instances, use the python source filename (relative to # the top directory): def invent_nice_name(g): # Lookup the filename from the function. # However, not all FunctionGraph objs actually have a "func": if hasattr(g, 'func'): if g.filename.endswith('.py'): localpath = py.path.local(g.filename) pypkgpath = localpath.pypkgpath() if pypkgpath: relpypath = localpath.relto(pypkgpath) return relpypath.replace('.py', '.c') return None if hasattr(node.obj, 'graph'): name = invent_nice_name(node.obj.graph) if name is not None: return name elif node._funccodegen_owner is not None: name = invent_nice_name(node._funccodegen_owner.graph) if name is not None: return "data_" + name return basecname def splitnodesimpl(self, basecname, nodes, nextra, nbetween, split_criteria=SPLIT_CRITERIA): # Gather nodes by some criteria: nodes_by_base_cfile = {} for node in nodes: c_filename = self.getbasecfilefornode(node, basecname) if c_filename in nodes_by_base_cfile: nodes_by_base_cfile[c_filename].append(node) else: nodes_by_base_cfile[c_filename] = [node] # produce a sequence of nodes, grouped into files # which have no more than SPLIT_CRITERIA lines for basecname in nodes_by_base_cfile: iternodes = iter(nodes_by_base_cfile[basecname]) done = [False] def subiter(): used = nextra for node in iternodes: impl = '\n'.join(list(node.implementation())).split('\n') if not impl: continue cost = len(impl) + nbetween yield node, impl del impl if used + cost > split_criteria: # split if criteria met, unless we would produce nothing. raise StopIteration used += cost done[0] = True while not done[0]: yield self.uniquecname(basecname), subiter() def gen_readable_parts_of_source(self, f): split_criteria_big = SPLIT_CRITERIA if py.std.sys.platform != "win32": if self.database.gcpolicy.need_no_typeptr(): pass # XXX gcc uses toooooons of memory??? else: split_criteria_big = SPLIT_CRITERIA * 4 if self.one_source_file: return gen_readable_parts_of_main_c_file(f, self.database, self.preimpl) # # All declarations # database = self.database structdeflist = database.getstructdeflist() name = 'structdef.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_structdef(fi, database) fi.close() name = 'forwarddecl.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_forwarddecl(fi, database) fi.close() # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' print >> f for line in self.preimpl: print >> f, line print >> f, '#include "src/g_include.h"' print >> f name = self.uniquecname('structimpl.c') print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Structure Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 11 + 1 for name, nodeiter in self.splitnodesimpl('nonfuncnodes.c', self.othernodes, nextralines, 1): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Non-function Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 8 + len(self.preimpl) + 4 + 1 for name, nodeiter in self.splitnodesimpl('implement.c', self.funcnodes, nextralines, 1, split_criteria_big): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#define PYPY_FILE_NAME "%s"' % name print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc for line in self.preimpl: print >> fc, line print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() print >> f
class SourceGenerator: one_source_file = True def __init__(self, database, preimplementationlines=[]): self.database = database self.preimpl = preimplementationlines self.extrafiles = [] self.path = None self.namespace = NameManager() def set_strategy(self, path): all_nodes = list(self.database.globalcontainers()) # split off non-function nodes. We don't try to optimize these, yet. funcnodes = [] othernodes = [] for node in all_nodes: if node.nodekind == 'func': funcnodes.append(node) else: othernodes.append(node) # for now, only split for stand-alone programs. if self.database.standalone: self.one_source_file = False self.funcnodes = funcnodes self.othernodes = othernodes self.path = path def uniquecname(self, name): assert name.endswith('.c') return self.namespace.uniquename(name[:-2]) + '.c' def makefile(self, name): log.writing(name) filepath = self.path.join(name) if name.endswith('.c'): self.extrafiles.append(filepath) return filepath.open('w') def getextrafiles(self): return self.extrafiles def getothernodes(self): return self.othernodes[:] def splitnodesimpl(self, basecname, nodes, nextra, nbetween, split_criteria=SPLIT_CRITERIA): # produce a sequence of nodes, grouped into files # which have no more than SPLIT_CRITERIA lines iternodes = iter(nodes) done = [False] def subiter(): used = nextra for node in iternodes: impl = '\n'.join(list(node.implementation())).split('\n') if not impl: continue cost = len(impl) + nbetween yield node, impl del impl if used + cost > split_criteria: # split if criteria met, unless we would produce nothing. raise StopIteration used += cost done[0] = True while not done[0]: yield self.uniquecname(basecname), subiter() def gen_readable_parts_of_source(self, f): if py.std.sys.platform != "win32": split_criteria_big = SPLIT_CRITERIA * 4 else: split_criteria_big = SPLIT_CRITERIA if self.one_source_file: return gen_readable_parts_of_main_c_file(f, self.database, self.preimpl) # # All declarations # database = self.database structdeflist = database.getstructdeflist() name = 'structdef.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_structdef(fi, database) fi.close() name = 'forwarddecl.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_forwarddecl(fi, database) fi.close() # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' print >> f for line in self.preimpl: print >> f, line print >> f, '#include "src/g_include.h"' print >> f name = self.uniquecname('structimpl.c') print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Structure Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 11 + 1 for name, nodeiter in self.splitnodesimpl('nonfuncnodes.c', self.othernodes, nextralines, 1): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Non-function Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 8 + len(self.preimpl) + 4 + 1 for name, nodeiter in self.splitnodesimpl('implement.c', self.funcnodes, nextralines, 1, split_criteria_big): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc for line in self.preimpl: print >> fc, line print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() print >> f
class SourceGenerator: one_source_file = True def __init__(self, database, preimplementationlines=[]): self.database = database self.preimpl = preimplementationlines self.extrafiles = [] self.path = None self.namespace = NameManager() def set_strategy(self, path, split=True): all_nodes = list(self.database.globalcontainers()) # split off non-function nodes. We don't try to optimize these, yet. funcnodes = [] othernodes = [] for node in all_nodes: if node.nodekind == 'func': funcnodes.append(node) else: othernodes.append(node) # for now, only split for stand-alone programs. #if self.database.standalone: if split: self.one_source_file = False self.funcnodes = funcnodes self.othernodes = othernodes self.path = path def uniquecname(self, name): assert name.endswith('.c') return self.namespace.uniquename(name[:-2]) + '.c' def makefile(self, name): log.writing(name) filepath = self.path.join(name) if name.endswith('.c'): self.extrafiles.append(filepath) return filepath.open('w') def getextrafiles(self): return self.extrafiles def getothernodes(self): return self.othernodes[:] def splitnodesimpl(self, basecname, nodes, nextra, nbetween, split_criteria=SPLIT_CRITERIA): # produce a sequence of nodes, grouped into files # which have no more than SPLIT_CRITERIA lines iternodes = iter(nodes) done = [False] def subiter(): used = nextra for node in iternodes: impl = '\n'.join(list(node.implementation())).split('\n') if not impl: continue cost = len(impl) + nbetween yield node, impl del impl if used + cost > split_criteria: # split if criteria met, unless we would produce nothing. raise StopIteration used += cost done[0] = True while not done[0]: yield self.uniquecname(basecname), subiter() def gen_readable_parts_of_source(self, f): split_criteria_big = SPLIT_CRITERIA if py.std.sys.platform != "win32": if self.database.gcpolicy.need_no_typeptr(): pass # XXX gcc uses toooooons of memory??? else: split_criteria_big = SPLIT_CRITERIA * 4 if self.one_source_file: return gen_readable_parts_of_main_c_file(f, self.database, self.preimpl) # # All declarations # database = self.database structdeflist = database.getstructdeflist() name = 'structdef.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_structdef(fi, database) fi.close() name = 'forwarddecl.h' fi = self.makefile(name) print >> f, '#include "%s"' % name gen_forwarddecl(fi, database) fi.close() # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' print >> f for line in self.preimpl: print >> f, line print >> f, '#include "src/g_include.h"' print >> f name = self.uniquecname('structimpl.c') print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Structure Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 11 + 1 for name, nodeiter in self.splitnodesimpl('nonfuncnodes.c', self.othernodes, nextralines, 1): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Non-function Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() nextralines = 8 + len(self.preimpl) + 4 + 1 for name, nodeiter in self.splitnodesimpl('implement.c', self.funcnodes, nextralines, 1, split_criteria_big): print >> f, '/* %s */' % name fc = self.makefile(name) print >> fc, '/***********************************************************/' print >> fc, '/*** Implementations ***/' print >> fc print >> fc, '#define PYPY_NOT_MAIN_FILE' print >> fc, '#define PYPY_FILE_NAME "%s"' % name print >> fc, '#include "common_header.h"' print >> fc, '#include "structdef.h"' print >> fc, '#include "forwarddecl.h"' print >> fc for line in self.preimpl: print >> fc, line print >> fc print >> fc, '#include "src/g_include.h"' print >> fc print >> fc, MARKER for node, impl in nodeiter: print >> fc, '\n'.join(impl) print >> fc, MARKER print >> fc, '/***********************************************************/' fc.close() print >> f