# Copyright 2019-present, GraphQL Foundation # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. from casing import snake from license import C_LICENSE_COMMENT def struct_name(type): return 'GraphQLAst' + type def return_type(type): if type == 'OperationKind' or type == 'string': return 'const char *' if type == 'boolean': return 'int' return 'const struct %s *' % struct_name(type) 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) class Printer(object): '''Printer for the pure C interface to the AST. Merely a set of wrappers around the C++ interface; makes it possible to use the AST from C code and simplifies the task of writing bindings for other langugages. The mapping is as follows: - For each concrete type, you get an opaque C struct type, accessible only by pointer. - For each singular field of a concrete type, you get an accessor function, returning said field in the obvious way. - For each plural field of a concrete type, you get an accessor function telling you its size. For access to elements of a plural field, you can use the visitor API. - For each union type, you get nothing specific (REVIEW), but you can use the visitor API to work around this entirely. ''' def __init__(self): self._current_type = None def start_file(self): print(C_LICENSE_COMMENT + '''/** @generated */ #pragma once #ifdef __cplusplus extern "C" { #endif ''') def end_file(self): print(''' #ifdef __cplusplus } #endif ''') def start_type(self, name): # Forward declarations for AST nodes. st_name = struct_name(name) print('struct ' + st_name + ';') self._current_type = name def field(self, type, name, nullable, plural): print(field_prototype(self._current_type, type, name, nullable, plural) + ';') def end_type(self, name): print() def start_union(self, name): print('struct ' + struct_name(name) + ';') def union_option(self, option): pass def end_union(self, name): print