def end_file(self): self.end_block() self.out() self.out() self.out('cdef extern from *:') with self.block(): for u in self.unions: for o in u.options: self.out('const %s *dynamic_cast_%s ' '"dynamic_cast<const %s::%s *>" (void *)' % (title(o), snake(o), namespace, title(o))) for u in self.unions: self.out() self.out() self.out('cdef inline object visit_%s(const Node *ptr):' % snake(u.name)) with self.block(): for o in u.options: self.visit_option(o) for t in self.types: self.out() self.out() self.out('cdef inline object visit_%s(const Node *ptr):' % snake(t.name)) with self.block(): self.out('cdef const Node *tmp') self.out('res = {}') for f in t.fields: self.visit_field(t.name, f) self.out('return res')
def end_file(self): for type in self._types: _map = {'snake': snake(type), 'name': type, 'cmodule': CMODULE_NAME} print ''' cdef int _visit_%(snake)s(%(cmodule)s.GraphQLAst%(name)s* node, void* userData, int end): cdef GraphQLAstVisitor visitor ast = GraphQLAst.GraphQLAst%(name)s.create(node) if userData is not NULL: visitor = <GraphQLAstVisitor>userData attname = 'end_visit_%(snake)s' if end else 'visit_%(snake)s' fun = getattr(visitor, attname, None) if fun is not None: retval = fun(ast) return 0 if retval is None else retval cdef int visit_%(snake)s(%(cmodule)s.GraphQLAst%(name)s* node, void* userData): return _visit_%(snake)s(node, userData, 0) cdef void end_visit_%(snake)s(%(cmodule)s.GraphQLAst%(name)s* node, void* userData): _visit_%(snake)s(node, userData, 1) ''' % _map print ''' cdef set_callbacks(%(cmodule)s.GraphQLAstVisitorCallbacks *callbacks): ''' % {'cmodule': CMODULE_NAME} for type in self._types: _map = {'snake': snake(type), 'name': type, 'cmodule': CMODULE_NAME} print ''' callbacks.visit_%(snake)s = &visit_%(snake)s callbacks.end_visit_%(snake)s = &end_visit_%(snake)s ''' % _map
def field_prototype(owning_type, type, name, nullable, plural): st_name = struct_name(owning_type) if plural: return 'int %s_get_%s_size(const struct %s *node)' % ( st_name, snake(name), st_name) else: ret_type = return_type(type) return '%s %s_get_%s(const struct %s *node)' % ( ret_type, st_name, snake(name), st_name)
def field_prototype(owning_type, type, name, nullable, plural): st_name = struct_name(owning_type) if plural: return 'int %s_get_%s_size(const %s *node)' % ( st_name, snake(name), st_name) else: ret_type = return_type(type) return '%s %s_get_%s(const %s *node)' % ( ret_type, st_name, snake(name), st_name)
def _print_ctor(self): fields = ( [field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]]) ctor_args = ', '.join(snake(name) + ('=None' if nullable else '') for (type, name, nullable, plural) in fields) print(''' def __init__(self, {ctor_args}, loc=None): self.loc = loc'''.format(ctor_args=ctor_args)) for type, name, nullable, plural in self._fields: print(''' self.{name} = {name}'''.format(name=snake(name)))
def _print_ctor(self): fields = [field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]] ctor_args = ", ".join(snake(name) + ("=None" if nullable else "") for (type, name, nullable, plural) in fields) print """ def __init__(self, {ctor_args}, loc=None): self.loc = loc""".format( ctor_args=ctor_args ) for type, name, nullable, plural in self._fields: print """ self.{name} = {name}""".format(name=snake(name))
def field(self, type, name, nullable, plural): owning_type = self._current_type # build the field accessor method print field_accessor(owning_type, type, name, nullable, plural) # associate the method with the class trailer = '_size' if plural else '' self._func_init_buffer += ' rb_define_method(%s_class, "%s%s", %s_get_%s%s, 0);\n' % ( snake(owning_type), snake(name), trailer, snake(owning_type), snake(name), trailer)
def _print_ctor(self): fields = ([field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]]) ctor_args = ', '.join( snake(name) + ('=None' if nullable else '') for (type, name, nullable, plural) in fields) print(''' def __init__(self, {ctor_args}, loc=None): self.loc = loc'''.format(ctor_args=ctor_args)) for type, name, nullable, plural in self._fields: print(''' self.{name} = {name}'''.format(name=snake(name)))
def start_type(self, name): self._types.append(name) _map = {'snake': snake(name), 'name': name} print ' struct %s:' % ast_cython_c.struct_name(name) print ' pass' print ' ctypedef int (*visit_%(snake)s_func)(GraphQLAst%(name)s*, void*)' % _map print ' ctypedef void (*end_visit_%(snake)s_func)(GraphQLAst%(name)s*, void*)' % _map
def start_type(self, name): self._types.append(name) _map = {"snake": snake(name), "name": name} print " struct %s:" % ast_cython_c.struct_name(name) print " pass" print " ctypedef int (*visit_%(snake)s_func)(GraphQLAst%(name)s*, void*)" % _map print " ctypedef void (*end_visit_%(snake)s_func)(GraphQLAst%(name)s*, void*)" % _map
def _print_ctor(self): fields = [field for field in self._fields if not field[2]] + [ field for field in self._fields if field[2] ] ctor_args = ", ".join( snake(name) + ("=None" if nullable else "") for (type, name, nullable, plural) in fields ) print( """ def __init__(self, {ctor_args}, loc=None): self.loc = loc""".format( ctor_args=ctor_args ) ) for type, name, nullable, plural in self._fields: print(""" self.{name} = {name}""".format(name=snake(name)))
def end_file(self): print ' struct GraphQLAstVisitorCallbacks:' for name in self._types: _map = {'snake': snake(name)} print ' visit_%(snake)s_func visit_%(snake)s' % _map print ' end_visit_%(snake)s_func end_visit_%(snake)s' % _map print '''
def end_file(self): print " struct GraphQLAstVisitorCallbacks:" for name in self._types: _map = {"snake": snake(name)} print " visit_%(snake)s_func visit_%(snake)s" % _map print " end_visit_%(snake)s_func end_visit_%(snake)s" % _map print """
def _print_repr(self, typename): print(''' def __repr__(self): return ('{typename}(' '''.rstrip().format(typename=typename)) first = True for type, name, nullable, plural in self._fields: print(" '{comma}{name}={{self.{name}!r}}'".format( comma=', ' if not first else '', name=snake(name))) first = False print(''' ')').format(self=self)''')
def _print_copy(self, typename): fields = ([field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]]) args = '\n'.join(''' self.{},'''.format(snake(name)) for (type, name, nullable, plural) in fields) print(''' def __copy__(self): return type(self)( {} self.loc )'''.format(args))
def _print_copy(self, typename): fields = ( [field for field in self._fields if not field[2]] + [field for field in self._fields if field[2]]) args = '\n'.join(''' self.{},'''.format(snake(name)) for (type, name, nullable, plural) in fields) print (''' def __copy__(self): return type(self)( {} self.loc )'''.format(args))
def _print_repr(self, typename): print(''' def __repr__(self): return ('{typename}(' '''.rstrip().format(typename=typename)) first = True for type, name, nullable, plural in self._fields: print(" '{comma}{name}={{self.{name}!r}}'".format( comma=', ' if not first else '', name=snake(name) )) first = False print(''' ')').format(self=self)''')
def field_accessor(owning_type, type, name, nullable, plural): preface = ' struct %s *node;\n' % struct_name(owning_type) preface += ' TypedData_Get_Struct(self, struct %s, &%s_type, node);\n' % ( struct_name(owning_type), snake(owning_type)) call_get = "%s_get_%s" % (struct_name(owning_type), snake(name)) func = '%s_get_%s' % (snake(owning_type), snake(name)) ret = ' return ' if plural: func += '_size' call_get += '_size(node)' ret += 'INT2FIX(%s)' % call_get else: call_get += '(node)' if nullable: preface += ' if (%s == NULL) return Qnil;\n' % call_get if type in ['string', 'OperationKind']: ret += 'rb_str_new_cstr(%s)' % call_get elif type in ['boolean']: ret += 'INT2BOOL(%s)' % call_get else: ret += 'TypedData_Wrap_Struct(%s_class, &%s_type, (void*)%s)' % ( snake(type), snake(type), call_get) return 'static VALUE ' + func + '(VALUE self) {\n' + preface + ret + ';\n}\n'
def _print_comparator(self, typename): print(''' def __eq__(self, other): return ( self is other or ( isinstance(other, {typename}) and self.loc == other.loc and'''.format(typename=typename)) print(' and\n'.join( ''' self.{name} == other.{name}'''.format( name=snake(name)) for type, name, nullable, plural in self._fields)) print(' )') print(' )')
def _print_comparator(self, typename): print """ def __eq__(self, other): return ( isinstance(other, {typename}) and self.loc == other.loc and""".format( typename=typename ) print " and\n".join( """ self.{name} == other.{name}""".format(name=snake(name)) for type, name, nullable, plural in self._fields ) print " )"
def _print_repr(self, typename): print """ def __repr__(self): return ('{typename}(' """.rstrip().format( typename=typename ) first = True for type, name, nullable, plural in self._fields: print " '{comma}{name}={{self.{name}!r}}'".format( comma=", " if not first else "", name=snake(name) ) first = False print """ ')').format(self=self)"""
def _print_comparator(self, typename): print(''' def __eq__(self, other): return ( self is other or ( isinstance(other, {typename}) and self.loc == other.loc and'''.format(typename=typename)) print(' and\n'.join( ''' self.{name} == other.{name}'''.format(name=snake(name)) for type, name, nullable, plural in self._fields )) print(' )') print(' )')
def start_type(self, name): self._current_type = name _map = {'snake': snake(name), 'name': name} print ''' cdef class %(name)s(GraphQLAst): @staticmethod cdef create(%(cmodule)s.%(name)s *thing): node = %(name)s() node._wrapped = thing return node ''' % {'name': ast_cython_c.struct_name(name), 'cmodule': ast_cython_c.CMODULE_NAME}
def start_type(self, name): self._current_type = name _map = {'snake': snake(name), 'name': name} print ''' cdef class %(name)s(GraphQLAst): @staticmethod cdef create(const %(cmodule)s.%(name)s *thing): node = %(name)s() node._wrapped = thing return node ''' % { 'name': ast_cython_c.struct_name(name), 'cmodule': ast_cython_c.CMODULE_NAME }
def _print_copy(self, typename): fields = [field for field in self._fields if not field[2]] + [ field for field in self._fields if field[2] ] args = "\n".join( """ self.{},""".format(snake(name)) for (type, name, nullable, plural) in fields ) print( """ def __copy__(self): return type(self)( {} self.loc )""".format( args ) )
def _print_comparator(self, typename): print( """ def __eq__(self, other): return ( self is other or ( isinstance(other, {typename}) and self.loc == other.loc and""".format( typename=typename ) ) print( " and\n".join( """ self.{name} == other.{name}""".format( name=snake(name) ) for type, name, nullable, plural in self._fields ) ) print(" )") print(" )")
def field_prototype(owning_type, type, name, nullable, plural): _map = { 'cmodule': ast_cython_c.CMODULE_NAME, 'owning_st': ast_cython_c.struct_name(owning_type), 'snake': snake(name), 'return_st': ast_cython_c.struct_name(type) } if plural: return ''' def get_%(snake)s_size(self): return int(%(cmodule)s.%(owning_st)s_get_%(snake)s_size(self._wrapped)) ''' % _map if type in SIMPLE_RETURN_CASTS: # TODO: convert string to unicode if owning_type in SOURCE_TYPE_CASTS: _map['cast'] = SOURCE_TYPE_CASTS[owning_type] else: _map['cast'] = SIMPLE_RETURN_CASTS[type] return ''' def get_%(snake)s(self): val = %(cmodule)s.%(owning_st)s_get_%(snake)s(self._wrapped) if val is None: return None return %(cast)s(val) ''' % _map elif type in ['Type', 'Value']: # XXX this types have no functions... return ''' ''' else: # python object return type return ''' def get_%(snake)s(self): cdef const %(cmodule)s.%(return_st)s *next next = %(cmodule)s.%(owning_st)s_get_%(snake)s(self._wrapped) if next is NULL: return None return %(return_st)s.create(next) ''' % _map
def field_prototype(owning_type, type, name, nullable, plural): _map = {'cmodule': ast_cython_c.CMODULE_NAME, 'owning_st': ast_cython_c.struct_name(owning_type), 'snake': snake(name), 'return_st': ast_cython_c.struct_name(type)} if plural: return ''' def get_%(snake)s_size(self): return int(%(cmodule)s.%(owning_st)s_get_%(snake)s_size(self._wrapped)) ''' % _map if type in SIMPLE_RETURN_CASTS: # TODO: convert string to unicode if owning_type in SOURCE_TYPE_CASTS: _map['cast'] = SOURCE_TYPE_CASTS[owning_type] else: _map['cast'] = SIMPLE_RETURN_CASTS[type] return ''' def get_%(snake)s(self): val = %(cmodule)s.%(owning_st)s_get_%(snake)s(self._wrapped) if val is None: return None return %(cast)s(val) ''' % _map elif type in ['Type', 'Value']: # XXX this types have no functions... return ''' ''' else: # python object return type return ''' def get_%(snake)s(self): cdef %(cmodule)s.%(return_st)s *next next = %(cmodule)s.%(owning_st)s_get_%(snake)s(self._wrapped) if next is NULL: return None return %(return_st)s.create(next) ''' % _map
def visit_field(self, ast_type, field): field_type, name, nullable, plural = field ref = '' if nullable else '&' if plural: vector = 'vector[unique_ptr[%s]] *' % title(field_type) self.out('cdef const %s%s = %s(<%s *>ptr).get%s()' % (vector, snake(name), ref, ast_type, title(name))) get = '%s[0].at(i).get()' % snake(name) size = '%s[0].size() if %s else 0' % (snake(name), snake(name)) self.out('res["%s"] = [visit_%s(%s) for i in xrange(%s)]' % (snake(name), snake(field_type), get, size)) else: mapped = type_map.get(field_type) get = '(<%s *>ptr)[0].get%s()' % (title(ast_type), title(name)) if mapped: assert(not nullable) decode = decode_map.get(field_type) if decode: self.out('res["%s"] = (<%s>%s).decode("%s")' % (snake(name), mapped, get, decode)) else: self.out('res["%s"] = <%s>%s' % (snake(name), mapped, get)) else: if nullable: self.out('tmp = %s' % get) self.out('res["%s"] = visit_%s(tmp) if tmp else None' % (snake(name), snake(field_type))) else: self.out('res["%s"] = visit_%s(&%s)' % (snake(name), snake(field_type), get))
def type_visitor_body(name): ret = ' VALUE parent = (VALUE)user_data;\n' ret += ' VALUE param = TypedData_Wrap_Struct(%s_class, &%s_type, (void*)%s);\n' % ( snake(name), snake(name), snake(name)) return ret
def _print_slots(self): slots = ', '.join("'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields) print(''' __slots__ = ('loc', {slots},)'''.format(slots=slots))
def type_end_visitor(name): prototype = 'static void end_visit_%s(const struct GraphQLAst%s *%s, void *user_data) {\n' % ( snake(name), name, snake(name)) ret = ' rb_funcall(parent, end_visit_%s_id, 1, param);\n' % (snake(name)) return prototype + type_visitor_body(name) + ret + '}\n'
def _print_fields(self): fields = ', '.join("'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields) print(''' _fields = ({},)'''.format(fields))
def end_file(self): print ' \\\n'.join('MACRO(%s, %s)' % (name, snake(name)) for name in self._types)
def type_visitor(name): prototype = 'static int visit_%s(const struct GraphQLAst%s *%s, void *user_data) {\n' % ( snake(name), name, snake(name)) ret = ' return rb_funcall(parent, visit_%s_id, 1, param) != skip_children;\n' % ( snake(name)) return prototype + type_visitor_body(name) + ret + '}\n'
def end_file(self): print(' \\\n'.join('MACRO(%s, %s)' % (name, snake(name)) for name in self._types))
def start_type(self, name): # define the values declared 'extern' in the header print 'const rb_data_type_t %s_type = { "%s", {}, };' % ( snake(name), struct_name(name)) print 'VALUE %s_class;' % snake(name) print 'ID visit_%s_id;' % snake(name) print 'ID end_visit_%s_id;' % snake(name) # build the two visitor methods print type_visitor(name) print type_end_visitor(name) # init the class self._class_init_buffer += ' %s_class = rb_define_class_under(module, "%s", node_class);\n' % ( snake(name), name) # init the symbols self._sym_init_buffer += ' visit_%s_id = rb_intern("visit_%s");\n' % ( snake(name), snake(name)) self._sym_init_buffer += ' end_visit_%s_id = rb_intern("end_visit_%s");\n' % ( snake(name), snake(name)) # init the visitor struct self._cbs_init_buffer += ' cbs.visit_%s = visit_%s;\n' % (snake(name), snake(name)) self._cbs_init_buffer += ' cbs.end_visit_%s = end_visit_%s;\n' % ( snake(name), snake(name)) self._current_type = name
def start_union(self, name): print 'const rb_data_type_t %s_type = { "%s", {}, };' % ( snake(name), struct_name(name)) print 'VALUE %s_class;' % snake(name)
def start_type(self, name): # define the values declared 'extern' in the header print 'const rb_data_type_t %s_type = { "%s", {}, };' % ( snake(name), struct_name(name)) print 'VALUE %s_class;' % snake(name) print 'ID visit_%s_id;' % snake(name) print 'ID end_visit_%s_id;' % snake(name) # build the two visitor methods print type_visitor(name) print type_end_visitor(name) # init the class self._class_init_buffer += ' %s_class = rb_define_class_under(module, "%s", node_class);\n' % ( snake(name), name) # init the symbols self._sym_init_buffer += ' visit_%s_id = rb_intern("visit_%s");\n' % ( snake(name), snake(name)) self._sym_init_buffer += ' end_visit_%s_id = rb_intern("end_visit_%s");\n' % ( snake(name), snake(name)) # init the visitor struct self._cbs_init_buffer += ' cbs.visit_%s = visit_%s;\n' % ( snake(name), snake(name)) self._cbs_init_buffer += ' cbs.end_visit_%s = end_visit_%s;\n' % ( snake(name), snake(name)) self._current_type = name
def start_type(self, name): print 'struct ' + struct_name(name) + ';' print 'extern const rb_data_type_t %s_type;' % snake(name) print 'extern VALUE %s_class;' % snake(name) print 'extern ID visit_%s_id;' % snake(name) print 'extern ID end_visit_%s_id;' % snake(name)
def start_union(self, name): print 'const rb_data_type_t %s_type = { "%s", {}, };' % (snake(name), struct_name(name)) print 'VALUE %s_class;' % snake(name)
def start_union(self, name): print 'struct ' + struct_name(name) + ';' print 'extern const rb_data_type_t %s_type;' % snake(name) print 'extern VALUE %s_class;' % snake(name)
def visit_option(self, option): option = snake(option) self.out('if dynamic_cast_%s(ptr):' % option) with self.block(): self.out('return visit_%s(ptr)' % option)
def type_end_visitor(name): prototype = 'static void end_visit_%s(const struct GraphQLAst%s *%s, void *user_data) {\n' % ( snake(name), name, snake(name)) ret = ' rb_funcall(parent, end_visit_%s_id, 1, param);\n' % ( snake(name)) return prototype + type_visitor_body(name) + ret + '}\n'
def _print_slots(self): slots = ", ".join("'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields) print """ __slots__ = ('loc', {slots})""".format(slots=slots)
def visit_field(self, ast_type, field): field_type, name, nullable, plural = field ref = '' if nullable else '&' if plural: vector = 'vector[unique_ptr[%s]] *' % title(field_type) self.out('cdef const %s%s = %s(<%s *>ptr).get%s()' % (vector, snake(name), ref, ast_type, title(name))) get = '%s[0].at(i).get()' % snake(name) size = '%s[0].size() if %s else 0' % (snake(name), snake(name)) self.out('res["%s"] = [visit_%s(%s) for i in xrange(%s)]' % (snake(name), snake(field_type), get, size)) else: mapped = type_map.get(field_type) get = '(<%s *>ptr)[0].get%s()' % (title(ast_type), title(name)) if mapped: assert (not nullable) decode = decode_map.get(field_type) if decode: self.out('res["%s"] = (<%s>%s).decode("%s")' % (snake(name), mapped, get, decode)) else: self.out('res["%s"] = <%s>%s' % (snake(name), mapped, get)) else: if nullable: self.out('tmp = %s' % get) self.out('res["%s"] = visit_%s(tmp) if tmp else None' % (snake(name), snake(field_type))) else: self.out('res["%s"] = visit_%s(&%s)' % (snake(name), snake(field_type), get))
def _print_fields(self): fields = ", ".join( "'" + snake(name) + "'" for (type, name, nullable, plural) in self._fields ) print(""" _fields = ({},)""".format(fields))