Eolian: WIP
This commit is contained in:
parent
8d116e2822
commit
6b45d3429d
|
@ -17,6 +17,11 @@
|
|||
|
||||
from efl.eina cimport Eina_Bool
|
||||
|
||||
cdef extern from "*":
|
||||
struct CFILE "__FILE__"
|
||||
struct CLINE "__LINE__"
|
||||
struct CFUNC "__FUNCTION__"
|
||||
|
||||
cdef extern from "Eo.h":
|
||||
####################################################################
|
||||
# Structures
|
||||
|
@ -85,3 +90,6 @@ cdef extern from "Eo.h":
|
|||
|
||||
void eo_event_callback_add(const Eo_Event_Description *desc, Eo_Event_Cb cb, const void *data)
|
||||
void eo_event_callback_del(const Eo_Event_Description *desc, Eo_Event_Cb cb, const void *data)
|
||||
|
||||
Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line)
|
||||
void _eo_do_end(const Eo **ojb)
|
||||
|
|
|
@ -2,6 +2,7 @@ import logging
|
|||
log = logging.getLogger("efl.eolian.conv")
|
||||
|
||||
import re
|
||||
import keyword
|
||||
|
||||
from efl import eolian
|
||||
|
||||
|
@ -20,12 +21,37 @@ docstring_replacements = (
|
|||
)
|
||||
|
||||
builtin_types = ( # automatically converted by cython
|
||||
"byte",
|
||||
"ubyte",
|
||||
#"char",
|
||||
"short",
|
||||
"ushort",
|
||||
#"char",
|
||||
"int",
|
||||
"uint",
|
||||
"long",
|
||||
"ulong",
|
||||
"llong",
|
||||
"ullong",
|
||||
"int8",
|
||||
"uint8",
|
||||
"int16",
|
||||
"uint16",
|
||||
"int32",
|
||||
"uint32",
|
||||
"int64",
|
||||
"uint64",
|
||||
"int128",
|
||||
"uint128",
|
||||
"size",
|
||||
"ssize",
|
||||
"intptr",
|
||||
"uintptr",
|
||||
"ptrdiff",
|
||||
#"time",
|
||||
"float",
|
||||
"double",
|
||||
#"bool",
|
||||
#"void",
|
||||
"Evas_Coord",
|
||||
"Evas_Real"
|
||||
)
|
||||
|
@ -38,8 +64,8 @@ mapping_in = {
|
|||
# c_type: pyx_type
|
||||
"bool": "bint",
|
||||
"char": "",
|
||||
"Evas_Object *": "_Eo_Base",
|
||||
"Eo *": "_Eo_Base",
|
||||
"Evas_Object": "_Eo_Base",
|
||||
"Eo": "_Eo_Base",
|
||||
}
|
||||
|
||||
conversions_in = {
|
||||
|
@ -69,6 +95,10 @@ conversions_out = {
|
|||
}
|
||||
|
||||
|
||||
class EolianTypeError(TypeError):
|
||||
pass
|
||||
|
||||
|
||||
def conv_cls_name(name):
|
||||
s = name.split("_")
|
||||
if len(s) > 1:
|
||||
|
@ -83,54 +113,62 @@ def remove_type_prefixes(ctype):
|
|||
return ctype
|
||||
|
||||
|
||||
def convert_in_param(tp, name, is_nonull=None):
|
||||
def convert_in_param(tp, param_name, is_nonull=None):
|
||||
c_type = tp.c_type
|
||||
if tp.type == eolian.TypeType.POINTER:
|
||||
tp = tp.base_type
|
||||
if tp.type == eolian.TypeType.CLASS:
|
||||
return None, c_type, "{0}.obj".format(tp.name)
|
||||
return None, "Eo", "{0}.obj".format(param_name)
|
||||
|
||||
key = tp.name if tp.name else c_type
|
||||
|
||||
if key in builtin_types:
|
||||
return "", "", key
|
||||
return "", c_type, param_name
|
||||
|
||||
if not key in mapping_in:
|
||||
raise EolianTypeError("Unknown IN type: %s" % (key))
|
||||
|
||||
conv_expr = conversions_in.get(key)
|
||||
if conv_expr is not None:
|
||||
conv_expr = conv_expr.format(name)
|
||||
|
||||
if not key in mapping_in:
|
||||
raise TypeError("Unknown IN type: %s" % (key))
|
||||
conv_expr = conv_expr.format(param_name)
|
||||
|
||||
conv_t = mapping_in[key]
|
||||
#if conv_t is None:
|
||||
#conv_t = ""
|
||||
|
||||
if not is_nonull:
|
||||
key = "<{0}>{1} if {1} is not None else NULL".format(c_type, name)
|
||||
key = "<{0}>{1} if {1} is not None else NULL".format(c_type, param_name)
|
||||
|
||||
return conv_expr, conv_t, key
|
||||
if keyword.iskeyword(param_name):
|
||||
param_name += "_"
|
||||
|
||||
return conv_expr, conv_t, param_name
|
||||
|
||||
|
||||
def convert_out_param(tp, name):
|
||||
def convert_out_param(tp, param_name):
|
||||
if tp.type == eolian.TypeType.POINTER:
|
||||
tp = tp.base_type
|
||||
if tp.type == eolian.TypeType.CLASS:
|
||||
# TODO: set obj
|
||||
return tp.c_type, name
|
||||
return tp.c_type, param_name
|
||||
|
||||
key = tp.name if tp.name else tp.c_type
|
||||
|
||||
if key in builtin_types:
|
||||
return tp.c_type, name
|
||||
return tp.c_type, param_name
|
||||
|
||||
if not key in mapping_out:
|
||||
raise TypeError("Unknown OUT type: %s" % (key))
|
||||
raise EolianTypeError("Unknown OUT type: %s" % (key))
|
||||
|
||||
conv = conversions_out.get(key)
|
||||
|
||||
name = conv.format(name)
|
||||
return tp.c_type, name
|
||||
if conv:
|
||||
param_name = conv.format(param_name)
|
||||
|
||||
if keyword.iskeyword(param_name):
|
||||
param_name += "_"
|
||||
|
||||
return tp.c_type, param_name
|
||||
|
||||
|
||||
def conv_type_ret(tp):
|
||||
|
@ -145,7 +183,7 @@ def conv_type_ret(tp):
|
|||
|
||||
py_t = mapping_out.get(key)
|
||||
if py_t is None:
|
||||
raise TypeError("Unknown RET type: %s" % (key))
|
||||
raise EolianTypeError("Unknown RET type: %s" % (key))
|
||||
|
||||
py_ret_type = py_t[0]
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ eolian.init()
|
|||
|
||||
|
||||
from converters import convert_in_param, convert_out_param, conv_type_ret, \
|
||||
conv_cls_name
|
||||
conv_cls_name, EolianTypeError
|
||||
|
||||
|
||||
|
||||
class Generator(object):
|
||||
|
@ -149,9 +150,8 @@ class PyxGenerator(Generator):
|
|||
self.write("%s %s" % (t, ", ".join(names)))
|
||||
self.dedent()
|
||||
|
||||
def c_call_write(self, c_name, c_params, ret_type=None, returns=None):
|
||||
def c_call_write(self, c_name, c_params, ret_type=None):
|
||||
# TODO: Eina_Bool ret value from do_start, useful?
|
||||
#self.write("_eo_do_start(self.obj, NULL, EINA_FALSE, eina_main_loop_is(), NULL, NULL, 0)")
|
||||
self.write("_eo_do_start(self.obj, NULL, EINA_FALSE, CFILE, CFUNC, CLINE)")
|
||||
|
||||
c_call = ""
|
||||
|
@ -171,7 +171,7 @@ class PyxGenerator(Generator):
|
|||
self.write(")")
|
||||
self.dedent()
|
||||
|
||||
#self.write("_eo_do_end(self.obj)")
|
||||
self.write("_eo_do_end(self.obj)")
|
||||
|
||||
|
||||
class Function(object):
|
||||
|
@ -207,7 +207,6 @@ class Function(object):
|
|||
|
||||
self.c_ret_type = ret_type.c_type if ret_type.type != eolian.TypeType.UNKNOWN else "void"
|
||||
|
||||
|
||||
def cdef_generate(self, gen):
|
||||
func = self.func
|
||||
ftypes = eolian.FunctionType
|
||||
|
@ -233,7 +232,7 @@ class Function(object):
|
|||
header_params = []
|
||||
c_call_params = []
|
||||
return_params = []
|
||||
conv_params = []
|
||||
expand_params = []
|
||||
conv_in_exps = []
|
||||
|
||||
out_cdefs = []
|
||||
|
@ -261,8 +260,9 @@ class Function(object):
|
|||
header_params.append((c_type, p.name))
|
||||
c_call_params.append(name)
|
||||
elif di == eolian.ParameterDir.OUT:
|
||||
out_cdefs.append((c_type, "&"+p.name))
|
||||
out_cdefs.append((c_type, p.name))
|
||||
c_type, name = convert_out_param(p.type, p.name)
|
||||
c_call_params.append("&" + name)
|
||||
return_params.append((p.type, name))
|
||||
elif di == eolian.ParameterDir.INOUT:
|
||||
conv_expr, c_type, name = convert_in_param(p.type, p.name, p.is_nonull)
|
||||
|
@ -276,14 +276,14 @@ class Function(object):
|
|||
if (func.type == ftypes.PROP_SET or func.type == ftypes.PROPERTY) and not self.isget:
|
||||
py_name = "__set__"
|
||||
c_name = "_".join((c_name, "set"))
|
||||
conv_params = []
|
||||
expand_params = []
|
||||
|
||||
for p in list(func.property_values) + list(func.property_keys):
|
||||
conv_expr, c_type, name = convert_in_param(p.type, p.name, p.is_nonull)
|
||||
|
||||
conv_in_exps.append(conv_expr)
|
||||
conv_params.append(p.name)
|
||||
c_call_params.append(name)
|
||||
expand_params.append(p.name)
|
||||
c_call_params.append(p.name)
|
||||
|
||||
header_params = (("", "value"),)
|
||||
ret_type = func.return_type_get(eolian.FunctionType.PROP_SET)
|
||||
|
@ -309,9 +309,9 @@ class Function(object):
|
|||
gen.method_header_write(py_name, header_params)
|
||||
gen.indent()
|
||||
|
||||
if conv_params:
|
||||
conv_params = ", ".join(conv_params)
|
||||
gen.write("%s = value" % (conv_params))
|
||||
if expand_params:
|
||||
expand_params = ", ".join(expand_params)
|
||||
gen.write("%s = value" % (expand_params))
|
||||
|
||||
for e in conv_in_exps:
|
||||
if e:
|
||||
|
@ -324,7 +324,7 @@ class Function(object):
|
|||
else:
|
||||
ret_type2 = None
|
||||
|
||||
gen.c_call_write(c_name, c_call_params, ret_type2, return_params)
|
||||
gen.c_call_write(c_name, c_call_params, ret_type2)
|
||||
|
||||
if return_params:
|
||||
rparams = []
|
||||
|
@ -334,7 +334,12 @@ class Function(object):
|
|||
gen.write("return %s" % (", ".join([r[1] for r in rparams])))
|
||||
elif ret_type.type != eolian.TypeType.UNKNOWN:
|
||||
ret = self.RET_PARAM
|
||||
ret_type = convert_out_param(ret_type, ret)
|
||||
try:
|
||||
ret_type = convert_out_param(ret_type, ret)
|
||||
except Exception:
|
||||
gen.write("# FIXME: Unknown return type")
|
||||
gen.dedent()
|
||||
raise
|
||||
gen.write("return %s" % (ret))
|
||||
|
||||
gen.dedent()
|
||||
|
@ -387,10 +392,15 @@ class Property(object):
|
|||
|
||||
gen.indent()
|
||||
|
||||
self.getter.generate(gen)
|
||||
self.setter.generate(gen)
|
||||
|
||||
gen.dedent()
|
||||
try:
|
||||
self.getter.generate(gen)
|
||||
self.setter.generate(gen)
|
||||
except Exception:
|
||||
gen.write("pass")
|
||||
gen.write()
|
||||
raise
|
||||
finally:
|
||||
gen.dedent()
|
||||
|
||||
|
||||
class Constructor(object):
|
||||
|
@ -472,7 +482,11 @@ class Class(object):
|
|||
class_counter[cls.name] += 1
|
||||
|
||||
self.c_name = cls.name
|
||||
self.lib_name, self.name = conv_cls_name(cls.name)
|
||||
if cls.namespaces:
|
||||
self.lib_name = ".".join(map(unicode.lower, cls.namespaces))
|
||||
self.name = cls.name
|
||||
else:
|
||||
self.lib_name, self.name = conv_cls_name(cls.name)
|
||||
|
||||
header_path = cls.filename
|
||||
if not header_path:
|
||||
|
@ -556,6 +570,7 @@ class Class(object):
|
|||
continue
|
||||
else:
|
||||
log.warn("Class %s is unknown" % (i))
|
||||
i = i.rpartition(".")[2]
|
||||
inherits.append("_" + i)
|
||||
if len(inherits) > 1:
|
||||
log.error(
|
||||
|
@ -580,6 +595,8 @@ class Class(object):
|
|||
):
|
||||
try:
|
||||
o.generate(gen)
|
||||
except EolianTypeError:
|
||||
log.info("Skipping %r because of unknown type", o)
|
||||
except Exception:
|
||||
log.exception("Error while generating %r", o)
|
||||
|
||||
|
@ -589,6 +606,8 @@ class Class(object):
|
|||
):
|
||||
try:
|
||||
o.generate(gen)
|
||||
except EolianTypeError:
|
||||
log.info("Skipping %r because of unknown type", o)
|
||||
except Exception:
|
||||
log.exception("Error while generating %r", o)
|
||||
else:
|
||||
|
@ -648,13 +667,13 @@ class File(object):
|
|||
def cdefs_generate(self):
|
||||
gen = self.pyxgen
|
||||
|
||||
gen.write('cdef extern from "*":')
|
||||
gen.indent()
|
||||
gen.write('struct CFILE "__FILE__"')
|
||||
gen.write('struct CLINE "__LINE__"')
|
||||
gen.write('struct CFUNC "__FUNCTION__"')
|
||||
gen.dedent()
|
||||
gen.write()
|
||||
# gen.write('cdef extern from "*":')
|
||||
# gen.indent()
|
||||
# gen.write('struct CFILE "__FILE__"')
|
||||
# gen.write('struct CLINE "__LINE__"')
|
||||
# gen.write('struct CFUNC "__FUNCTION__"')
|
||||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
# gen.write('cdef extern from "Eina.h":')
|
||||
# gen.indent()
|
||||
|
@ -662,13 +681,13 @@ class File(object):
|
|||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
gen.write('cdef extern from "Eo.h":')
|
||||
gen.indent()
|
||||
# gen.write('cdef extern from "Eo.h":')
|
||||
# gen.indent()
|
||||
#gen.write('Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, Eina_Bool is_main_loop, const char *file, const char *func, int line)')
|
||||
gen.write('Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line)')
|
||||
# gen.write('Eina_Bool _eo_do_start(const Eo *obj, const Eo_Class *cur_klass, Eina_Bool is_super, const char *file, const char *func, int line)')
|
||||
#gen.write('void _eo_do_end(const Eo **ojb)')
|
||||
gen.dedent()
|
||||
gen.write()
|
||||
# gen.dedent()
|
||||
# gen.write()
|
||||
|
||||
gen.write('cdef extern from "%s":' % (self.gencls.header_path))
|
||||
gen.indent()
|
||||
|
@ -692,11 +711,15 @@ class File(object):
|
|||
gen.write("%s %s" % (f.type.c_type, f.name))
|
||||
gen.dedent()
|
||||
else:
|
||||
log.warning("Unhandled alias! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
log.error("Unhandled alias! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
for i in eolian.type_structs_get_by_file(self.filepath):
|
||||
log.warning("Type struct not handled! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
log.error("Type struct not handled! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
for i in eolian.type_enums_get_by_file(self.filepath):
|
||||
log.warning("Type enum not handled! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
log.error("Type enum not handled! %s %s %s %s", i.name, i.full_name, i.filename, i.description)
|
||||
for i in eolian.variable_constants_get_by_file(self.filepath):
|
||||
log.error("Variable constant not handled! %s", i)
|
||||
for i in eolian.variable_globals_get_by_file(self.filepath):
|
||||
log.error("Variable global not handled! %s", i)
|
||||
|
||||
self.gencls.cdefs_generate(gen)
|
||||
|
||||
|
@ -707,13 +730,18 @@ class File(object):
|
|||
self.gencls.pyx_generate(self.pyxgen)
|
||||
|
||||
path = [args.output]
|
||||
cls_name = self.cls.name.lower()
|
||||
filename = cls_name + ".pxi"
|
||||
namespaces = []
|
||||
for ns in self.cls.namespaces:
|
||||
namespaces.append(ns.lower())
|
||||
if not namespaces:
|
||||
log.error("Class %s has no namespaces defined" % (self.cls.name))
|
||||
filename = self.cls.name.lower() + ".pxi"
|
||||
namespace = ".".join(namespaces)
|
||||
log.warning("Class %s has no namespaces defined" % (self.cls.name))
|
||||
nstmp = cls_name.partition("_")
|
||||
namespace = nstmp[0]
|
||||
filename = nstmp[2] + ".pxi"
|
||||
else:
|
||||
namespace = ".".join(namespaces)
|
||||
filename = ".".join((namespace, filename))
|
||||
path.append(filename)
|
||||
pxi_path = os.path.join(*path)
|
||||
|
|
Loading…
Reference in New Issue