Major refactoring
This commit is contained in:
parent
a3da74c416
commit
eba88b32ba
22 changed files with 999 additions and 924 deletions
|
|
@ -1,17 +1,12 @@
|
||||||
PYTHON = python
|
PYTHON = python
|
||||||
|
|
||||||
PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef
|
|
||||||
|
|
||||||
PYMODS += LLVMContext AssemblyAnnotationWriter Module
|
|
||||||
PYMODS += Value User Constant
|
|
||||||
|
|
||||||
all: _api.so _capsule.so
|
all: _api.so _capsule.so
|
||||||
|
|
||||||
_api.so _capsule.so: api.cpp capsule.cpp
|
_api.so _capsule.so: api.cpp capsule.cpp
|
||||||
$(PYTHON) setup.py build_ext --inplace
|
$(PYTHON) setup.py build_ext --inplace
|
||||||
|
|
||||||
api.cpp api.py: src/*.py include/llvm_binding/*.h
|
api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py
|
||||||
$(PYTHON) gen.py api src $(PYMODS)
|
$(PYTHON) gen.py api src
|
||||||
|
|
||||||
clean: cleantemp
|
clean: cleantemp
|
||||||
rm -f _api.so _capsule.so
|
rm -f _api.so _capsule.so
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,352 @@
|
||||||
import logging
|
import functools
|
||||||
import re
|
import codegen as cg
|
||||||
from utils import *
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
_rank = 0
|
||||||
|
namespaces = {}
|
||||||
|
|
||||||
_py2capi_fmtmap = {
|
class Namespace(object):
|
||||||
str: 's#',
|
def __init__(self, name):
|
||||||
}
|
self.name = name
|
||||||
|
self.classes = []
|
||||||
|
self.functions = []
|
||||||
|
namespaces[name] = self
|
||||||
|
|
||||||
NULL = 'NULL'
|
def Class(self, *bases):
|
||||||
|
cls = Class(self, *bases)
|
||||||
|
self.classes.append(cls)
|
||||||
|
return cls
|
||||||
|
|
||||||
_symbols = set()
|
def Function(self, *args):
|
||||||
|
fn = Function(self, *args)
|
||||||
|
self.functions.append(fn)
|
||||||
|
return fn
|
||||||
|
|
||||||
def new_symbol(name):
|
@property
|
||||||
if name in _symbols:
|
def fullname(self):
|
||||||
ct = 1
|
return self.name
|
||||||
orig = name
|
|
||||||
while name in _symbols:
|
|
||||||
name = '%s%d' % (orig, ct)
|
|
||||||
ct += 1
|
|
||||||
_symbols.add(name)
|
|
||||||
return name
|
|
||||||
|
|
||||||
def parse_arguments(println, var, *args):
|
def __str__(self):
|
||||||
typecodes = []
|
return self.name
|
||||||
holders = []
|
|
||||||
argvals = []
|
|
||||||
for arg in args:
|
|
||||||
typecodes.append(arg.format)
|
|
||||||
val = declare(println, 'PyObject*')
|
|
||||||
argvals.append(val)
|
|
||||||
holders.append('&' + val)
|
|
||||||
|
|
||||||
items = [var, '"%s"' % (''.join(typecodes))] + holders
|
class Type(object):
|
||||||
println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items))
|
pass
|
||||||
|
|
||||||
# unwrap
|
class BuiltinTypes(Type):
|
||||||
unwrapped = []
|
def __init__(self, name):
|
||||||
for arg, val in zip(args, argvals):
|
self.name = name
|
||||||
unwrapped.append(arg.unwrap(println, val))
|
|
||||||
|
|
||||||
return unwrapped
|
@property
|
||||||
|
def fullname(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
_re_mangle_pattern = re.compile(r'[ _<>\*&]')
|
def wrap(self, writer, var):
|
||||||
|
return var
|
||||||
|
|
||||||
def mangle(name):
|
Void = BuiltinTypes('void')
|
||||||
def repl(m):
|
Unsigned = BuiltinTypes('unsigned')
|
||||||
s = m.group(0)
|
Bool = BuiltinTypes('bool')
|
||||||
if s in '<>*&':
|
ConstStdString = BuiltinTypes('const std::string')
|
||||||
return ''
|
|
||||||
elif s in ' ':
|
class Class(Type):
|
||||||
return '_'
|
format = 'O'
|
||||||
elif s in '_':
|
|
||||||
return '__'
|
def __init__(self, ns, *bases):
|
||||||
|
self.ns = ns
|
||||||
|
self.bases = bases
|
||||||
|
self._is_defined = False
|
||||||
|
self.methods = []
|
||||||
|
self.enums = []
|
||||||
|
self.includes = set()
|
||||||
|
|
||||||
|
def __call__(self, defn):
|
||||||
|
assert not self._is_defined
|
||||||
|
self.name = defn.__name__
|
||||||
|
for k, v in defn.__dict__.items():
|
||||||
|
if isinstance(v, Method):
|
||||||
|
self.methods.append(v)
|
||||||
|
if isinstance(v, Constructor):
|
||||||
|
for sig in v.signatures:
|
||||||
|
sig[0] = ptr(self)
|
||||||
|
v.name = k
|
||||||
|
v.parent = self
|
||||||
|
elif isinstance(v, Enum):
|
||||||
|
self.enums.append(v)
|
||||||
|
v.name = k
|
||||||
|
v.parent = self
|
||||||
|
elif k == '_include_':
|
||||||
|
if isinstance(v, str):
|
||||||
|
self.includes.add(v)
|
||||||
|
else:
|
||||||
|
for i in v:
|
||||||
|
self.includes.add(i)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def compile_cpp(self, writer):
|
||||||
|
# generate methods
|
||||||
|
for meth in self.methods:
|
||||||
|
meth.compile_cpp(writer)
|
||||||
|
|
||||||
|
# generate method table
|
||||||
|
writer.println('static')
|
||||||
|
writer.println('PyMethodDef %s[] = {' % cg.mangle(self.fullname))
|
||||||
|
with writer.indent():
|
||||||
|
fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },'
|
||||||
|
for meth in self.methods:
|
||||||
|
name = meth.name
|
||||||
|
func = cg.mangle(meth.fullname)
|
||||||
|
writer.println(fmt % locals())
|
||||||
|
writer.println('{ NULL },')
|
||||||
|
writer.println('};')
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
def compile_py(self, writer):
|
||||||
|
clsname = self.name
|
||||||
|
bases = 'capsule.Wrapper'
|
||||||
|
if self.bases:
|
||||||
|
bases = ', '.join(x.name for x in self.bases)
|
||||||
|
writer.println('@capsule.register_class')
|
||||||
|
with writer.block('class %(clsname)s(%(bases)s):' % locals()):
|
||||||
|
for enum in self.enums:
|
||||||
|
enum.compile_py(writer)
|
||||||
|
for meth in self.methods:
|
||||||
|
meth.compile_py(writer)
|
||||||
|
if not self.enums and not self.methods:
|
||||||
|
writer.println('pass')
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def capsule_name(self):
|
||||||
|
if self.bases:
|
||||||
|
return self.bases[-1].capsule_name
|
||||||
else:
|
else:
|
||||||
assert False
|
return self.fullname
|
||||||
name = _re_mangle_pattern.sub(repl, name)
|
|
||||||
return name.replace('::', '_')
|
|
||||||
|
|
||||||
def pycapsule_new(println, ptr, name, clsname):
|
@property
|
||||||
# build capsule
|
def fullname(self):
|
||||||
name_soften = mangle(name)
|
try:
|
||||||
var = new_symbol('pycap_%s' % name_soften)
|
name = self.realname
|
||||||
fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");'
|
except AttributeError:
|
||||||
println(fmt % locals())
|
name = self.name
|
||||||
println('if (!%(var)s) return NULL;' % locals())
|
return '::'.join([self.ns.fullname, name])
|
||||||
return var
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.fullname
|
||||||
|
|
||||||
|
def unwrap(self, writer, val):
|
||||||
|
fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")'
|
||||||
|
name = self.capsule_name
|
||||||
|
raw = writer.declare('void*', fmt % locals())
|
||||||
|
writer.die_if_false(raw)
|
||||||
|
ptrty = ptr(self).fullname
|
||||||
|
ty = self.fullname
|
||||||
|
fmt = 'typecast<%(ty)s>::from(%(raw)s)'
|
||||||
|
casted = writer.declare(ptrty, fmt % locals())
|
||||||
|
writer.die_if_false(casted)
|
||||||
|
return casted
|
||||||
|
|
||||||
|
|
||||||
def declare(println, typ, init=None):
|
class Enum(object):
|
||||||
typ_soften = mangle(typ)
|
def __init__(self, *value_names):
|
||||||
var = new_symbol('var_%s' % typ_soften)
|
self.parent = None
|
||||||
if init is None:
|
self.value_names = value_names
|
||||||
println('%(typ)s %(var)s;' % locals())
|
|
||||||
else:
|
@property
|
||||||
println('%(typ)s %(var)s = %(init)s;' % locals())
|
def fullname(self):
|
||||||
return var
|
try:
|
||||||
|
name = self.realname
|
||||||
|
except AttributeError:
|
||||||
|
name = self.name
|
||||||
|
return '::'.join([self.parent.fullname, name])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.fullname
|
||||||
|
|
||||||
|
def wrap(self, writer, val):
|
||||||
|
ret = writer.declare('PyObject*', 'NULL')
|
||||||
|
with writer.block('switch(%s) ' % val):
|
||||||
|
for v in self.value_names:
|
||||||
|
writer.println('case %s::%s:' % (self.parent, v))
|
||||||
|
with writer.indent():
|
||||||
|
fmt = '%(ret)s = PyString_FromString("%(v)s");'
|
||||||
|
writer.println(fmt % locals())
|
||||||
|
writer.println('break;')
|
||||||
|
else:
|
||||||
|
writer.println('default:')
|
||||||
|
with writer.indent():
|
||||||
|
writer.raises(ValueError, 'Invalid enum %s' % v)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def compile_py(self, writer):
|
||||||
|
with writer.block('class %s:' % self.name):
|
||||||
|
for v in self.value_names:
|
||||||
|
writer.println('%(v)s = "%(v)s"' % locals())
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
class Method(object):
|
||||||
|
_kind_ = 'meth'
|
||||||
|
|
||||||
|
def __init__(self, return_type=Void, *args):
|
||||||
|
self.parent = None
|
||||||
|
self.signatures = []
|
||||||
|
self.includes = set()
|
||||||
|
self._add_signature(return_type, *args)
|
||||||
|
|
||||||
|
def _add_signature(self, return_type, *args):
|
||||||
|
prev_lens = set(map(len, self.signatures))
|
||||||
|
cur_len = len(args) + 1
|
||||||
|
if cur_len in prev_lens:
|
||||||
|
raise Exception('Only support overloading with different number'
|
||||||
|
' of arguments')
|
||||||
|
self.signatures.append([return_type] + list(args))
|
||||||
|
|
||||||
|
def __ior__(self, method):
|
||||||
|
assert type(self) is type(method)
|
||||||
|
for sig in method.signatures:
|
||||||
|
self._add_signature(sig[0], *sig[1:])
|
||||||
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fullname(self):
|
||||||
|
return '::'.join([self.parent.fullname, self.realname])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def realname(self):
|
||||||
|
try:
|
||||||
|
return self.__realname
|
||||||
|
except AttributeError:
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
@realname.setter
|
||||||
|
def realname(self, v):
|
||||||
|
self.__realname = v
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.fullname
|
||||||
|
|
||||||
|
def compile_cpp(self, writer):
|
||||||
|
with writer.py_function(self.fullname):
|
||||||
|
if len(self.signatures) == 1:
|
||||||
|
sig = self.signatures[0]
|
||||||
|
retty = sig[0]
|
||||||
|
argtys = sig[1:]
|
||||||
|
self.compile_cpp_body(writer, retty, argtys)
|
||||||
|
else:
|
||||||
|
nargs = writer.declare('Py_ssize_t', 'PyTuple_Size(args)')
|
||||||
|
for sig in self.signatures:
|
||||||
|
retty = sig[0]
|
||||||
|
argtys = sig[1:]
|
||||||
|
expect = len(argtys)
|
||||||
|
if (not isinstance(self, StaticMethod) and
|
||||||
|
isinstance(self.parent, Class)):
|
||||||
|
# Is a instance method, add 1 for "this".
|
||||||
|
expect += 1
|
||||||
|
with writer.block('if (%(expect)d == %(nargs)s)' % locals()):
|
||||||
|
self.compile_cpp_body(writer, retty, argtys)
|
||||||
|
writer.raises(TypeError, 'Invalid number of args')
|
||||||
|
|
||||||
|
def compile_cpp_body(self, writer, retty, argtys):
|
||||||
|
if isinstance(self.parent, Class):
|
||||||
|
args = writer.parse_arguments('args', ptr(self.parent), *argtys)
|
||||||
|
ret = writer.method_call(self.realname, retty.fullname, *args)
|
||||||
|
else:
|
||||||
|
args = writer.parse_arguments('args', *argtys)
|
||||||
|
ret = writer.call(self.fullname, retty.fullname, *args)
|
||||||
|
writer.return_value(retty.wrap(writer, ret))
|
||||||
|
|
||||||
|
def compile_py(self, writer):
|
||||||
|
decl = writer.function(self.name, args=('self',), varargs='args')
|
||||||
|
with decl as (this, varargs):
|
||||||
|
unwrap_this = writer.unwrap(this)
|
||||||
|
unwrapped = writer.unwrap_many(varargs)
|
||||||
|
func = '.'.join([self.parent.name, self.name])
|
||||||
|
ret = writer.call('_api.%s' % func,
|
||||||
|
args=(unwrap_this,), varargs=unwrapped)
|
||||||
|
wrapped = writer.wrap(ret)
|
||||||
|
writer.return_value(wrapped)
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
|
||||||
def return_value(println, var):
|
class StaticMethod(Method):
|
||||||
println('return %(var)s;' % locals())
|
|
||||||
|
def compile_cpp_body(self, writer, retty, argtys):
|
||||||
|
assert isinstance(self.parent, Class)
|
||||||
|
args = writer.parse_arguments('args', *argtys)
|
||||||
|
ret = self.compile_cpp_call(writer, retty, args)
|
||||||
|
writer.return_value(retty.wrap(writer, ret))
|
||||||
|
|
||||||
|
def compile_cpp_call(self, writer, retty, args):
|
||||||
|
ret = writer.call(self.fullname, retty.fullname, *args)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def compile_py(self, writer):
|
||||||
|
writer.println('@staticmethod')
|
||||||
|
decl = writer.function(self.name, varargs='args')
|
||||||
|
with decl as varargs:
|
||||||
|
unwrapped = writer.unwrap_many(varargs)
|
||||||
|
func = '.'.join([self.parent.name, self.name])
|
||||||
|
ret = writer.call('_api.%s' % func, varargs=unwrapped)
|
||||||
|
wrapped = writer.wrap(ret)
|
||||||
|
writer.return_value(wrapped)
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
|
||||||
def return_none(println):
|
class Function(Method):
|
||||||
println('Py_RETURN_NONE;')
|
_kind_ = 'func'
|
||||||
|
|
||||||
|
def __init__(self, parent, name, return_type=Void, *args):
|
||||||
|
super(Function, self).__init__(return_type, *args)
|
||||||
|
self.parent = parent
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def compile_py(self, writer):
|
||||||
|
with writer.function(self.name, varargs='args') as varargs:
|
||||||
|
unwrapped = writer.unwrap_many(varargs)
|
||||||
|
func = self.fullname.split('::', 1)[1].replace('::', '.')
|
||||||
|
ret = writer.call('_api.%s' % func,
|
||||||
|
varargs=unwrapped)
|
||||||
|
wrapped = writer.wrap(ret)
|
||||||
|
writer.return_value(wrapped)
|
||||||
|
writer.println()
|
||||||
|
|
||||||
|
|
||||||
def die_if_null(println, var):
|
class Destructor(Method):
|
||||||
println('if (!%(var)s) return NULL;' % locals())
|
_kind_ = 'dtor'
|
||||||
|
|
||||||
|
|
||||||
class Binding(object):
|
|
||||||
__rank_global = 0
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.rank = Binding.__rank_global
|
super(Destructor, self).__init__()
|
||||||
Binding.__rank_global += 1
|
|
||||||
self.include = set()
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
def compile_cpp_body(self, writer, retty, argtys):
|
||||||
raise NotImplementedError(type(self))
|
assert isinstance(self.parent, Class)
|
||||||
|
assert not argtys
|
||||||
|
args = writer.parse_arguments('args', ptr(self.parent), *argtys)
|
||||||
|
writer.println('delete %s;' % args[0])
|
||||||
|
writer.return_value(None)
|
||||||
|
|
||||||
class Ref(object):
|
def compile_py(self, writer):
|
||||||
def __init__(self, elem):
|
func = '.'.join([self.parent.name, self.name])
|
||||||
self.element = elem
|
writer.println('_delete_ = _api.%s' % func)
|
||||||
|
|
||||||
|
|
||||||
|
class Constructor(StaticMethod):
|
||||||
|
_kind_ = 'ctor'
|
||||||
|
|
||||||
|
def __init__(self, *args):
|
||||||
|
super(Constructor, self).__init__(Void, *args)
|
||||||
|
|
||||||
|
def compile_cpp_call(self, writer, retty, args):
|
||||||
|
alloctype = retty.fullname.rstrip(' *')
|
||||||
|
arglist = ', '.join(args)
|
||||||
|
stmt = 'new %(alloctype)s(%(arglist)s)' % locals()
|
||||||
|
ret = writer.declare(retty.fullname, stmt)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
class ref(Type):
|
||||||
|
def __init__(self, element):
|
||||||
|
assert isinstance(element, Class), type(element)
|
||||||
|
self.element = element
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.fullname
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fullname(self):
|
def fullname(self):
|
||||||
|
|
@ -112,503 +356,79 @@ class Ref(object):
|
||||||
def capsule_name(self):
|
def capsule_name(self):
|
||||||
return self.element.capsule_name
|
return self.element.capsule_name
|
||||||
|
|
||||||
@property
|
|
||||||
def pointer(self):
|
|
||||||
return self.element.pointer
|
|
||||||
|
|
||||||
def as_pointer(self, println, var):
|
|
||||||
init = '&%s' % (var)
|
|
||||||
casted = declare(println, self.pointer, init)
|
|
||||||
return casted
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def format(self):
|
def format(self):
|
||||||
return 'O'
|
return self.element.format
|
||||||
|
|
||||||
def unwrap(self, println, var):
|
def wrap(self, writer, val):
|
||||||
ptr = self.element.unwrap(println, var)
|
p = writer.declare(ptr(self.element).fullname, '&%s' % val)
|
||||||
return declare(println, self.fullname, '*%s' % ptr)
|
return writer.pycapsule_new(p, self.capsule_name, self.element.fullname)
|
||||||
|
|
||||||
def wrap(self, println, var):
|
def unwrap(self, writer, val):
|
||||||
return self.element.wrap(println, self.as_pointer(println, var))
|
p = self.element.unwrap(writer, val)
|
||||||
|
return writer.declare(self.fullname, '*%s' % p)
|
||||||
|
|
||||||
|
|
||||||
class Pointer(object):
|
class ptr(Type):
|
||||||
def __init__(self, elem):
|
def __init__(self, element):
|
||||||
self.element = elem
|
assert isinstance(element, Class)
|
||||||
|
self.element = element
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fullname(self):
|
def fullname(self):
|
||||||
return '%s*' % self.element.fullname
|
return '%s*' % self.element
|
||||||
|
|
||||||
@property
|
|
||||||
def capsule_name(self):
|
|
||||||
return self.element.capsule_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pointer(self):
|
|
||||||
return self.element.pointer
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def format(self):
|
def format(self):
|
||||||
return 'O'
|
return self.element.format
|
||||||
|
|
||||||
def unwrap(self, println, var):
|
def unwrap(self, writer, val):
|
||||||
ret = declare(println, self.fullname)
|
ret = writer.declare(self.fullname, 'NULL')
|
||||||
println2 = indent_println(println)
|
with writer.block('if (%(val)s != Py_None)' % locals()):
|
||||||
println('if (%(var)s == Py_None) {' % locals())
|
val = self.element.unwrap(writer, val)
|
||||||
println2('%(ret)s = NULL;' % locals())
|
writer.println('%(ret)s = %(val)s;' % locals())
|
||||||
println('} else {')
|
|
||||||
ptr = self.element.unwrap(println2, var)
|
|
||||||
println2('%(ret)s = %(ptr)s;' % locals())
|
|
||||||
println('}')
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def wrap(self, println, var):
|
def wrap(self, writer, val):
|
||||||
return self.element.wrap(println, var)
|
return writer.pycapsule_new(val, self.element.capsule_name,
|
||||||
|
self.element.fullname)
|
||||||
|
|
||||||
|
class cast(Type):
|
||||||
class BuiltinType(object):
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
self.Ref = Ref(self)
|
|
||||||
self.Pointer = Pointer(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def capsule_name(self):
|
|
||||||
return self.fullname
|
|
||||||
|
|
||||||
def To(self, pytype):
|
|
||||||
return Wrapper(self, pytype)
|
|
||||||
|
|
||||||
def From(self, pytype):
|
|
||||||
return Unwrapper(self, pytype)
|
|
||||||
|
|
||||||
Void = BuiltinType('void')
|
|
||||||
Bool = BuiltinType('bool')
|
|
||||||
Unsigned = BuiltinType('unsigned')
|
|
||||||
ConstStdString = BuiltinType('const std::string')
|
|
||||||
|
|
||||||
class PyObjectImpl(object):
|
|
||||||
name = 'PyObject*'
|
|
||||||
fullname = name
|
|
||||||
format = 'O'
|
format = 'O'
|
||||||
|
|
||||||
def unwrap(self, println, var):
|
def __init__(self, original, target):
|
||||||
return var
|
self.original = original
|
||||||
|
self.target = target
|
||||||
PyObject = PyObjectImpl()
|
|
||||||
|
|
||||||
class Unwrapper(object):
|
|
||||||
def __init__(self, cls, pytype):
|
|
||||||
self.cls = cls
|
|
||||||
self.pytype = pytype
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fullname(self):
|
def fullname(self):
|
||||||
return str(self.pytype)
|
return self.binding_type.fullname
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def format(self):
|
def python_type(self):
|
||||||
return 'O'
|
if not isinstance(self.target, Type):
|
||||||
|
return self.target
|
||||||
def unwrap(self, println, var):
|
|
||||||
out = declare(println, self.cls.fullname)
|
|
||||||
conv = 'py_%s_to' % (self.pytype.__name__)
|
|
||||||
status = '%(conv)s(%(var)s, %(out)s)' % locals()
|
|
||||||
println('if (!%(status)s) return NULL;' % locals())
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
class Wrapper(object):
|
|
||||||
def __init__(self, cls, pytype):
|
|
||||||
self.cls = cls
|
|
||||||
self.pytype = pytype
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return self.cls.fullname
|
|
||||||
|
|
||||||
def wrap(self, println, var):
|
|
||||||
conv = 'py_%s_from' % (self.pytype.__name__)
|
|
||||||
func = '%(conv)s(%(var)s)' % locals()
|
|
||||||
out = declare(println, 'PyObject*', func)
|
|
||||||
println('if (!%(out)s) return NULL;' % locals())
|
|
||||||
return out
|
|
||||||
|
|
||||||
class Enum(Binding):
|
|
||||||
def __init__(self, ns, *values):
|
|
||||||
super(Enum, self).__init__()
|
|
||||||
self.values = values
|
|
||||||
self.ns = ns
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
self.name = self.name or name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.ns, self.name])
|
|
||||||
|
|
||||||
class ClassEnum(Enum):
|
|
||||||
def __init__(self, cls, *values):
|
|
||||||
super(ClassEnum, self).__init__(None, *values)
|
|
||||||
self.cls = cls
|
|
||||||
self.cls.enums.append(self)
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
self.ns = self.cls.fullname
|
|
||||||
super(ClassEnum, self).compile(name, println)
|
|
||||||
|
|
||||||
def wrap(self, println, var):
|
|
||||||
println2 = indent_println(println)
|
|
||||||
ret = declare(println, 'PyObject*', NULL)
|
|
||||||
println('switch(%s) { ' % var)
|
|
||||||
for v in self.values:
|
|
||||||
println('case %s::%s:' % (self.ns, v))
|
|
||||||
println2('%(ret)s = PyString_FromString("%(v)s");' % locals())
|
|
||||||
println2('break;')
|
|
||||||
else:
|
else:
|
||||||
println('default:')
|
return self.original
|
||||||
println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' %
|
|
||||||
v)
|
@property
|
||||||
println2('return NULL;')
|
def binding_type(self):
|
||||||
println('}')
|
if isinstance(self.target, Type):
|
||||||
|
return self.target
|
||||||
|
else:
|
||||||
|
return self.original
|
||||||
|
|
||||||
|
def wrap(self, writer, val):
|
||||||
|
dst = self.python_type.__name__
|
||||||
|
return writer.call('py_%(dst)s_from' % locals(), 'PyObject*', val)
|
||||||
|
|
||||||
|
def unwrap(self, writer, val):
|
||||||
|
src = self.python_type.__name__
|
||||||
|
dst = self.binding_type.fullname
|
||||||
|
ret = writer.declare(dst)
|
||||||
|
status = writer.call('py_%(src)s_to' % locals(), 'int', val, ret)
|
||||||
|
writer.die_if_false(status)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def unwrap(self, println, var):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Class(Binding):
|
|
||||||
def __init__(self, ns):
|
|
||||||
super(Class, self).__init__()
|
|
||||||
self.ctor = None
|
|
||||||
self.Ref = Ref(self)
|
|
||||||
self.Pointer = Pointer(self)
|
|
||||||
self.Subclass = lambda: Subclass(self)
|
|
||||||
self.Enum = lambda *v: ClassEnum(self, *v)
|
|
||||||
self.enums = []
|
|
||||||
self.ns = ns
|
|
||||||
self.methods = []
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
def To(self, pytype):
|
|
||||||
return Wrapper(self, pytype)
|
|
||||||
|
|
||||||
def From(self, pytype):
|
|
||||||
return Unwrapper(self, pytype)
|
|
||||||
|
|
||||||
def new(self, *args):
|
|
||||||
method = Constructor(self, self.Pointer, *args)
|
|
||||||
self.methods.append(method)
|
|
||||||
return method
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
method = Destructor(self, Void, self.Pointer)
|
|
||||||
self.methods.append(method)
|
|
||||||
return method
|
|
||||||
|
|
||||||
def method(self, return_type, *args):
|
|
||||||
method = Method(self, return_type, self.Pointer, *args)
|
|
||||||
self.methods.append(method)
|
|
||||||
return method
|
|
||||||
|
|
||||||
def staticmethod(self, return_type, *args):
|
|
||||||
sm = StaticMethod(self, return_type, *args)
|
|
||||||
self.methods.append(sm)
|
|
||||||
return sm
|
|
||||||
|
|
||||||
def multimethod(self, *signatures):
|
|
||||||
mm = MultiMethod(self, signatures)
|
|
||||||
self.methods.append(mm)
|
|
||||||
return mm
|
|
||||||
|
|
||||||
def staticmultimethod(self, *signatures):
|
|
||||||
smm = StaticMultiMethod(self, signatures)
|
|
||||||
self.methods.append(smm)
|
|
||||||
return smm
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
# set name
|
|
||||||
self.name = self.name or name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def capsule_name(self):
|
|
||||||
return self.fullname
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pointer(self):
|
|
||||||
return '%s*' % self.fullname
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.ns, self.name])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mangled_name(self):
|
|
||||||
return mangle(self.fullname)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def format(self):
|
|
||||||
return 'O'
|
|
||||||
|
|
||||||
def unwrap(self, println, var):
|
|
||||||
typ = self.pointer
|
|
||||||
elty = self.fullname
|
|
||||||
cap = self.capsule_name
|
|
||||||
capptr = 'PyCapsule_GetPointer(%(var)s, "%(cap)s")' % locals()
|
|
||||||
ptr = declare(println, 'void*', capptr)
|
|
||||||
unwrapped = 'typecast<%(elty)s>::from(%(ptr)s)' % locals()
|
|
||||||
var = declare(println, typ, unwrapped)
|
|
||||||
println('if (!%(var)s) {' % locals())
|
|
||||||
println2 = indent_println(println)
|
|
||||||
println2('PyErr_SetString(PyExc_TypeError, "Invalid cast");')
|
|
||||||
println2('return NULL;')
|
|
||||||
println('}')
|
|
||||||
die_if_null(println, var)
|
|
||||||
return var
|
|
||||||
|
|
||||||
def wrap(self, println, var):
|
|
||||||
return pycapsule_new(println, var, self.capsule_name, self.fullname)
|
|
||||||
|
|
||||||
class Subclass(Class):
|
|
||||||
def __init__(self, parent):
|
|
||||||
super(Subclass, self).__init__(parent.ns)
|
|
||||||
self.parent = parent
|
|
||||||
self.ns = self.parent.ns
|
|
||||||
|
|
||||||
@property
|
|
||||||
def capsule_name(self):
|
|
||||||
return self.parent.capsule_name
|
|
||||||
|
|
||||||
class Function(Binding):
|
|
||||||
def __init__(self, ns, return_type, *args):
|
|
||||||
super(Function, self).__init__()
|
|
||||||
self.return_type = return_type
|
|
||||||
self.args = args
|
|
||||||
self.ns = ns
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
# set name
|
|
||||||
self.name = self.name or name
|
|
||||||
# generate wrapper
|
|
||||||
println('static')
|
|
||||||
println('PyObject*')
|
|
||||||
println('%(name)s(PyObject* self, PyObject* args)' % locals())
|
|
||||||
println('{')
|
|
||||||
self.compile_body(indent_println(println))
|
|
||||||
println('}')
|
|
||||||
|
|
||||||
def compile_body(self, println):
|
|
||||||
args = parse_arguments(println, 'args', *self.args)
|
|
||||||
call = '%s(%s)' % (self.fullname, ', '.join(args))
|
|
||||||
if self.return_type is not Void:
|
|
||||||
callres = declare(println, self.return_type.fullname, call)
|
|
||||||
pycap = self.return_type.wrap(println, callres)
|
|
||||||
return_value(println, pycap)
|
|
||||||
else:
|
|
||||||
println('%s;' % call)
|
|
||||||
return_none(println)
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.ns, self.name])
|
|
||||||
|
|
||||||
class Method(Binding):
|
|
||||||
def __init__(self, cls, return_type, *args):
|
|
||||||
super(Method, self).__init__()
|
|
||||||
self.cls = cls
|
|
||||||
self.return_type = return_type
|
|
||||||
self.args = args
|
|
||||||
self.name = None
|
|
||||||
self._realname = None
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
# set name
|
|
||||||
self.name = self.name or name
|
|
||||||
# generate wrapper
|
|
||||||
println('static')
|
|
||||||
println('PyObject*')
|
|
||||||
mangled = self.mangled_name
|
|
||||||
println('%(mangled)s(PyObject* self, PyObject* args)' % locals())
|
|
||||||
println('{')
|
|
||||||
self.compile_body(indent_println(println))
|
|
||||||
println('}')
|
|
||||||
|
|
||||||
def compile_body(self, println):
|
|
||||||
args = parse_arguments(println, 'args', *self.args)
|
|
||||||
this = args[0]
|
|
||||||
args = ', '.join(args[1:])
|
|
||||||
name = self.realname
|
|
||||||
call = '%(this)s->%(name)s(%(args)s)' % locals()
|
|
||||||
if self.return_type is not Void:
|
|
||||||
obj = declare(println, self.return_type.fullname, call)
|
|
||||||
ret = self.return_type.wrap(println, obj)
|
|
||||||
return_value(println, ret)
|
|
||||||
else:
|
|
||||||
println('%s;' % call)
|
|
||||||
return_none(println)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.cls.fullname, self.name])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def realname(self):
|
|
||||||
if not self._realname:
|
|
||||||
return self.name
|
|
||||||
else:
|
|
||||||
return self._realname
|
|
||||||
|
|
||||||
@realname.setter
|
|
||||||
def realname(self, v):
|
|
||||||
self._realname = v
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mangled_name(self):
|
|
||||||
return mangle(self.fullname)
|
|
||||||
|
|
||||||
class MultiMethod(Binding):
|
|
||||||
'''Can only differs by the number of arguments.
|
|
||||||
'''
|
|
||||||
def __init__(self, cls, signatures):
|
|
||||||
super(MultiMethod, self).__init__()
|
|
||||||
nargs = set()
|
|
||||||
for sig in signatures:
|
|
||||||
n = len(sig)
|
|
||||||
if n in nargs:
|
|
||||||
raise TypeError("MultiMethod only supports overloaded version"
|
|
||||||
"with different number of arguments")
|
|
||||||
nargs.add(n)
|
|
||||||
self.cls = cls
|
|
||||||
self.signatures = signatures
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
# set name
|
|
||||||
self.name = self.name or name
|
|
||||||
# generate wrapper
|
|
||||||
println('static')
|
|
||||||
println('PyObject*')
|
|
||||||
mangled = self.mangled_name
|
|
||||||
println('%(mangled)s(PyObject* self, PyObject* args)' % locals())
|
|
||||||
println('{')
|
|
||||||
println2 = indent_println(println)
|
|
||||||
nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)')
|
|
||||||
for sig in self.signatures:
|
|
||||||
expect = len(sig)
|
|
||||||
println2('if (%(nargs)s == %(expect)d) {' % locals())
|
|
||||||
method = Method(self.cls, sig[0], self.cls.Pointer, *sig[1:])
|
|
||||||
method.name = self.name
|
|
||||||
method.compile_body(indent_println(println2))
|
|
||||||
println2('}')
|
|
||||||
println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");')
|
|
||||||
println2('return NULL;')
|
|
||||||
println('}')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.cls.fullname, self.name])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mangled_name(self):
|
|
||||||
return mangle(self.fullname)
|
|
||||||
|
|
||||||
class StaticMethod(Method):
|
|
||||||
def compile_body(self, println):
|
|
||||||
args = parse_arguments(println, 'args', *self.args)
|
|
||||||
args = ', '.join(args)
|
|
||||||
fullname = self.fullname
|
|
||||||
call = '%(fullname)s(%(args)s)' % locals()
|
|
||||||
if self.return_type is not Void:
|
|
||||||
obj = declare(println, self.return_type.fullname, call)
|
|
||||||
ret = self.return_type.wrap(println, obj)
|
|
||||||
return_value(println, ret)
|
|
||||||
else:
|
|
||||||
println('%s;' % call)
|
|
||||||
return_none(println)
|
|
||||||
|
|
||||||
class StaticMultiMethod(Binding):
|
|
||||||
'''Can only differs by the number of arguments.
|
|
||||||
'''
|
|
||||||
def __init__(self, cls, signatures):
|
|
||||||
super(StaticMultiMethod, self).__init__()
|
|
||||||
nargs = set()
|
|
||||||
for sig in signatures:
|
|
||||||
n = len(sig)
|
|
||||||
if n in nargs:
|
|
||||||
raise TypeError("StaticMultiMethod only supports overloaded "
|
|
||||||
"version with different number of arguments")
|
|
||||||
nargs.add(n)
|
|
||||||
self.cls = cls
|
|
||||||
self.signatures = signatures
|
|
||||||
self.name = None
|
|
||||||
|
|
||||||
|
|
||||||
def compile(self, name, println):
|
|
||||||
# set name
|
|
||||||
self.name = self.name or name
|
|
||||||
# generate wrapper
|
|
||||||
println('static')
|
|
||||||
println('PyObject*')
|
|
||||||
mangled = self.mangled_name
|
|
||||||
println('%(mangled)s(PyObject* self, PyObject* args)' % locals())
|
|
||||||
println('{')
|
|
||||||
println2 = indent_println(println)
|
|
||||||
nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)')
|
|
||||||
for sig in self.signatures:
|
|
||||||
expect = len(sig) - 1
|
|
||||||
println2('if (%(nargs)s == %(expect)d) {' % locals())
|
|
||||||
method = StaticMethod(self.cls, sig[0], *sig[1:])
|
|
||||||
method.name = self.name
|
|
||||||
method.compile_body(indent_println(println2))
|
|
||||||
println2('}')
|
|
||||||
println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");')
|
|
||||||
println2('return NULL;')
|
|
||||||
println('}')
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fullname(self):
|
|
||||||
return '::'.join([self.cls.fullname, self.name])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def mangled_name(self):
|
|
||||||
return mangle(self.fullname)
|
|
||||||
|
|
||||||
class Constructor(StaticMethod):
|
|
||||||
def compile_body(self, println):
|
|
||||||
args = parse_arguments(println, 'args', *self.args)
|
|
||||||
args = ', '.join(args)
|
|
||||||
name = self.cls.fullname
|
|
||||||
ctor = 'new %(name)s(%(args)s)' % locals()
|
|
||||||
obj = declare(println, self.cls.pointer, ctor)
|
|
||||||
ret = self.return_type.wrap(println, obj)
|
|
||||||
return_value(println, ret)
|
|
||||||
|
|
||||||
class Destructor(Method):
|
|
||||||
def compile_body(self, println):
|
|
||||||
args = parse_arguments(println, 'args', *self.args)
|
|
||||||
assert len(args) == 1
|
|
||||||
dtor = 'delete %s;' % args[0]
|
|
||||||
println(dtor)
|
|
||||||
return_none(println)
|
|
||||||
|
|
||||||
|
|
||||||
class Namespace(object):
|
|
||||||
def __init__(self, name):
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def Class(self, *args, **kwargs):
|
|
||||||
return Class(self.name, *args, **kwargs)
|
|
||||||
|
|
||||||
def Function(self, *args, **kwargs):
|
|
||||||
return Function(self.name, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
|
||||||
279
newbinding/codegen.py
Normal file
279
newbinding/codegen.py
Normal file
|
|
@ -0,0 +1,279 @@
|
||||||
|
import re, contextlib
|
||||||
|
|
||||||
|
NULL = 'NULL'
|
||||||
|
|
||||||
|
_symbols = set()
|
||||||
|
|
||||||
|
def indent(println):
|
||||||
|
def _println(s=''):
|
||||||
|
println("%s%s" % (' '* 4, s))
|
||||||
|
return _println
|
||||||
|
|
||||||
|
def quote(txt):
|
||||||
|
return '"%s"' % txt
|
||||||
|
|
||||||
|
def new_symbol(name):
|
||||||
|
if name in _symbols:
|
||||||
|
ct = 1
|
||||||
|
orig = name
|
||||||
|
while name in _symbols:
|
||||||
|
name = '%s%d' % (orig, ct)
|
||||||
|
ct += 1
|
||||||
|
_symbols.add(name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
def parse_arguments(println, var, *args):
|
||||||
|
typecodes = []
|
||||||
|
holders = []
|
||||||
|
argvals = []
|
||||||
|
for arg in args:
|
||||||
|
typecodes.append(arg.format)
|
||||||
|
val = declare(println, 'PyObject*')
|
||||||
|
argvals.append(val)
|
||||||
|
holders.append('&' + val)
|
||||||
|
|
||||||
|
items = [var, '"%s"' % (''.join(typecodes))] + holders
|
||||||
|
println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items))
|
||||||
|
|
||||||
|
# unwrap
|
||||||
|
unwrapped = []
|
||||||
|
for arg, val in zip(args, argvals):
|
||||||
|
unwrapped.append(arg.unwrap(println, val))
|
||||||
|
|
||||||
|
return unwrapped
|
||||||
|
|
||||||
|
_re_mangle_pattern = re.compile(r'[ _<>\*&]')
|
||||||
|
|
||||||
|
def mangle(name):
|
||||||
|
def repl(m):
|
||||||
|
s = m.group(0)
|
||||||
|
if s in '<>*&':
|
||||||
|
return ''
|
||||||
|
elif s in ' ':
|
||||||
|
return '_'
|
||||||
|
elif s in '_':
|
||||||
|
return '__'
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
name = _re_mangle_pattern.sub(repl, name)
|
||||||
|
return name.replace('::', '_')
|
||||||
|
|
||||||
|
def pycapsule_new(println, ptr, name, clsname):
|
||||||
|
# build capsule
|
||||||
|
name_soften = mangle(name)
|
||||||
|
var = new_symbol('pycap_%s' % name_soften)
|
||||||
|
fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");'
|
||||||
|
println(fmt % locals())
|
||||||
|
println('if (!%(var)s) return NULL;' % locals())
|
||||||
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
def declare(println, typ, init=None):
|
||||||
|
typ_soften = mangle(typ)
|
||||||
|
var = new_symbol('var_%s' % typ_soften)
|
||||||
|
if init is None:
|
||||||
|
println('%(typ)s %(var)s;' % locals())
|
||||||
|
else:
|
||||||
|
println('%(typ)s %(var)s = %(init)s;' % locals())
|
||||||
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
def return_value(println, var):
|
||||||
|
println('return %(var)s;' % locals())
|
||||||
|
|
||||||
|
|
||||||
|
def return_none(println):
|
||||||
|
println('Py_RETURN_NONE;')
|
||||||
|
|
||||||
|
|
||||||
|
def die_if_null(println, var):
|
||||||
|
println('if (!%(var)s) return NULL;' % locals())
|
||||||
|
|
||||||
|
|
||||||
|
class CodeWriterBase(object):
|
||||||
|
def __init__(self, println):
|
||||||
|
self.println = println
|
||||||
|
self.used_symbols = set()
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def indent(self):
|
||||||
|
old = self.println
|
||||||
|
self.println = indent(self.println)
|
||||||
|
yield
|
||||||
|
self.println = old
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def py_function(self, name):
|
||||||
|
mangled = mangle(name)
|
||||||
|
self.println('static')
|
||||||
|
self.println('PyObject*')
|
||||||
|
with self.block('%(mangled)s(PyObject* self, PyObject* args)' % locals()):
|
||||||
|
self.used_symbols.add('self')
|
||||||
|
self.used_symbols.add('args')
|
||||||
|
yield
|
||||||
|
self.println()
|
||||||
|
|
||||||
|
def new_symbol(self, name):
|
||||||
|
if name in self.used_symbols:
|
||||||
|
ct = 1
|
||||||
|
orig = name
|
||||||
|
while name in self.used_symbols:
|
||||||
|
name = '%s%d' % (orig, ct)
|
||||||
|
ct += 1
|
||||||
|
self.used_symbols.add(name)
|
||||||
|
return name
|
||||||
|
|
||||||
|
class CppCodeWriter(CodeWriterBase):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def block(self, lead):
|
||||||
|
self.println(lead)
|
||||||
|
self.println('{')
|
||||||
|
with self.indent():
|
||||||
|
yield
|
||||||
|
self.println('}')
|
||||||
|
|
||||||
|
def declare(self, typ, init=None):
|
||||||
|
typ_soften = mangle(typ)
|
||||||
|
var = self.new_symbol('var_%s' % typ_soften)
|
||||||
|
if init is None:
|
||||||
|
self.println('%(typ)s %(var)s;' % locals())
|
||||||
|
else:
|
||||||
|
self.println('%(typ)s %(var)s = %(init)s;' % locals())
|
||||||
|
return var
|
||||||
|
|
||||||
|
def return_value(self, val):
|
||||||
|
if val is None:
|
||||||
|
self.println('Py_RETURN_NONE;')
|
||||||
|
else:
|
||||||
|
self.println('return %s;' % val)
|
||||||
|
|
||||||
|
def return_null(self):
|
||||||
|
self.return_value(NULL)
|
||||||
|
|
||||||
|
def parse_arguments(self, var, *args):
|
||||||
|
typecodes = []
|
||||||
|
holders = []
|
||||||
|
argvals = []
|
||||||
|
for arg in args:
|
||||||
|
typecodes.append(arg.format)
|
||||||
|
val = self.declare('PyObject*')
|
||||||
|
argvals.append(val)
|
||||||
|
holders.append('&' + val)
|
||||||
|
|
||||||
|
items = [var, '"%s"' % (''.join(typecodes))] + holders
|
||||||
|
with self.block('if(!PyArg_ParseTuple(%s))' % ', '.join(items)):
|
||||||
|
self.return_null()
|
||||||
|
|
||||||
|
# unwrap
|
||||||
|
unwrapped = []
|
||||||
|
for arg, val in zip(args, argvals):
|
||||||
|
unwrapped.append(arg.unwrap(self, val))
|
||||||
|
|
||||||
|
return unwrapped
|
||||||
|
|
||||||
|
def call(self, func, retty, *args):
|
||||||
|
arglist = ', '.join(args)
|
||||||
|
stmt = '%(func)s(%(arglist)s)' % locals()
|
||||||
|
if retty == 'void':
|
||||||
|
self.println(stmt)
|
||||||
|
else:
|
||||||
|
return self.declare(retty, stmt)
|
||||||
|
|
||||||
|
def method_call(self, func, retty, *args):
|
||||||
|
this = args[0]
|
||||||
|
arglist = ', '.join(args[1:])
|
||||||
|
if func == 'delete':
|
||||||
|
assert not arglist
|
||||||
|
stmt = 'delete %(this)s;' % locals()
|
||||||
|
elif func == 'new':
|
||||||
|
alloctype = retty.rstrip(' *')
|
||||||
|
stmt = 'new %(alloctype)s(%(arglist)s);' % locals()
|
||||||
|
else:
|
||||||
|
stmt = '%(this)s->%(func)s(%(arglist)s);' % locals()
|
||||||
|
if retty == 'void':
|
||||||
|
self.println(stmt)
|
||||||
|
else:
|
||||||
|
return self.declare(retty, stmt)
|
||||||
|
|
||||||
|
def pycapsule_new(self, ptr, name, clsname):
|
||||||
|
name_soften = mangle(name)
|
||||||
|
ret = self.call('pycapsule_new', 'PyObject*', ptr, quote(name),
|
||||||
|
quote(clsname))
|
||||||
|
with self.block('if (!%(ret)s)' % locals()):
|
||||||
|
self.return_null()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def die_if_false(self, val):
|
||||||
|
with self.block('if(!%(val)s)' % locals()):
|
||||||
|
self.return_null()
|
||||||
|
|
||||||
|
def raises(self, exccls, msg):
|
||||||
|
exc = 'PyExc_%s' % exccls.__name__
|
||||||
|
self.println('PyErr_SetString(%s, "%s");' % (exc, msg))
|
||||||
|
self.return_null()
|
||||||
|
|
||||||
|
|
||||||
|
class PyCodeWriter(CodeWriterBase):
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def block(self, lead):
|
||||||
|
self.println(lead)
|
||||||
|
with self.indent():
|
||||||
|
yield
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def function(self, func, args=(), varargs=None):
|
||||||
|
with self.scope():
|
||||||
|
arguments = []
|
||||||
|
for arg in args:
|
||||||
|
arguments.append(self.new_symbol(arg))
|
||||||
|
if varargs:
|
||||||
|
varargs = self.new_symbol(varargs)
|
||||||
|
arguments.append('*%s' % varargs)
|
||||||
|
arglist = ', '.join(arguments)
|
||||||
|
with self.block('def %(func)s(%(arglist)s):' % locals()):
|
||||||
|
if arguments:
|
||||||
|
arguments[-1] = arguments[-1].lstrip('*')
|
||||||
|
if len(arguments) > 1:
|
||||||
|
yield arguments
|
||||||
|
else:
|
||||||
|
yield arguments[0]
|
||||||
|
else:
|
||||||
|
yield
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def scope(self):
|
||||||
|
self.old = self.used_symbols
|
||||||
|
self.used_symbols = set()
|
||||||
|
yield
|
||||||
|
self.used_symbols = self.old
|
||||||
|
|
||||||
|
def unwrap_many(self, args):
|
||||||
|
unwrapped = self.new_symbol('unwrapped')
|
||||||
|
self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals())
|
||||||
|
return unwrapped
|
||||||
|
|
||||||
|
def unwrap(self, val):
|
||||||
|
return self.call('capsule.unwrap', args=(val,), ret='unwrapped')
|
||||||
|
|
||||||
|
def wrap(self, val):
|
||||||
|
wrapped = self.new_symbol('wrapped')
|
||||||
|
self.println('%(wrapped)s = capsule.wrap(%(val)s)' % locals())
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
def call(self, func, args=(), varargs=None, ret='ret'):
|
||||||
|
arguments = []
|
||||||
|
for arg in args:
|
||||||
|
arguments.append(arg)
|
||||||
|
if varargs:
|
||||||
|
arguments.append('*%s' % varargs)
|
||||||
|
arglist = ', '.join(arguments)
|
||||||
|
ret = self.new_symbol(ret)
|
||||||
|
self.println('%(ret)s = %(func)s(%(arglist)s)' % locals())
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def return_value(self, val=None):
|
||||||
|
if val is None:
|
||||||
|
val = ''
|
||||||
|
self.println('return %s' % val)
|
||||||
|
|
||||||
|
|
||||||
20
newbinding/extra.py
Normal file
20
newbinding/extra.py
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
'''
|
||||||
|
Wrapped the extra functions in _api.so
|
||||||
|
'''
|
||||||
|
|
||||||
|
import capsule
|
||||||
|
|
||||||
|
def _wrapper(func):
|
||||||
|
def _core(*args):
|
||||||
|
unwrapped = map(capsule.unwrap, args)
|
||||||
|
ret = func(*unwrapped)
|
||||||
|
return capsule.wrap(ret)
|
||||||
|
return _core
|
||||||
|
|
||||||
|
def _init(glob):
|
||||||
|
from _api import extra
|
||||||
|
for k, v in extra.__dict__.items():
|
||||||
|
glob[k] = _wrapper(v)
|
||||||
|
|
||||||
|
_init(globals())
|
||||||
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
import sys, logging
|
import sys
|
||||||
from binding import *
|
from binding import *
|
||||||
from utils import *
|
import codegen
|
||||||
from cStringIO import StringIO
|
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
extension_entry = '''
|
extension_entry = '''
|
||||||
|
|
||||||
|
|
@ -15,12 +12,12 @@ extern "C" {
|
||||||
PyObject *
|
PyObject *
|
||||||
PyInit_%(module)s(void)
|
PyInit_%(module)s(void)
|
||||||
{
|
{
|
||||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||||
if (module) {
|
if (module) {
|
||||||
if (populate_submodules(module, submodules))
|
if (populate_submodules(module, submodules))
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
@ -28,10 +25,10 @@ PyInit_%(module)s(void)
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
init%(module)s(void)
|
init%(module)s(void)
|
||||||
{
|
{
|
||||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||||
if (module) {
|
if (module) {
|
||||||
populate_submodules(module, submodules);
|
populate_submodules(module, submodules);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -39,172 +36,6 @@ init%(module)s(void)
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def build_methoddef(name, defns, println):
|
|
||||||
println('static PyMethodDef %s[] = {' % name)
|
|
||||||
for name, func in defns:
|
|
||||||
println('{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' %
|
|
||||||
locals())
|
|
||||||
else:
|
|
||||||
println('{ NULL }')
|
|
||||||
println('};')
|
|
||||||
println('')
|
|
||||||
|
|
||||||
|
|
||||||
class Context(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.includes = set()
|
|
||||||
self.functions = {}
|
|
||||||
self.classes = {}
|
|
||||||
self.definitions = []
|
|
||||||
self._pending_symbols = []
|
|
||||||
|
|
||||||
def generate_cpp(self, println):
|
|
||||||
for i in self.includes:
|
|
||||||
println('#include "%s"' % i)
|
|
||||||
|
|
||||||
println('\n'.join(self.definitions))
|
|
||||||
|
|
||||||
# global function
|
|
||||||
defns = []
|
|
||||||
for name, func in self.functions.items():
|
|
||||||
defns.append((name, func.name))
|
|
||||||
build_methoddef('global_functions', defns, println)
|
|
||||||
|
|
||||||
# classes
|
|
||||||
for name, cls in self.classes.items():
|
|
||||||
defns = []
|
|
||||||
for meth in cls.methods:
|
|
||||||
defns.append((meth.name, meth.mangled_name))
|
|
||||||
println("// %s" % cls.fullname)
|
|
||||||
build_methoddef(cls.mangled_name, defns, println)
|
|
||||||
|
|
||||||
println('static SubModuleEntry submodules[] = {')
|
|
||||||
for name, cls in self.classes.items():
|
|
||||||
table = cls.mangled_name
|
|
||||||
println('{ "%(name)s", %(table)s },' % locals())
|
|
||||||
println('{ "extra", extra_methodtable },')
|
|
||||||
println('{ NULL }')
|
|
||||||
println('};')
|
|
||||||
println('')
|
|
||||||
|
|
||||||
# generate entry
|
|
||||||
println(extension_entry % {'module': '_api',
|
|
||||||
'methtable': 'global_functions',})
|
|
||||||
|
|
||||||
def generate_py(self, println):
|
|
||||||
println('import _api, capsule')
|
|
||||||
println('')
|
|
||||||
# wraps all extras
|
|
||||||
extra_wrapper = '''
|
|
||||||
def _init_extra_wrapper():
|
|
||||||
def wrap(callee):
|
|
||||||
def _wrapped(*args):
|
|
||||||
args = map(capsule.unwrap, args)
|
|
||||||
ret = callee(*args)
|
|
||||||
return capsule.wrap(ret)
|
|
||||||
return _wrapped
|
|
||||||
for k in dir(_api.extra):
|
|
||||||
v = getattr(_api.extra, k)
|
|
||||||
if not k.startswith('__') and callable(v):
|
|
||||||
globals()[k] = wrap(v)
|
|
||||||
_init_extra_wrapper()
|
|
||||||
'''
|
|
||||||
println(extra_wrapper)
|
|
||||||
println('')
|
|
||||||
# global function
|
|
||||||
for name in self.functions:
|
|
||||||
println('def %(name)s(*args):' % locals())
|
|
||||||
println2 = indent_println(println)
|
|
||||||
println2('args = map(capsule.unwrap, args)')
|
|
||||||
println2('ptr = _api.%(name)s(*args)' % locals())
|
|
||||||
println2('return capsule.wrap(ptr)')
|
|
||||||
println('')
|
|
||||||
# classes
|
|
||||||
classes = sorted(self.classes.items(), key=lambda x: x[1].rank)
|
|
||||||
|
|
||||||
for name, cls in classes:
|
|
||||||
if isinstance(cls, Subclass):
|
|
||||||
parent = cls.parent.name
|
|
||||||
else:
|
|
||||||
parent = 'capsule.Wrapper'
|
|
||||||
println('@capsule.register_class')
|
|
||||||
println('class %(name)s(%(parent)s):' % locals())
|
|
||||||
self.generate_py_class(indent_println(println), cls)
|
|
||||||
println('')
|
|
||||||
|
|
||||||
def generate_py_class(self, println, cls):
|
|
||||||
if len(cls.methods) == 0:
|
|
||||||
println('pass')
|
|
||||||
else:
|
|
||||||
mod = cls.name
|
|
||||||
# generate class enums
|
|
||||||
for enum in cls.enums:
|
|
||||||
println('class %s:' % enum.name)
|
|
||||||
println2 = indent_println(println)
|
|
||||||
for v in enum.values:
|
|
||||||
println2('%(v)s = "%(v)s"' % locals())
|
|
||||||
println('')
|
|
||||||
# generate class methods
|
|
||||||
for method in cls.methods:
|
|
||||||
name = method.name
|
|
||||||
if(isinstance(method, StaticMethod) or
|
|
||||||
isinstance(method, StaticMultiMethod)):
|
|
||||||
println('@staticmethod')
|
|
||||||
println('def %(name)s(*args):' % locals())
|
|
||||||
println2 = indent_println(println)
|
|
||||||
println2('args = map(capsule.unwrap, args)')
|
|
||||||
println2('ret = _api.%(mod)s.%(name)s(*args)' % locals())
|
|
||||||
println2('return capsule.wrap(ret)')
|
|
||||||
elif isinstance(method, Destructor):
|
|
||||||
println('_delete_ = _api.%(mod)s.%(name)s' % locals())
|
|
||||||
else:
|
|
||||||
println('def %(name)s(self, *args):' % locals())
|
|
||||||
println2 = indent_println(println)
|
|
||||||
println2('args = map(capsule.unwrap, args)')
|
|
||||||
println2('ret = _api.%(mod)s.%(name)s(self._ptr, *args)' %
|
|
||||||
locals())
|
|
||||||
println2('return capsule.wrap(ret)')
|
|
||||||
println('')
|
|
||||||
|
|
||||||
def add_module(self, module):
|
|
||||||
allsyms = [(k, v) for k, v in vars(module).items()
|
|
||||||
if isinstance(v, Binding)]
|
|
||||||
# generate includes
|
|
||||||
for k, v in allsyms:
|
|
||||||
self.includes |= v.include
|
|
||||||
|
|
||||||
self._pending_symbols.extend(allsyms)
|
|
||||||
|
|
||||||
def materialize(self):
|
|
||||||
symtab = sorted(self._pending_symbols, key=lambda x: x[1].rank)
|
|
||||||
|
|
||||||
# compile everything
|
|
||||||
for k, v in symtab:
|
|
||||||
buf = StringIO()
|
|
||||||
def println_to_def(s):
|
|
||||||
buf.write(s)
|
|
||||||
buf.write('\n')
|
|
||||||
logger.info('compiling %s', k)
|
|
||||||
v.compile(k, println_to_def)
|
|
||||||
self.definitions.append(buf.getvalue())
|
|
||||||
buf.close()
|
|
||||||
|
|
||||||
# generate py defintion table for global functions
|
|
||||||
for k, v in symtab:
|
|
||||||
if isinstance(v, Function):
|
|
||||||
if v.name in self.functions:
|
|
||||||
raise NameError("Duplicated function name: %s" % v.name)
|
|
||||||
self.functions[v.name] = v
|
|
||||||
|
|
||||||
# generate sub module tables for classes
|
|
||||||
submodules = []
|
|
||||||
for k, v in symtab:
|
|
||||||
if isinstance(v, Class):
|
|
||||||
if v.name in self.classes:
|
|
||||||
if v is not self.classes[v.name]:
|
|
||||||
raise NameError("Duplicated class: %s" % v.name)
|
|
||||||
self.classes[v.name] = v
|
|
||||||
|
|
||||||
|
|
||||||
def populate_headers(println):
|
def populate_headers(println):
|
||||||
includes = [
|
includes = [
|
||||||
|
|
@ -216,38 +47,96 @@ def populate_headers(println):
|
||||||
]
|
]
|
||||||
for inc in includes:
|
for inc in includes:
|
||||||
println('#include "%s"' % inc)
|
println('#include "%s"' % inc)
|
||||||
|
println()
|
||||||
|
|
||||||
def wrap_println(f):
|
|
||||||
def println(s):
|
def wrap_println_from_file(file):
|
||||||
f.write(s)
|
def println(s=''):
|
||||||
f.write('\n')
|
file.write(s)
|
||||||
|
file.write('\n')
|
||||||
return println
|
return println
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def main():
|
||||||
outputfilename = sys.argv[1]
|
outputfilename = sys.argv[1]
|
||||||
srcdir = sys.argv[2]
|
entry_modname = sys.argv[2]
|
||||||
modnames = sys.argv[3:]
|
|
||||||
|
|
||||||
modules = []
|
entry_module = __import__(entry_modname)
|
||||||
for m in modnames:
|
|
||||||
path = '%s.%s' % (srcdir, m)
|
|
||||||
logger.info("import module %s", path)
|
|
||||||
module = __import__(path)
|
|
||||||
for token in path.split('.')[1:]:
|
|
||||||
module = getattr(module, token)
|
|
||||||
modules.append(module)
|
|
||||||
|
|
||||||
context = Context()
|
units = []
|
||||||
|
for ns in namespaces.values():
|
||||||
|
print 'namespace', ns
|
||||||
|
for fn in ns.functions:
|
||||||
|
print fn
|
||||||
|
units.append(fn)
|
||||||
|
for cls in ns.classes:
|
||||||
|
print cls
|
||||||
|
units.append(cls)
|
||||||
|
|
||||||
for mod in modules:
|
with open('%s.cpp' % outputfilename, 'w') as cppfile:
|
||||||
context.add_module(mod)
|
println = wrap_println_from_file(cppfile)
|
||||||
context.materialize()
|
|
||||||
|
|
||||||
with open('%s.cpp' % outputfilename, 'w') as outfile:
|
# extra headers
|
||||||
println = wrap_println(outfile)
|
|
||||||
populate_headers(println)
|
populate_headers(println)
|
||||||
context.generate_cpp(println)
|
|
||||||
with open('%s.py' % outputfilename, 'w') as outfile:
|
|
||||||
println = wrap_println(outfile)
|
|
||||||
context.generate_py(println)
|
|
||||||
|
|
||||||
|
# required headers
|
||||||
|
includes = set()
|
||||||
|
for u in units:
|
||||||
|
includes |= u.includes
|
||||||
|
|
||||||
|
for inc in includes:
|
||||||
|
println('#include "%s"' % inc)
|
||||||
|
println()
|
||||||
|
|
||||||
|
# write methods and method tables
|
||||||
|
for u in units:
|
||||||
|
writer = codegen.CppCodeWriter(println)
|
||||||
|
u.compile_cpp(writer)
|
||||||
|
else:
|
||||||
|
del writer
|
||||||
|
|
||||||
|
# write function table
|
||||||
|
writer = codegen.CppCodeWriter(println)
|
||||||
|
writer.println('static')
|
||||||
|
writer.println('PyMethodDef methtable[] = {')
|
||||||
|
with writer.indent():
|
||||||
|
fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },'
|
||||||
|
for u in units:
|
||||||
|
if isinstance(u, Function):
|
||||||
|
name = u.name
|
||||||
|
func = codegen.mangle(u.fullname)
|
||||||
|
writer.println(fmt % locals())
|
||||||
|
writer.println('{ NULL },')
|
||||||
|
writer.println('};')
|
||||||
|
writer.println()
|
||||||
|
del writer
|
||||||
|
|
||||||
|
|
||||||
|
# write submodule table
|
||||||
|
writer = codegen.CppCodeWriter(println)
|
||||||
|
writer.println('static')
|
||||||
|
writer.println('SubModuleEntry submodules[] = {')
|
||||||
|
with writer.indent():
|
||||||
|
for cls in units:
|
||||||
|
if isinstance(cls, Class):
|
||||||
|
name = cls.name
|
||||||
|
table = codegen.mangle(cls.fullname)
|
||||||
|
writer.println('{ "%(name)s", %(table)s },' % locals())
|
||||||
|
writer.println('{ "extra", extra_methodtable },')
|
||||||
|
writer.println('{ NULL }')
|
||||||
|
writer.println('};')
|
||||||
|
writer.println('')
|
||||||
|
del writer
|
||||||
|
|
||||||
|
println(extension_entry % {'module': '_api', 'methtable': 'methtable'})
|
||||||
|
|
||||||
|
with open('%s.py' % outputfilename, 'w') as pyfile:
|
||||||
|
println = wrap_println_from_file(pyfile)
|
||||||
|
println('import _api, capsule')
|
||||||
|
println()
|
||||||
|
for u in units:
|
||||||
|
writer = codegen.PyCodeWriter(println)
|
||||||
|
u.compile_py(writer)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
|
||||||
38
newbinding/include/llvm_binding/auto_pyobject.h
Normal file
38
newbinding/include/llvm_binding/auto_pyobject.h
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef AUTO_PYOBJECT_H_
|
||||||
|
#define AUTO_PYOBJECT_H_
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
class auto_pyobject{
|
||||||
|
mutable PyObject* PO;
|
||||||
|
public:
|
||||||
|
auto_pyobject(): PO(NULL) { }
|
||||||
|
|
||||||
|
auto_pyobject(PyObject* po) : PO(po) { }
|
||||||
|
|
||||||
|
auto_pyobject(const auto_pyobject& other) : PO(*other){
|
||||||
|
other.PO = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
~auto_pyobject() {
|
||||||
|
Py_XDECREF(PO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator ! () const {
|
||||||
|
return !PO;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* operator * () const {
|
||||||
|
return PO;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* get() const {
|
||||||
|
return PO;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
// disable assign
|
||||||
|
void operator = (const auto_pyobject&);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif AUTO_PYOBJECT_H_
|
||||||
|
|
||||||
|
|
@ -62,6 +62,11 @@ static
|
||||||
PyObject* py_str_from(const std::string &str){
|
PyObject* py_str_from(const std::string &str){
|
||||||
return PyString_FromStringAndSize(str.c_str(), str.size());
|
return PyString_FromStringAndSize(str.c_str(), str.size());
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
//static
|
||||||
|
//PyObject* py_str_from(const llvm::StringRef *str){
|
||||||
|
// return py_str_from(str->str());
|
||||||
|
//}
|
||||||
|
|
||||||
static
|
static
|
||||||
PyObject* py_bool_from(bool val){
|
PyObject* py_bool_from(bool val){
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
|
|
||||||
AssemblyAnnotationWriter = llvm.Class()
|
@llvm.Class()
|
||||||
AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h")
|
class AssemblyAnnotationWriter:
|
||||||
|
_include_ = "llvm/Assembly/AssemblyAnnotationWriter.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,6 @@ from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
from User import User
|
from User import User
|
||||||
|
|
||||||
Constant = User.Subclass()
|
@llvm.Class(User)
|
||||||
|
class Constant:
|
||||||
|
pass
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,15 @@ from LLVMContext import LLVMContext
|
||||||
from Type import Type
|
from Type import Type
|
||||||
from SmallVector import SmallVector_Type
|
from SmallVector import SmallVector_Type
|
||||||
|
|
||||||
FunctionType = Type.Subclass()
|
FunctionType = llvm.Class(Type)
|
||||||
FunctionType.include.add('llvm/DerivedTypes.h')
|
|
||||||
|
|
||||||
_get_signatures = [(FunctionType.Pointer,
|
@FunctionType
|
||||||
Type.Pointer, Bool.From(bool)),
|
class FunctionType:
|
||||||
(FunctionType.Pointer,
|
_include_ = 'llvm/DerivedTypes.h'
|
||||||
Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))]
|
get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool))
|
||||||
|
get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), cast(bool, Bool))
|
||||||
|
isVarArg = Method(cast(Bool, bool))
|
||||||
|
getReturnType = Method(ptr(Type))
|
||||||
|
getParamType = Method(ptr(Type), cast(int, Unsigned))
|
||||||
|
getNumParams = Method(cast(Unsigned, int))
|
||||||
|
|
||||||
get = FunctionType.staticmultimethod(*_get_signatures)
|
|
||||||
|
|
||||||
isVarArg = FunctionType.method(Bool.To(bool))
|
|
||||||
getReturnType = FunctionType.method(Type.Pointer)
|
|
||||||
getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int))
|
|
||||||
getNumParams = FunctionType.method(Unsigned.To(int))
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
|
|
||||||
LLVMContext = llvm.Class()
|
@llvm.Class()
|
||||||
LLVMContext.include.add("llvm/LLVMContext.h")
|
class LLVMContext:
|
||||||
|
_include_ = "llvm/LLVMContext.h"
|
||||||
getGlobalContext = llvm.Function(LLVMContext.Ref)
|
|
||||||
|
|
||||||
|
llvm.Function('getGlobalContext', ref(LLVMContext))
|
||||||
|
|
|
||||||
|
|
@ -7,39 +7,39 @@ from DerivedTypes import FunctionType
|
||||||
from raw_ostream import raw_ostream
|
from raw_ostream import raw_ostream
|
||||||
from AssemblyAnnotationWriter import AssemblyAnnotationWriter
|
from AssemblyAnnotationWriter import AssemblyAnnotationWriter
|
||||||
|
|
||||||
# class Module
|
@llvm.Class()
|
||||||
Module = llvm.Class()
|
class Module:
|
||||||
Module.include.add("llvm/Module.h")
|
_include_ = "llvm/Module.h"
|
||||||
|
# Enumerators
|
||||||
|
Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
||||||
|
PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
||||||
|
|
||||||
# Enumerators
|
# Constructors & Destructors
|
||||||
Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
new = Constructor(cast(str, StringRef), ref(LLVMContext))
|
||||||
PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
delete = Destructor()
|
||||||
|
|
||||||
# Constructors & Destructors
|
# Module Level Accessor
|
||||||
new = Module.new(StringRef.From(str), LLVMContext.Ref)
|
getModuleIdentifier = Method(cast(ConstStdString, str))
|
||||||
delete = Module.delete()
|
getDataLayout = Method(cast(ConstStdString, str))
|
||||||
|
getTargetTriple = Method(cast(ConstStdString, str))
|
||||||
|
getEndianness = Method(Endianness)
|
||||||
|
getPointerSize = Method(PointerSize)
|
||||||
|
getContext = Method(ref(LLVMContext))
|
||||||
|
getModuleInlineAsm = Method(cast(ConstStdString, str))
|
||||||
|
|
||||||
# Module Level Accessor
|
# Module Level Mutators
|
||||||
getModuleIdentifier = Module.method(ConstStdString.To(str))
|
setModuleIdentifier = Method(Void, cast(str, StringRef))
|
||||||
getDataLayout = Module.method(ConstStdString.To(str))
|
setDataLayout = Method(Void, cast(str, StringRef))
|
||||||
getTargetTriple = Module.method(ConstStdString.To(str))
|
setTargetTriple = Method(Void, cast(str, StringRef))
|
||||||
getEndianness = Module.method(Endianness)
|
setModuleInlineAsm = Method(Void, cast(str, StringRef))
|
||||||
getPointerSize = Module.method(PointerSize)
|
appendModuleInlineAsm = Method(Void, cast(str, StringRef))
|
||||||
getContext = Module.method(LLVMContext.Ref)
|
|
||||||
getModuleInlineAsm = Module.method(ConstStdString.To(str))
|
|
||||||
|
|
||||||
# Module Level Mutators
|
# Function Accessors
|
||||||
setModuleIdentifier = Module.method(Void, StringRef.From(str))
|
getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType))
|
||||||
setDataLayout = Module.method(Void, StringRef.From(str))
|
|
||||||
setTargetTriple = Module.method(Void, StringRef.From(str))
|
|
||||||
setModuleInlineAsm = Module.method(Void, StringRef.From(str))
|
|
||||||
appendModuleInlineAsm = Module.method(Void, StringRef.From(str))
|
|
||||||
|
|
||||||
# Function Accessors
|
# Utilities
|
||||||
getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer)
|
dump = Method(Void)
|
||||||
|
print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter))
|
||||||
|
print_.realname = 'print'
|
||||||
|
|
||||||
# Utilities
|
dropAllReferences = Method()
|
||||||
dump = Module.method(Void)
|
|
||||||
print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer)
|
|
||||||
print_.realname = 'print'
|
|
||||||
dropAllReferences = Module.method(Void)
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
|
|
||||||
SmallVector_Type = llvm.Class()
|
@llvm.Class()
|
||||||
delete = SmallVector_Type.delete()
|
class SmallVector_Type:
|
||||||
|
delete = Destructor()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
|
|
||||||
StringRef = llvm.Class()
|
@llvm.Class()
|
||||||
StringRef.include.add("llvm/ADT/StringRef.h")
|
class StringRef:
|
||||||
|
_include_ = "llvm/ADT/StringRef.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,93 +4,112 @@ from LLVMContext import LLVMContext
|
||||||
from raw_ostream import raw_ostream
|
from raw_ostream import raw_ostream
|
||||||
|
|
||||||
Type = llvm.Class()
|
Type = llvm.Class()
|
||||||
Type.include.add('llvm/Type.h')
|
IntegerType = llvm.Class(Type)
|
||||||
|
CompositeType = llvm.Class(Type)
|
||||||
|
SequentialType = llvm.Class(CompositeType)
|
||||||
|
PointerType = llvm.Class(SequentialType)
|
||||||
|
|
||||||
IntegerType = Type.Subclass()
|
@Type
|
||||||
CompositeType = Type.Subclass()
|
class Type:
|
||||||
SequentialType = CompositeType.Subclass()
|
_include_ = 'llvm/Type.h'
|
||||||
PointerType = SequentialType.Subclass()
|
|
||||||
|
|
||||||
getContext = Type.method(LLVMContext.Ref)
|
getContext = Method(ref(LLVMContext))
|
||||||
dump = Type.method(Void)
|
dump = Method()
|
||||||
print_ = Type.method(Void, raw_ostream.Ref)
|
print_ = Method(Void, ref(raw_ostream))
|
||||||
print_.realname = 'print'
|
print_.realname = 'print'
|
||||||
|
|
||||||
def type_checker():
|
def type_checker():
|
||||||
return Type.method(Bool.To(bool))
|
return Method(cast(Bool, bool))
|
||||||
|
|
||||||
isVoidTy = type_checker()
|
isVoidTy = type_checker()
|
||||||
isHalfTy = type_checker()
|
isHalfTy = type_checker()
|
||||||
isFloatTy = type_checker()
|
isFloatTy = type_checker()
|
||||||
isDoubleTy = type_checker()
|
isDoubleTy = type_checker()
|
||||||
isX86_FP80Ty = type_checker()
|
isX86_FP80Ty = type_checker()
|
||||||
isFP128Ty = type_checker()
|
isFP128Ty = type_checker()
|
||||||
isPPC_FP128Ty = type_checker()
|
isPPC_FP128Ty = type_checker()
|
||||||
isFloatingPointTy = type_checker()
|
isFloatingPointTy = type_checker()
|
||||||
isX86_MMXTy = type_checker()
|
isX86_MMXTy = type_checker()
|
||||||
isFPOrFPVectorTy = type_checker()
|
isFPOrFPVectorTy = type_checker()
|
||||||
isLabelTy = type_checker()
|
isLabelTy = type_checker()
|
||||||
isMetadataTy = type_checker()
|
isMetadataTy = type_checker()
|
||||||
isIntOrIntVectorTy = type_checker()
|
isIntOrIntVectorTy = type_checker()
|
||||||
isFunctionTy = type_checker()
|
isFunctionTy = type_checker()
|
||||||
isStructTy = type_checker()
|
isStructTy = type_checker()
|
||||||
isArrayTy = type_checker()
|
isArrayTy = type_checker()
|
||||||
isPointerTy = type_checker()
|
isPointerTy = type_checker()
|
||||||
isPtrOrPtrVectorTy = type_checker()
|
isPtrOrPtrVectorTy = type_checker()
|
||||||
isVectorTy = type_checker()
|
isVectorTy = type_checker()
|
||||||
isEmptyTy = type_checker()
|
isEmptyTy = type_checker()
|
||||||
isPrimitiveType = type_checker()
|
isPrimitiveType = type_checker()
|
||||||
isDerivedType = type_checker()
|
isDerivedType = type_checker()
|
||||||
isFirstClassType = type_checker()
|
isFirstClassType = type_checker()
|
||||||
isSingleValueType = type_checker()
|
isSingleValueType = type_checker()
|
||||||
isAggregateType = type_checker()
|
isAggregateType = type_checker()
|
||||||
isSized = type_checker()
|
isSized = type_checker()
|
||||||
|
|
||||||
isIntegerTy = Type.multimethod([Bool.To(bool)],
|
isIntegerTy = Method(cast(Bool, bool))
|
||||||
[Bool.To(bool), Unsigned.From(int)])
|
isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned))
|
||||||
|
|
||||||
|
|
||||||
def type_factory():
|
def type_factory():
|
||||||
return Type.staticmethod(Type.Pointer, LLVMContext.Ref)
|
return StaticMethod(ptr(Type), ref(LLVMContext))
|
||||||
|
|
||||||
getVoidTy = type_factory()
|
getVoidTy = type_factory()
|
||||||
getLabelTy = type_factory()
|
getLabelTy = type_factory()
|
||||||
getHalfTy = type_factory()
|
getHalfTy = type_factory()
|
||||||
getFloatTy = type_factory()
|
getFloatTy = type_factory()
|
||||||
getDoubleTy = type_factory()
|
getDoubleTy = type_factory()
|
||||||
getMetadataTy = type_factory()
|
getMetadataTy = type_factory()
|
||||||
getX86_FP80Ty = type_factory()
|
getX86_FP80Ty = type_factory()
|
||||||
getFP128Ty = type_factory()
|
getFP128Ty = type_factory()
|
||||||
getPPC_FP128Ty = type_factory()
|
getPPC_FP128Ty = type_factory()
|
||||||
getX86_MMXTy = type_factory()
|
getX86_MMXTy = type_factory()
|
||||||
|
|
||||||
getIntNTy = Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref, Unsigned.From(int))
|
getIntNTy = StaticMethod(ptr(IntegerType), ref(LLVMContext), cast(Unsigned, int))
|
||||||
|
|
||||||
def integer_factory():
|
def integer_factory():
|
||||||
return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref)
|
return StaticMethod(ptr(IntegerType), ref(LLVMContext))
|
||||||
|
|
||||||
getInt1Ty = integer_factory()
|
getInt1Ty = integer_factory()
|
||||||
getInt8Ty = integer_factory()
|
getInt8Ty = integer_factory()
|
||||||
getInt16Ty = integer_factory()
|
getInt16Ty = integer_factory()
|
||||||
getInt32Ty = integer_factory()
|
getInt32Ty = integer_factory()
|
||||||
getInt64Ty = integer_factory()
|
getInt64Ty = integer_factory()
|
||||||
|
|
||||||
def pointer_factory():
|
def pointer_factory():
|
||||||
return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref)
|
return StaticMethod(ptr(PointerType), ref(LLVMContext))
|
||||||
|
|
||||||
getHalfPtrTy = pointer_factory()
|
getHalfPtrTy = pointer_factory()
|
||||||
getFloatPtrTy = pointer_factory()
|
getFloatPtrTy = pointer_factory()
|
||||||
getDoublePtrTy = pointer_factory()
|
getDoublePtrTy = pointer_factory()
|
||||||
getX86_FP80PtrTy = pointer_factory()
|
getX86_FP80PtrTy = pointer_factory()
|
||||||
getFP128PtrTy = pointer_factory()
|
getFP128PtrTy = pointer_factory()
|
||||||
getPPC_FP128PtrTy = pointer_factory()
|
getPPC_FP128PtrTy = pointer_factory()
|
||||||
getX86_MMXPtrTy = pointer_factory()
|
getX86_MMXPtrTy = pointer_factory()
|
||||||
getInt1PtrTy = pointer_factory()
|
getInt1PtrTy = pointer_factory()
|
||||||
getInt8PtrTy = pointer_factory()
|
getInt8PtrTy = pointer_factory()
|
||||||
getInt16PtrTy = pointer_factory()
|
getInt16PtrTy = pointer_factory()
|
||||||
getInt32PtrTy = pointer_factory()
|
getInt32PtrTy = pointer_factory()
|
||||||
getInt64PtrTy = pointer_factory()
|
getInt64PtrTy = pointer_factory()
|
||||||
getIntNPtrTy = Type.staticmethod(PointerType.Pointer,
|
getIntNPtrTy = StaticMethod(ptr(PointerType),
|
||||||
LLVMContext.Ref, Unsigned.From(int))
|
ref(LLVMContext), cast(int, Unsigned))
|
||||||
|
|
||||||
|
|
||||||
|
@IntegerType
|
||||||
|
class IntegerType:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@CompositeType
|
||||||
|
class CompositeType:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@SequentialType
|
||||||
|
class SequentialType:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@PointerType
|
||||||
|
class PointerType:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,7 @@ from binding import *
|
||||||
from namespace import llvm
|
from namespace import llvm
|
||||||
from Value import Value
|
from Value import Value
|
||||||
|
|
||||||
User = Value.Subclass()
|
@llvm.Class(Value)
|
||||||
|
class User:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,23 @@ from AssemblyAnnotationWriter import AssemblyAnnotationWriter
|
||||||
from Type import Type
|
from Type import Type
|
||||||
from LLVMContext import LLVMContext
|
from LLVMContext import LLVMContext
|
||||||
from StringRef import StringRef
|
from StringRef import StringRef
|
||||||
#
|
|
||||||
Value = llvm.Class()
|
Value = llvm.Class()
|
||||||
|
|
||||||
dump = Value.method(Void)
|
@Value
|
||||||
|
class Value:
|
||||||
|
|
||||||
print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer)
|
dump = Method()
|
||||||
print_.realname = 'print'
|
|
||||||
|
|
||||||
getType = Value.method(Type.Pointer)
|
print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter))
|
||||||
getContext = Value.method(LLVMContext.Ref)
|
print_.realname = 'print'
|
||||||
|
|
||||||
hasName = Value.method(Bool.To(bool))
|
getType = Method(ptr(Type))
|
||||||
# skip getValueName, setValueName
|
getContext = Method(ref(LLVMContext))
|
||||||
getName = Value.method(StringRef.To(str))
|
|
||||||
setName = Value.method(Void, StringRef.From(str))
|
|
||||||
|
|
||||||
replaceAllUsesWith = Value.method(Void, Value.Pointer)
|
hasName = Method(cast(Bool, bool))
|
||||||
|
# skip getValueName, setValueName
|
||||||
|
getName = Method(cast(StringRef, str))
|
||||||
|
setName = Method(Void, cast(str, StringRef))
|
||||||
|
|
||||||
|
replaceAllUsesWith = Method(Void, ptr(Value))
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import Module
|
||||||
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
from binding import *
|
from binding import *
|
||||||
|
|
||||||
extra = Namespace('llvm_extra')
|
|
||||||
llvm = Namespace('llvm')
|
llvm = Namespace('llvm')
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,15 @@ from namespace import llvm
|
||||||
from LLVMContext import LLVMContext
|
from LLVMContext import LLVMContext
|
||||||
from StringRef import StringRef
|
from StringRef import StringRef
|
||||||
|
|
||||||
raw_ostream = llvm.Class()
|
@llvm.Class()
|
||||||
raw_ostream.include.add("llvm/Support/raw_ostream.h")
|
class raw_ostream:
|
||||||
delete = raw_ostream.delete()
|
_include_ = "llvm/Support/raw_ostream.h"
|
||||||
|
delete = Destructor()
|
||||||
|
|
||||||
|
@llvm.Class(raw_ostream)
|
||||||
|
class raw_svector_ostream:
|
||||||
|
_include_ = "llvm/Support/raw_os_ostream.h"
|
||||||
|
_base_ = raw_ostream
|
||||||
|
|
||||||
|
str = Method(cast(str, StringRef))
|
||||||
|
|
||||||
raw_svector_ostream = raw_ostream.Subclass()
|
|
||||||
raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h")
|
|
||||||
str = raw_svector_ostream.method(StringRef.To(str))
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import api
|
import api
|
||||||
|
import extra
|
||||||
import _capsule
|
import _capsule
|
||||||
api.capsule.set_debug(True)
|
api.capsule.set_debug(True)
|
||||||
context = api.getGlobalContext()
|
context = api.getGlobalContext()
|
||||||
|
|
@ -15,7 +16,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize
|
||||||
m.dump()
|
m.dump()
|
||||||
|
|
||||||
|
|
||||||
os = api.make_raw_ostream_for_printing()
|
os = extra.make_raw_ostream_for_printing()
|
||||||
m.print_(os, None)
|
m.print_(os, None)
|
||||||
print os.str()
|
print os.str()
|
||||||
|
|
||||||
|
|
@ -29,15 +30,15 @@ fnty = api.FunctionType.get(int1ty, False)
|
||||||
fnty.dump()
|
fnty.dump()
|
||||||
|
|
||||||
types = [int1ty, api.Type.getIntNTy(context, 21)]
|
types = [int1ty, api.Type.getIntNTy(context, 21)]
|
||||||
svt = api.make_small_vector_from_types(*types)
|
svt = extra.make_small_vector_from_types(*types)
|
||||||
fnty = api.FunctionType.get(int1ty, svt, False)
|
fnty = api.FunctionType.get(int1ty, svt, False)
|
||||||
|
|
||||||
os = api.make_raw_ostream_for_printing()
|
os = extra.make_raw_ostream_for_printing()
|
||||||
fnty.print_(os)
|
fnty.print_(os)
|
||||||
print os.str()
|
print os.str()
|
||||||
|
|
||||||
fn = m.getOrInsertFunction("foo", fnty)
|
fn = m.getOrInsertFunction("foo", fnty)
|
||||||
os = api.make_raw_ostream_for_printing()
|
os = extra.make_raw_ostream_for_printing()
|
||||||
fn.print_(os, None)
|
fn.print_(os, None)
|
||||||
print os.str()
|
print os.str()
|
||||||
assert fn.hasName()
|
assert fn.hasName()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
def indent_println(println):
|
|
||||||
def _println(s):
|
|
||||||
println("%s%s" % (' '* 4, s))
|
|
||||||
return _println
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue