Author: Armin Rigo <[email protected]>
Branch:
Changeset: r67:c78b70b93c73
Date: 2014-11-18 15:47 +0100
http://bitbucket.org/cffi/creflect/changeset/c78b70b93c73/
Log: Starting on global vars
diff --git a/creflect/cparser.py b/creflect/cparser.py
--- a/creflect/cparser.py
+++ b/creflect/cparser.py
@@ -97,7 +97,6 @@
assert isinstance(tp, model.FunctionType)
self.declarations.append(model.FuncDecl(decl.name, tp))
else:
- xxxxxxxxxxxxxx
const = 'const' in decl.quals
if isinstance(node, pycparser.c_ast.Struct):
if node.decls is not None:
@@ -117,7 +116,7 @@
if self._is_constant_globalvar(node):
self._declare('constant ' + decl.name, tp)
else:
- self._declare('variable ' + decl.name, tp)
+ self.declarations.append(model.VarDecl(decl.name, tp))
def _parse_typedef(self, decl):
if not decl.name:
@@ -203,10 +202,7 @@
params = list(getattr(typenode.args, 'params', []))
ellipsis = (
len(params) > 0 and
- isinstance(params[-1].type, pycparser.c_ast.TypeDecl) and
- isinstance(params[-1].type.type,
- pycparser.c_ast.IdentifierType) and
- params[-1].type.type.names == ['__dotdotdot__'])
+ isinstance(params[-1], pycparser.c_ast.EllipsisParam))
if ellipsis:
params.pop()
if not params:
@@ -229,6 +225,13 @@
else:
return type
+ def _is_constant_globalvar(self, typenode):
+ if isinstance(typenode, pycparser.c_ast.PtrDecl):
+ return 'const' in typenode.quals
+ if isinstance(typenode, pycparser.c_ast.TypeDecl):
+ return 'const' in typenode.quals
+ return False
+
def _get_struct_union_enum_type(self, kind, type, const, approx_name=None):
name = type.name or approx_name
if not name or name.startswith('$$$'):
diff --git a/creflect/model.py b/creflect/model.py
--- a/creflect/model.py
+++ b/creflect/model.py
@@ -23,10 +23,6 @@
def inspect_nonconst_type(self, block, inspect):
raise NotImplementedError
- def _flush_inspect(self, inspect):
- if inspect is not None and inspect.started:
- inspect.assign_to_p1('0')
-
def shadow_global_var(self, top_level_block, name):
return name
@@ -51,7 +47,7 @@
self.c_name_with_marker = 'const ' + self.c_name_with_marker
def inspect_nonconst_type(self, block, inspect):
- self._flush_inspect(inspect)
+ inspect.flush()
return block.write_crx_type_var('cb->get_void_type(cb)')
void_type = VoidType(const=False)
@@ -99,7 +95,7 @@
return self.ALL_PRIMITIVE_TYPES[self.name] == 'f'
def inspect_nonconst_type(self, block, inspect):
- if inspect is None:
+ if not isinstance(inspect, TypeInspector):
if self.is_signed_type():
expr = 'cb->get_signed_type(cb, sizeof(%s), "%s")' % (
self.name, self.name)
@@ -152,48 +148,62 @@
self.c_name_with_marker = (
self.result.c_name_with_marker.replace('&', replace_with))
- def inspect_type(self, block, inspect):
- # this class overrides inspect_type() instead of
- # inspect_nonconst_type(), to avoid the extra call to get_const_type()
- self._flush_inspect(inspect)
+ def _get_arg_ret_types(self, block):
+ inspect = MissingInspector()
+ t1 = self.result.inspect_type(block, inspect)
+ t_args = [arg.inspect_type(block, inspect) for arg in self.args]
+ a2 = block.add_array_crx_types(len(t_args))
+ for i, t in enumerate(t_args):
+ block.writeline('%s[%d] = %s;' % (a2, i, t))
+ return t1, a2
- # limitations so far:
- assert not self.ellipsis, "XXX"
- assert inspect is not None, "XXX"
- assert inspect.started, "XXX"
- assert inspect.levels == ['*'], "XXX"
-
- t1 = self.result.inspect_type(block, None)
+ def _get_c_call_sequence(self, varname):
call = [' ']
if not isinstance(self.result, VoidType):
call.append('*(%s)result = ' % (self.result.get_c_name('*'),))
- call.append('f(')
- t_args = [arg.inspect_type(block, None) for arg in self.args]
- a2 = block.add_array_crx_types(len(t_args))
- for i, t in enumerate(t_args):
- block.writeline('%s[%d] = %s;' % (a2, i, t))
+ call.append(varname)
+ call.append('(')
+ for i in range(len(self.args)):
if i > 0:
call.append(', ')
call.append('*(%s)args[%d]' % (self.args[i].get_c_name('*'), i))
call.append(');')
- #
+ return ''.join(call)
+
+ def inspect_type(self, block, inspect):
+ # this class overrides inspect_type() instead of
+ # inspect_nonconst_type(), to avoid the extra call to get_const_type()
+ if self.ellipsis:
+ return self.inspect_type_ellipsis(block, inspect)
+
+ inspect.flush()
+
+ # limitations so far:
+ assert isinstance(inspect, TypeInspector)
+ assert inspect.started, "XXX"
+ assert inspect.levels == ['*'], "XXX"
+
toplevel = block.crx_top_level
- if inspect.varname is not None:
- extraname = 'c_' + inspect.varname
- else:
- extraname = block._get_next_name('f')
+ extraname = block._get_next_name('f')
crx_func_name = '%s__%s' % (toplevel.crx_func_name, extraname)
wrline = toplevel.writeline
wrline('static void %s(void *func, void *args[], void *result) {' % (
crx_func_name,))
- if inspect.started:
- assert inspect.levels == ['*']
- wrline(' %s f = func;' % inspect.typename)
- wrline(''.join(call))
+ wrline(' %s f = func;' % inspect.typename)
+ wrline(self._get_c_call_sequence('f'))
wrline('}')
wrline('')
+ t1, a2 = self._get_arg_ret_types(block)
expr = 'cb->get_function_type(cb, %s, %s, %d, &%s)' % (
- t1, a2, len(t_args), crx_func_name)
+ t1, a2, len(self.args), crx_func_name)
+ return block.write_crx_type_var(expr)
+
+ def inspect_type_ellipsis(self, block, inspect):
+ if not isinstance(inspect, TypeInspector):
+ XXX
+ else:
+ star_p1 = inspect.fetch_star_p1()
+ xxx
return block.write_crx_type_var(expr)
def shadow_global_var(self, top_level_block, fnname):
@@ -211,32 +221,20 @@
return shadowname
def write_func_decl(self, block, fnname):
- # XXX code duplication!
- t1 = self.result.inspect_type(block, None)
- call = [' ']
- if not isinstance(self.result, VoidType):
- call.append('*(%s)result = ' % (self.result.get_c_name('*'),))
- call.append('%s(' % fnname)
- t_args = [arg.inspect_type(block, None) for arg in self.args]
- a2 = block.add_array_crx_types(len(t_args))
- for i, t in enumerate(t_args):
- block.writeline('%s[%d] = %s;' % (a2, i, t))
- if i > 0:
- call.append(', ')
- call.append('*(%s)args[%d]' % (self.args[i].get_c_name('*'), i))
- call.append(');')
- #
+ # a special-case for global function declarations
+ assert not self.ellipsis
toplevel = block.crx_top_level
crx_func_name = '%s__c_%s' % (toplevel.crx_func_name, fnname)
wrline = toplevel.writeline
wrline('static void %s(void *args[], void *result) {' % (
crx_func_name,))
- wrline(''.join(call))
+ wrline(self._get_c_call_sequence(fnname))
wrline('}')
wrline('')
shadow = self.shadow_global_var(toplevel, fnname)
+ t1, a2 = self._get_arg_ret_types(block)
block.writeline('cb->define_func(cb, "%s", %s, %s, %d, &%s, &%s);' % (
- fnname, t1, a2, len(t_args), crx_func_name, shadow))
+ fnname, t1, a2, len(self.args), crx_func_name, shadow))
class PointerType(BaseType):
@@ -257,7 +255,7 @@
self.c_name_with_marker = base.replace('&', extra)
def inspect_nonconst_type(self, block, inspect):
- if inspect is not None:
+ if isinstance(inspect, TypeInspector):
star_p1 = inspect.fetch_star_p1()
new_var = 'p%d' % (len(inspect.levels) + 2,)
block.writedecl("char *%s;" % (new_var,))
@@ -278,6 +276,12 @@
block.writeline("}")
inspect.after_star_p1_assignment.append(after)
inspect.levels.append('*')
+ elif isinstance(inspect, VarInspector):
+ block.writeline("void *p1 = %s; /* check that '%s' is a"
+ " pointer */" % (inspect.varname, inspect.varname))
+ block.writeline("if (0) { %s = p1; } /* check that '%s' is a"
+ " pointer variable, and not an array or a"
+ " constant */" % (inspect.varname,
inspect.varname))
t1 = self.totype.inspect_type(block, inspect)
return block.write_crx_type_var('cb->get_pointer_type(cb, %s)' % t1)
@@ -302,7 +306,7 @@
def inspect_type(self, block, inspect):
# this class overrides inspect_type() instead of
# inspect_nonconst_type(), to avoid the extra call to get_const_type()
- if inspect is not None:
+ if isinstance(inspect, TypeInspector):
star_p1 = inspect.fetch_star_p1()
errmsg = "type '%s' is not an array, but a pointer type" % (
inspect.get_comment_type(0, False),)
@@ -338,11 +342,25 @@
# ____________________________________________________________
+class MissingInspector(object):
+
+ def flush(self):
+ pass
+
+
+class VarInspector(object):
+ def __init__(self, block, varname):
+ self.block = block
+ self.varname = varname
+
+ def flush(self):
+ pass
+
+
class TypeInspector(object):
- def __init__(self, block, typename, structfield=None, varname=None):
+ def __init__(self, block, typename, structfield=None):
self.block = block
self.typename = typename
- self.varname = varname
self.structfield = structfield
self.started = False
if structfield is None:
@@ -362,6 +380,10 @@
self.at_end = []
self.assign_target = None
+ def flush(self):
+ if self.started:
+ self.assign_to_p1('0')
+
def get_comment_type(self, levels_delta, ignore_array, minlevel=0):
end = len(self.levels)
while ignore_array and end > 0 and self.levels[end - 1] == '[]':
@@ -527,21 +549,23 @@
def write_declaration(self, funcblock):
block = CodeBlock(funcblock)
- inspect = TypeInspector(block, None, varname=self.name)
+ inspect = VarInspector(block, self.name)
t1 = self.type.inspect_type(block, inspect)
- inspect.stop()
shadow = self.type.shadow_global_var(block.crx_top_level, self.name)
block.writeline('cb->define_var(cb, "%s", %s, &%s);' % (
self.name, t1, shadow))
funcblock.write_subblock(block)
-class FuncDecl(object):
+class FuncDecl(VarDecl):
def __init__(self, name, type):
self.name = name
self.type = type
def write_declaration(self, funcblock):
- block = CodeBlock(funcblock)
- self.type.write_func_decl(block, self.name)
- funcblock.write_subblock(block)
+ if self.type.ellipsis:
+ VarDecl.write_declaration(self, funcblock)
+ else:
+ block = CodeBlock(funcblock)
+ self.type.write_func_decl(block, self.name)
+ funcblock.write_subblock(block)
diff --git a/test/cgcompile.c b/test/cgcompile.c
--- a/test/cgcompile.c
+++ b/test/cgcompile.c
@@ -96,7 +96,8 @@
crx_type_t *ret,
crx_type_t *args[], int
nargs)
{
- abort();
+ crx_type_t *dotdotdot = newtype2("... -> ", ret->text);
+ return tst_get_function_type(cb, dotdotdot, args, nargs, 0);
}
static crx_type_t *tst_get_pointer_type(crx_builder_t *cb, crx_type_t *t)
diff --git a/test/codegen/func-002.c b/test/codegen/func-002.c
--- a/test/codegen/func-002.c
+++ b/test/codegen/func-002.c
@@ -9,12 +9,13 @@
void testfunc_002(crx_builder_t *cb)
{
- crx_type *t1, *a2[1], *t2;
+ crx_type_t *t1, *a2[1], *t3;
{
int (*p1)(int, ...) = f; /* check that 'f' is a function with exactly
the given signature */
t1 = cb->get_signed_type(cb, sizeof(int), "int");
a2[0] = t1;
- t2 = cb->get_ellipsis_function_type(cb, t1, a2, 1);
- cb->define_var(cb, "f", t2, p1);
+ t3 = cb->get_ellipsis_function_type(cb, t1, a2, 1);
+ cb->define_var(cb, "f", t3, p1);
+#expect VAR f: FUNC( int -> ... -> int )
}
}
diff --git a/test/codegen/glob-001.c b/test/codegen/glob-001.c
--- a/test/codegen/glob-001.c
+++ b/test/codegen/glob-001.c
@@ -2,15 +2,15 @@
# ____________________________________________________________
-int testglob_001(char *r)
+void testglob_001(crx_builder_t *cb)
{
- if (!r)
- return 28 + 17;
+ crx_type_t *t1, *t2;
{
void *p1 = someglob; /* check that 'someglob' is a pointer */
- r += sprintf(r, "/*%p*/", &someglob);
if (0) { someglob = p1; } /* check that 'someglob' is a pointer
variable, and not an array or a constant */
- r += sprintf(r, "void *someglob;\n");
+ t1 = cb->get_void_type(cb);
+ t2 = cb->get_pointer_type(cb, t1);
+ cb->define_var(cb, "someglob", t2, &someglob);
+#expect VAR someglob: PTR void
}
- return 0;
}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit