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
|
||||
|
||||
PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef
|
||||
|
||||
PYMODS += LLVMContext AssemblyAnnotationWriter Module
|
||||
PYMODS += Value User Constant
|
||||
|
||||
all: _api.so _capsule.so
|
||||
|
||||
_api.so _capsule.so: api.cpp capsule.cpp
|
||||
$(PYTHON) setup.py build_ext --inplace
|
||||
|
||||
api.cpp api.py: src/*.py include/llvm_binding/*.h
|
||||
$(PYTHON) gen.py api src $(PYMODS)
|
||||
api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py
|
||||
$(PYTHON) gen.py api src
|
||||
|
||||
clean: cleantemp
|
||||
rm -f _api.so _capsule.so
|
||||
|
|
|
|||
|
|
@ -1,108 +1,352 @@
|
|||
import logging
|
||||
import re
|
||||
from utils import *
|
||||
import functools
|
||||
import codegen as cg
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
_rank = 0
|
||||
namespaces = {}
|
||||
|
||||
_py2capi_fmtmap = {
|
||||
str: 's#',
|
||||
}
|
||||
class Namespace(object):
|
||||
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):
|
||||
if name in _symbols:
|
||||
ct = 1
|
||||
orig = name
|
||||
while name in _symbols:
|
||||
name = '%s%d' % (orig, ct)
|
||||
ct += 1
|
||||
_symbols.add(name)
|
||||
return name
|
||||
@property
|
||||
def fullname(self):
|
||||
return self.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)
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
items = [var, '"%s"' % (''.join(typecodes))] + holders
|
||||
println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items))
|
||||
class Type(object):
|
||||
pass
|
||||
|
||||
# unwrap
|
||||
unwrapped = []
|
||||
for arg, val in zip(args, argvals):
|
||||
unwrapped.append(arg.unwrap(println, val))
|
||||
class BuiltinTypes(Type):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
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):
|
||||
def repl(m):
|
||||
s = m.group(0)
|
||||
if s in '<>*&':
|
||||
return ''
|
||||
elif s in ' ':
|
||||
return '_'
|
||||
elif s in '_':
|
||||
return '__'
|
||||
Void = BuiltinTypes('void')
|
||||
Unsigned = BuiltinTypes('unsigned')
|
||||
Bool = BuiltinTypes('bool')
|
||||
ConstStdString = BuiltinTypes('const std::string')
|
||||
|
||||
class Class(Type):
|
||||
format = 'O'
|
||||
|
||||
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:
|
||||
assert False
|
||||
name = _re_mangle_pattern.sub(repl, name)
|
||||
return name.replace('::', '_')
|
||||
return self.fullname
|
||||
|
||||
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
|
||||
@property
|
||||
def fullname(self):
|
||||
try:
|
||||
name = self.realname
|
||||
except AttributeError:
|
||||
name = self.name
|
||||
return '::'.join([self.ns.fullname, name])
|
||||
|
||||
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):
|
||||
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
|
||||
class Enum(object):
|
||||
def __init__(self, *value_names):
|
||||
self.parent = None
|
||||
self.value_names = value_names
|
||||
|
||||
@property
|
||||
def fullname(self):
|
||||
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):
|
||||
println('return %(var)s;' % locals())
|
||||
class StaticMethod(Method):
|
||||
|
||||
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):
|
||||
println('Py_RETURN_NONE;')
|
||||
class Function(Method):
|
||||
_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):
|
||||
println('if (!%(var)s) return NULL;' % locals())
|
||||
class Destructor(Method):
|
||||
_kind_ = 'dtor'
|
||||
|
||||
|
||||
class Binding(object):
|
||||
__rank_global = 0
|
||||
def __init__(self):
|
||||
self.rank = Binding.__rank_global
|
||||
Binding.__rank_global += 1
|
||||
self.include = set()
|
||||
super(Destructor, self).__init__()
|
||||
|
||||
def compile(self, name, println):
|
||||
raise NotImplementedError(type(self))
|
||||
def compile_cpp_body(self, writer, retty, argtys):
|
||||
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 __init__(self, elem):
|
||||
self.element = elem
|
||||
def compile_py(self, writer):
|
||||
func = '.'.join([self.parent.name, self.name])
|
||||
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
|
||||
def fullname(self):
|
||||
|
|
@ -112,503 +356,79 @@ class Ref(object):
|
|||
def capsule_name(self):
|
||||
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
|
||||
def format(self):
|
||||
return 'O'
|
||||
return self.element.format
|
||||
|
||||
def unwrap(self, println, var):
|
||||
ptr = self.element.unwrap(println, var)
|
||||
return declare(println, self.fullname, '*%s' % ptr)
|
||||
def wrap(self, writer, val):
|
||||
p = writer.declare(ptr(self.element).fullname, '&%s' % val)
|
||||
return writer.pycapsule_new(p, self.capsule_name, self.element.fullname)
|
||||
|
||||
def wrap(self, println, var):
|
||||
return self.element.wrap(println, self.as_pointer(println, var))
|
||||
def unwrap(self, writer, val):
|
||||
p = self.element.unwrap(writer, val)
|
||||
return writer.declare(self.fullname, '*%s' % p)
|
||||
|
||||
|
||||
class Pointer(object):
|
||||
def __init__(self, elem):
|
||||
self.element = elem
|
||||
class ptr(Type):
|
||||
def __init__(self, element):
|
||||
assert isinstance(element, Class)
|
||||
self.element = element
|
||||
|
||||
@property
|
||||
def fullname(self):
|
||||
return '%s*' % self.element.fullname
|
||||
|
||||
@property
|
||||
def capsule_name(self):
|
||||
return self.element.capsule_name
|
||||
|
||||
@property
|
||||
def pointer(self):
|
||||
return self.element.pointer
|
||||
return '%s*' % self.element
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
return 'O'
|
||||
return self.element.format
|
||||
|
||||
def unwrap(self, println, var):
|
||||
ret = declare(println, self.fullname)
|
||||
println2 = indent_println(println)
|
||||
println('if (%(var)s == Py_None) {' % locals())
|
||||
println2('%(ret)s = NULL;' % locals())
|
||||
println('} else {')
|
||||
ptr = self.element.unwrap(println2, var)
|
||||
println2('%(ret)s = %(ptr)s;' % locals())
|
||||
println('}')
|
||||
def unwrap(self, writer, val):
|
||||
ret = writer.declare(self.fullname, 'NULL')
|
||||
with writer.block('if (%(val)s != Py_None)' % locals()):
|
||||
val = self.element.unwrap(writer, val)
|
||||
writer.println('%(ret)s = %(val)s;' % locals())
|
||||
return ret
|
||||
|
||||
def wrap(self, println, var):
|
||||
return self.element.wrap(println, var)
|
||||
def wrap(self, writer, val):
|
||||
return writer.pycapsule_new(val, self.element.capsule_name,
|
||||
self.element.fullname)
|
||||
|
||||
|
||||
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
|
||||
class cast(Type):
|
||||
format = 'O'
|
||||
|
||||
def unwrap(self, println, var):
|
||||
return var
|
||||
|
||||
PyObject = PyObjectImpl()
|
||||
|
||||
class Unwrapper(object):
|
||||
def __init__(self, cls, pytype):
|
||||
self.cls = cls
|
||||
self.pytype = pytype
|
||||
def __init__(self, original, target):
|
||||
self.original = original
|
||||
self.target = target
|
||||
|
||||
@property
|
||||
def fullname(self):
|
||||
return str(self.pytype)
|
||||
return self.binding_type.fullname
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
return 'O'
|
||||
|
||||
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;')
|
||||
def python_type(self):
|
||||
if not isinstance(self.target, Type):
|
||||
return self.target
|
||||
else:
|
||||
println('default:')
|
||||
println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' %
|
||||
v)
|
||||
println2('return NULL;')
|
||||
println('}')
|
||||
return self.original
|
||||
|
||||
@property
|
||||
def binding_type(self):
|
||||
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
|
||||
|
||||
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,26 +1,23 @@
|
|||
import sys, logging
|
||||
import sys
|
||||
from binding import *
|
||||
from utils import *
|
||||
from cStringIO import StringIO
|
||||
import codegen
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
extension_entry = '''
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if (PY_MAJOR_VERSION >= 3)
|
||||
|
||||
|
||||
PyObject *
|
||||
PyInit_%(module)s(void)
|
||||
{
|
||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||
if (module) {
|
||||
if (populate_submodules(module, submodules))
|
||||
return module;
|
||||
}
|
||||
return NULL;
|
||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||
if (module) {
|
||||
if (populate_submodules(module, submodules))
|
||||
return module;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
@ -28,10 +25,10 @@ PyInit_%(module)s(void)
|
|||
PyMODINIT_FUNC
|
||||
init%(module)s(void)
|
||||
{
|
||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||
if (module) {
|
||||
populate_submodules(module, submodules);
|
||||
}
|
||||
PyObject *module = create_python_module("%(module)s", %(methtable)s);
|
||||
if (module) {
|
||||
populate_submodules(module, submodules);
|
||||
}
|
||||
}
|
||||
#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):
|
||||
includes = [
|
||||
|
|
@ -216,38 +47,96 @@ def populate_headers(println):
|
|||
]
|
||||
for inc in includes:
|
||||
println('#include "%s"' % inc)
|
||||
println()
|
||||
|
||||
def wrap_println(f):
|
||||
def println(s):
|
||||
f.write(s)
|
||||
f.write('\n')
|
||||
|
||||
def wrap_println_from_file(file):
|
||||
def println(s=''):
|
||||
file.write(s)
|
||||
file.write('\n')
|
||||
return println
|
||||
|
||||
if __name__ == '__main__':
|
||||
def main():
|
||||
outputfilename = sys.argv[1]
|
||||
srcdir = sys.argv[2]
|
||||
modnames = sys.argv[3:]
|
||||
entry_modname = sys.argv[2]
|
||||
|
||||
modules = []
|
||||
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)
|
||||
entry_module = __import__(entry_modname)
|
||||
|
||||
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:
|
||||
context.add_module(mod)
|
||||
context.materialize()
|
||||
with open('%s.cpp' % outputfilename, 'w') as cppfile:
|
||||
println = wrap_println_from_file(cppfile)
|
||||
|
||||
with open('%s.cpp' % outputfilename, 'w') as outfile:
|
||||
println = wrap_println(outfile)
|
||||
# extra headers
|
||||
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){
|
||||
return PyString_FromStringAndSize(str.c_str(), str.size());
|
||||
}
|
||||
//
|
||||
//static
|
||||
//PyObject* py_str_from(const llvm::StringRef *str){
|
||||
// return py_str_from(str->str());
|
||||
//}
|
||||
|
||||
static
|
||||
PyObject* py_bool_from(bool val){
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from binding import *
|
||||
from namespace import llvm
|
||||
|
||||
AssemblyAnnotationWriter = llvm.Class()
|
||||
AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h")
|
||||
@llvm.Class()
|
||||
class AssemblyAnnotationWriter:
|
||||
_include_ = "llvm/Assembly/AssemblyAnnotationWriter.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -2,4 +2,6 @@ from binding import *
|
|||
from namespace import llvm
|
||||
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 SmallVector import SmallVector_Type
|
||||
|
||||
FunctionType = Type.Subclass()
|
||||
FunctionType.include.add('llvm/DerivedTypes.h')
|
||||
FunctionType = llvm.Class(Type)
|
||||
|
||||
_get_signatures = [(FunctionType.Pointer,
|
||||
Type.Pointer, Bool.From(bool)),
|
||||
(FunctionType.Pointer,
|
||||
Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))]
|
||||
@FunctionType
|
||||
class FunctionType:
|
||||
_include_ = 'llvm/DerivedTypes.h'
|
||||
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 namespace import llvm
|
||||
|
||||
LLVMContext = llvm.Class()
|
||||
LLVMContext.include.add("llvm/LLVMContext.h")
|
||||
|
||||
getGlobalContext = llvm.Function(LLVMContext.Ref)
|
||||
@llvm.Class()
|
||||
class LLVMContext:
|
||||
_include_ = "llvm/LLVMContext.h"
|
||||
|
||||
llvm.Function('getGlobalContext', ref(LLVMContext))
|
||||
|
|
|
|||
|
|
@ -7,39 +7,39 @@ from DerivedTypes import FunctionType
|
|||
from raw_ostream import raw_ostream
|
||||
from AssemblyAnnotationWriter import AssemblyAnnotationWriter
|
||||
|
||||
# class Module
|
||||
Module = llvm.Class()
|
||||
Module.include.add("llvm/Module.h")
|
||||
@llvm.Class()
|
||||
class Module:
|
||||
_include_ = "llvm/Module.h"
|
||||
# Enumerators
|
||||
Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
||||
PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
||||
|
||||
# Enumerators
|
||||
Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian')
|
||||
PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64')
|
||||
# Constructors & Destructors
|
||||
new = Constructor(cast(str, StringRef), ref(LLVMContext))
|
||||
delete = Destructor()
|
||||
|
||||
# Constructors & Destructors
|
||||
new = Module.new(StringRef.From(str), LLVMContext.Ref)
|
||||
delete = Module.delete()
|
||||
# Module Level Accessor
|
||||
getModuleIdentifier = Method(cast(ConstStdString, str))
|
||||
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
|
||||
getModuleIdentifier = Module.method(ConstStdString.To(str))
|
||||
getDataLayout = Module.method(ConstStdString.To(str))
|
||||
getTargetTriple = Module.method(ConstStdString.To(str))
|
||||
getEndianness = Module.method(Endianness)
|
||||
getPointerSize = Module.method(PointerSize)
|
||||
getContext = Module.method(LLVMContext.Ref)
|
||||
getModuleInlineAsm = Module.method(ConstStdString.To(str))
|
||||
# Module Level Mutators
|
||||
setModuleIdentifier = Method(Void, cast(str, StringRef))
|
||||
setDataLayout = Method(Void, cast(str, StringRef))
|
||||
setTargetTriple = Method(Void, cast(str, StringRef))
|
||||
setModuleInlineAsm = Method(Void, cast(str, StringRef))
|
||||
appendModuleInlineAsm = Method(Void, cast(str, StringRef))
|
||||
|
||||
# Module Level Mutators
|
||||
setModuleIdentifier = Module.method(Void, StringRef.From(str))
|
||||
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
|
||||
getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType))
|
||||
|
||||
# Function Accessors
|
||||
getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer)
|
||||
# Utilities
|
||||
dump = Method(Void)
|
||||
print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter))
|
||||
print_.realname = 'print'
|
||||
|
||||
# Utilities
|
||||
dump = Module.method(Void)
|
||||
print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer)
|
||||
print_.realname = 'print'
|
||||
dropAllReferences = Module.method(Void)
|
||||
dropAllReferences = Method()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from binding import *
|
||||
from namespace import llvm
|
||||
|
||||
SmallVector_Type = llvm.Class()
|
||||
delete = SmallVector_Type.delete()
|
||||
@llvm.Class()
|
||||
class SmallVector_Type:
|
||||
delete = Destructor()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from binding import *
|
||||
from namespace import llvm
|
||||
|
||||
StringRef = llvm.Class()
|
||||
StringRef.include.add("llvm/ADT/StringRef.h")
|
||||
@llvm.Class()
|
||||
class StringRef:
|
||||
_include_ = "llvm/ADT/StringRef.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -4,93 +4,112 @@ from LLVMContext import LLVMContext
|
|||
from raw_ostream import raw_ostream
|
||||
|
||||
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()
|
||||
CompositeType = Type.Subclass()
|
||||
SequentialType = CompositeType.Subclass()
|
||||
PointerType = SequentialType.Subclass()
|
||||
@Type
|
||||
class Type:
|
||||
_include_ = 'llvm/Type.h'
|
||||
|
||||
getContext = Type.method(LLVMContext.Ref)
|
||||
dump = Type.method(Void)
|
||||
print_ = Type.method(Void, raw_ostream.Ref)
|
||||
print_.realname = 'print'
|
||||
getContext = Method(ref(LLVMContext))
|
||||
dump = Method()
|
||||
print_ = Method(Void, ref(raw_ostream))
|
||||
print_.realname = 'print'
|
||||
|
||||
def type_checker():
|
||||
return Type.method(Bool.To(bool))
|
||||
def type_checker():
|
||||
return Method(cast(Bool, bool))
|
||||
|
||||
isVoidTy = type_checker()
|
||||
isHalfTy = type_checker()
|
||||
isFloatTy = type_checker()
|
||||
isDoubleTy = type_checker()
|
||||
isX86_FP80Ty = type_checker()
|
||||
isFP128Ty = type_checker()
|
||||
isPPC_FP128Ty = type_checker()
|
||||
isFloatingPointTy = type_checker()
|
||||
isX86_MMXTy = type_checker()
|
||||
isFPOrFPVectorTy = type_checker()
|
||||
isLabelTy = type_checker()
|
||||
isMetadataTy = type_checker()
|
||||
isIntOrIntVectorTy = type_checker()
|
||||
isFunctionTy = type_checker()
|
||||
isStructTy = type_checker()
|
||||
isArrayTy = type_checker()
|
||||
isPointerTy = type_checker()
|
||||
isPtrOrPtrVectorTy = type_checker()
|
||||
isVectorTy = type_checker()
|
||||
isEmptyTy = type_checker()
|
||||
isPrimitiveType = type_checker()
|
||||
isDerivedType = type_checker()
|
||||
isFirstClassType = type_checker()
|
||||
isSingleValueType = type_checker()
|
||||
isAggregateType = type_checker()
|
||||
isSized = type_checker()
|
||||
isVoidTy = type_checker()
|
||||
isHalfTy = type_checker()
|
||||
isFloatTy = type_checker()
|
||||
isDoubleTy = type_checker()
|
||||
isX86_FP80Ty = type_checker()
|
||||
isFP128Ty = type_checker()
|
||||
isPPC_FP128Ty = type_checker()
|
||||
isFloatingPointTy = type_checker()
|
||||
isX86_MMXTy = type_checker()
|
||||
isFPOrFPVectorTy = type_checker()
|
||||
isLabelTy = type_checker()
|
||||
isMetadataTy = type_checker()
|
||||
isIntOrIntVectorTy = type_checker()
|
||||
isFunctionTy = type_checker()
|
||||
isStructTy = type_checker()
|
||||
isArrayTy = type_checker()
|
||||
isPointerTy = type_checker()
|
||||
isPtrOrPtrVectorTy = type_checker()
|
||||
isVectorTy = type_checker()
|
||||
isEmptyTy = type_checker()
|
||||
isPrimitiveType = type_checker()
|
||||
isDerivedType = type_checker()
|
||||
isFirstClassType = type_checker()
|
||||
isSingleValueType = type_checker()
|
||||
isAggregateType = type_checker()
|
||||
isSized = type_checker()
|
||||
|
||||
isIntegerTy = Type.multimethod([Bool.To(bool)],
|
||||
[Bool.To(bool), Unsigned.From(int)])
|
||||
isIntegerTy = Method(cast(Bool, bool))
|
||||
isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned))
|
||||
|
||||
|
||||
def type_factory():
|
||||
return Type.staticmethod(Type.Pointer, LLVMContext.Ref)
|
||||
def type_factory():
|
||||
return StaticMethod(ptr(Type), ref(LLVMContext))
|
||||
|
||||
getVoidTy = type_factory()
|
||||
getLabelTy = type_factory()
|
||||
getHalfTy = type_factory()
|
||||
getFloatTy = type_factory()
|
||||
getDoubleTy = type_factory()
|
||||
getMetadataTy = type_factory()
|
||||
getX86_FP80Ty = type_factory()
|
||||
getFP128Ty = type_factory()
|
||||
getPPC_FP128Ty = type_factory()
|
||||
getX86_MMXTy = type_factory()
|
||||
getVoidTy = type_factory()
|
||||
getLabelTy = type_factory()
|
||||
getHalfTy = type_factory()
|
||||
getFloatTy = type_factory()
|
||||
getDoubleTy = type_factory()
|
||||
getMetadataTy = type_factory()
|
||||
getX86_FP80Ty = type_factory()
|
||||
getFP128Ty = type_factory()
|
||||
getPPC_FP128Ty = 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():
|
||||
return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref)
|
||||
def integer_factory():
|
||||
return StaticMethod(ptr(IntegerType), ref(LLVMContext))
|
||||
|
||||
getInt1Ty = integer_factory()
|
||||
getInt8Ty = integer_factory()
|
||||
getInt16Ty = integer_factory()
|
||||
getInt32Ty = integer_factory()
|
||||
getInt64Ty = integer_factory()
|
||||
getInt1Ty = integer_factory()
|
||||
getInt8Ty = integer_factory()
|
||||
getInt16Ty = integer_factory()
|
||||
getInt32Ty = integer_factory()
|
||||
getInt64Ty = integer_factory()
|
||||
|
||||
def pointer_factory():
|
||||
return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref)
|
||||
def pointer_factory():
|
||||
return StaticMethod(ptr(PointerType), ref(LLVMContext))
|
||||
|
||||
getHalfPtrTy = pointer_factory()
|
||||
getFloatPtrTy = pointer_factory()
|
||||
getDoublePtrTy = pointer_factory()
|
||||
getX86_FP80PtrTy = pointer_factory()
|
||||
getFP128PtrTy = pointer_factory()
|
||||
getPPC_FP128PtrTy = pointer_factory()
|
||||
getX86_MMXPtrTy = pointer_factory()
|
||||
getInt1PtrTy = pointer_factory()
|
||||
getInt8PtrTy = pointer_factory()
|
||||
getInt16PtrTy = pointer_factory()
|
||||
getInt32PtrTy = pointer_factory()
|
||||
getInt64PtrTy = pointer_factory()
|
||||
getIntNPtrTy = Type.staticmethod(PointerType.Pointer,
|
||||
LLVMContext.Ref, Unsigned.From(int))
|
||||
getHalfPtrTy = pointer_factory()
|
||||
getFloatPtrTy = pointer_factory()
|
||||
getDoublePtrTy = pointer_factory()
|
||||
getX86_FP80PtrTy = pointer_factory()
|
||||
getFP128PtrTy = pointer_factory()
|
||||
getPPC_FP128PtrTy = pointer_factory()
|
||||
getX86_MMXPtrTy = pointer_factory()
|
||||
getInt1PtrTy = pointer_factory()
|
||||
getInt8PtrTy = pointer_factory()
|
||||
getInt16PtrTy = pointer_factory()
|
||||
getInt32PtrTy = pointer_factory()
|
||||
getInt64PtrTy = pointer_factory()
|
||||
getIntNPtrTy = StaticMethod(ptr(PointerType),
|
||||
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 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 LLVMContext import LLVMContext
|
||||
from StringRef import StringRef
|
||||
#
|
||||
|
||||
Value = llvm.Class()
|
||||
|
||||
dump = Value.method(Void)
|
||||
@Value
|
||||
class Value:
|
||||
|
||||
print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer)
|
||||
print_.realname = 'print'
|
||||
dump = Method()
|
||||
|
||||
getType = Value.method(Type.Pointer)
|
||||
getContext = Value.method(LLVMContext.Ref)
|
||||
print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter))
|
||||
print_.realname = 'print'
|
||||
|
||||
hasName = Value.method(Bool.To(bool))
|
||||
# skip getValueName, setValueName
|
||||
getName = Value.method(StringRef.To(str))
|
||||
setName = Value.method(Void, StringRef.From(str))
|
||||
getType = Method(ptr(Type))
|
||||
getContext = Method(ref(LLVMContext))
|
||||
|
||||
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 *
|
||||
|
||||
extra = Namespace('llvm_extra')
|
||||
llvm = Namespace('llvm')
|
||||
|
|
|
|||
|
|
@ -3,10 +3,15 @@ from namespace import llvm
|
|||
from LLVMContext import LLVMContext
|
||||
from StringRef import StringRef
|
||||
|
||||
raw_ostream = llvm.Class()
|
||||
raw_ostream.include.add("llvm/Support/raw_ostream.h")
|
||||
delete = raw_ostream.delete()
|
||||
@llvm.Class()
|
||||
class raw_ostream:
|
||||
_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 extra
|
||||
import _capsule
|
||||
api.capsule.set_debug(True)
|
||||
context = api.getGlobalContext()
|
||||
|
|
@ -15,7 +16,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize
|
|||
m.dump()
|
||||
|
||||
|
||||
os = api.make_raw_ostream_for_printing()
|
||||
os = extra.make_raw_ostream_for_printing()
|
||||
m.print_(os, None)
|
||||
print os.str()
|
||||
|
||||
|
|
@ -29,15 +30,15 @@ fnty = api.FunctionType.get(int1ty, False)
|
|||
fnty.dump()
|
||||
|
||||
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)
|
||||
|
||||
os = api.make_raw_ostream_for_printing()
|
||||
os = extra.make_raw_ostream_for_printing()
|
||||
fnty.print_(os)
|
||||
print os.str()
|
||||
|
||||
fn = m.getOrInsertFunction("foo", fnty)
|
||||
os = api.make_raw_ostream_for_printing()
|
||||
os = extra.make_raw_ostream_for_printing()
|
||||
fn.print_(os, None)
|
||||
print os.str()
|
||||
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