Skip to content

Commit

Permalink
feat(build): Also support python3
Browse files Browse the repository at this point in the history
  • Loading branch information
Aurélien 'Bubu' Busi committed Jul 10, 2018
1 parent 9d55a3c commit 6a3693f
Show file tree
Hide file tree
Showing 11 changed files with 717 additions and 4 deletions.
5 changes: 1 addition & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ INCLUDE(version)

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

FIND_PACKAGE(PythonInterp 2 REQUIRED)
IF (NOT PYTHON_VERSION_MAJOR EQUAL 2)
MESSAGE(FATAL_ERROR "Python 2 is required.")
ENDIF()
FIND_PACKAGE(PythonInterp 2)

FIND_PROGRAM(CTYPESGEN_FOUND ctypesgen.py)

Expand Down
7 changes: 7 additions & 0 deletions ast/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ def print_ast(lang_module, input_file):
if __name__ == '__main__':
import sys
lang = sys.argv[1]

try:
if sys.version_info >= (3,0):

This comment has been minimized.

Copy link
@haikaladnan

haikaladnan Jul 19, 2018

V(3.0):

lang = "%s_py3" % lang
except:

This comment has been minimized.

Copy link
@haikaladnan

haikaladnan Jul 19, 2018

+pass

pass

filename = sys.argv[2]

lang_module = load_lang(lang)
Expand Down
61 changes: 61 additions & 0 deletions ast/c_impl_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from c_py3 import field_prototype, return_type, struct_name
from casing import title
from license import C_LICENSE_COMMENT

class Printer(object):
'''Printer for the implementation of the pure C interface to the AST.
'''

def __init__(self):
self._current_type = None

def start_file(self):
print(C_LICENSE_COMMENT + '''/** @generated */
#include "GraphQLAst.h"
#include "../Ast.h"
using namespace facebook::graphql::ast; // NOLINT
''')

def end_file(self):
pass

def start_type(self, name):
self._current_type = name

def field(self, type, name, nullable, plural):
print(field_prototype(self._current_type, type, name, nullable, plural) + ' {')
print(' const auto *realNode = reinterpret_cast<const %s *>(node);' % self._current_type)
title_name = title(name)
call_get = 'realNode->get%s()' % title_name
if plural:
if nullable:
print(' return %s ? %s->size() : 0;' % (call_get, call_get))
else:
print(' return %s.size();' % call_get)
else:
if type in ['string', 'OperationKind', 'boolean']:
print(' return %s;' % call_get)
else:
fmt = ' return reinterpret_cast<const struct %s *>(%s%s);'
print(fmt % (struct_name(type), '' if nullable else '&', call_get))

print('}')

def end_type(self, name):
pass

def start_union(self, name):
pass

def union_option(self, option):
pass

def end_union(self, name):
pass
100 changes: 100 additions & 0 deletions ast/c_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# 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()
39 changes: 39 additions & 0 deletions ast/c_visitor_impl_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# 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

class Printer(object):

This comment has been minimized.

Copy link
@haikaladnan
'''Printer for a simple list of types to be visited by the C visitor.
'''

def __init__(self):
self._types = []

def start_file(self):
print(C_LICENSE_COMMENT + '/** @generated */')
print('#define FOR_EACH_CONCRETE_TYPE(MACRO) \\')

def start_type(self, name):
self._types.append(name)

def field(self, type, name, nullable, plural):
pass

def end_type(self, name):
pass

def end_file(self):
print(' \\\n'.join('MACRO(%s, %s)' % (name, snake(name)) for name in self._types))

def start_union(self, name):
pass

def union_option(self, option):
pass

def end_union(self, name):
pass
61 changes: 61 additions & 0 deletions ast/cxx_impl_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

from license import C_LICENSE_COMMENT

class Printer(object):
def __init__(self):
pass

def start_file(self):
print(C_LICENSE_COMMENT + '''/** @generated */
#include "Ast.h"
#include "AstVisitor.h"
namespace facebook {
namespace graphql {
namespace ast {
''')

def end_file(self):
print('} // namespace ast')
print('} // namespace graphql')
print('} // namespace facebook')

def start_type(self, name):
print('''void %s::accept(visitor::AstVisitor *visitor) const {
if (visitor->visit%s(*this)) {
''' % (name, name))

def field(self, type, name, nullable, plural):
if type in ['OperationKind', 'string', 'boolean']:
return

if plural:
accept = '{ for (const auto &x : *%s_) { x->accept(visitor); } }' % name
if nullable:
accept = 'if (%s_) %s' % (name, accept)
print(' ' + accept)
else:
accept = '%s_->accept(visitor);' % name
if nullable:
accept = 'if (%s_) { %s }' % (name, accept)
print(' ' + accept)

def end_type(self, name):
print(''' }
visitor->endVisit%s(*this);
}
''' % name)

def start_union(self, name):
pass

def union_option(self, option):
pass

def end_union(self, name):
pass
42 changes: 42 additions & 0 deletions ast/cxx_json_visitor_header_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# 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 title
from license import C_LICENSE_COMMENT

class Printer(object):
def __init__(self):
self._anyFieldIsANode = False

def start_file(self):
print(C_LICENSE_COMMENT + '/** @generated */')

def end_file(self):
pass

def start_type(self, name):
self._anyFieldIsANode = False

def end_type(self, name):
titleName = title(name)
if self._anyFieldIsANode:
print('bool visit%s(const %s &node) override;' % (titleName, titleName))
print('void endVisit%s(const %s &node) override;' % (titleName, titleName))
print()

def field(self, type, name, nullable, plural):
if (not self._anyFieldIsANode and
type not in ('OperationKind', 'string', 'boolean')):
self._anyFieldIsANode = True

def start_union(self, name):
pass

def union_option(self, option):
pass

def end_union(self, name):
pass
Loading

1 comment on commit 6a3693f

@haikaladnan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#66

Please sign in to comment.