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

Reply via email to