[pypy-commit] cffi cffi-1.0: progress on enums

arigo noreply at buildbot.pypy.org
Fri Apr 24 17:15:19 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1805:7231fd7eae98
Date: 2015-04-24 17:15 +0200
http://bitbucket.org/cffi/cffi/changeset/7231fd7eae98/

Log:	progress on enums

diff --git a/_cffi1/_cffi_include.h b/_cffi1/_cffi_include.h
--- a/_cffi1/_cffi_include.h
+++ b/_cffi1/_cffi_include.h
@@ -162,10 +162,12 @@
 #define _cffi_array_len(array)   (sizeof(array) / sizeof((array)[0]))
 
 #define _cffi_prim_int(size, sign)                                      \
-    ((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8  : _CFFI_PRIM_UINT8)  :    \
-     (size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) :    \
-     (size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) :    \
-     (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) :    \
+    ((size) == sizeof(int) ? ((sign) ? _CFFI_PRIM_INT   : _CFFI_PRIM_UINT)   : \
+     (size) == sizeof(long)? ((sign) ? _CFFI_PRIM_LONG  : _CFFI_PRIM_ULONG)  : \
+     (size) == 1           ? ((sign) ? _CFFI_PRIM_INT8  : _CFFI_PRIM_UINT8)  : \
+     (size) == 2           ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \
+     (size) == 4           ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \
+     (size) == 8           ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \
      0)
 
 
diff --git a/_cffi1/parse_c_type.h b/_cffi1/parse_c_type.h
--- a/_cffi1/parse_c_type.h
+++ b/_cffi1/parse_c_type.h
@@ -90,7 +90,8 @@
 
 struct _cffi_enum_s {
     const char *name;
-    int type_prim;    /* _CFFI_PRIM_xxx */
+    int type_index;          // -> _cffi_types, on a OP_ENUM
+    int type_prim;           // _CFFI_PRIM_xxx
 };
 
 struct _cffi_typename_s {
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -11,6 +11,10 @@
 
 static PyObject *build_primitive_type(int num);   /* forward */
 
+#define get_primitive_type(num)                                 \
+    (all_primitives[num] != NULL ? all_primitives[num]          \
+                                 : build_primitive_type(num))
+
 static int init_global_types_dict(PyObject *ffi_type_dict)
 {
     int err;
@@ -20,7 +24,7 @@
     if (global_types_dict == NULL)
         return -1;
 
-    ct = build_primitive_type(_CFFI_PRIM_VOID);         // 'void'
+    ct = get_primitive_type(_CFFI_PRIM_VOID);         // 'void'
     if (ct == NULL)
         return -1;
     if (PyDict_SetItemString(global_types_dict,
@@ -260,9 +264,7 @@
     switch (_CFFI_GETOP(op)) {
 
     case _CFFI_OP_PRIMITIVE:
-        x = all_primitives[_CFFI_GETARG(op)];
-        if (x == NULL)
-            x = build_primitive_type(_CFFI_GETARG(op));
+        x = get_primitive_type(_CFFI_GETARG(op));
         Py_XINCREF(x);
         break;
 
@@ -334,7 +336,7 @@
                 ct->ct_extra = builder;
             }
 
-            /* Update the "primary" OP_STRUCT_OR_UNION slot, which
+            /* Update the "primary" OP_STRUCT_UNION slot, which
                may be the same or a different slot than the "current" one */
             assert((((uintptr_t)x) & 1) == 0);
             assert(builder->ctx.types[s->type_index] == op2);
@@ -363,12 +365,40 @@
     case _CFFI_OP_ENUM:
     {
         const struct _cffi_enum_s *e;
+        _cffi_opcode_t op2;
 
         e = &builder->ctx.enums[_CFFI_GETARG(op)];
-        x = all_primitives[e->type_prim];
-        if (x == NULL)
-            x = build_primitive_type(e->type_prim);
-        Py_XINCREF(x);
+        op2 = builder->ctx.types[e->type_index];
+        if ((((uintptr_t)op2) & 1) == 0) {
+            x = (PyObject *)op2;
+            Py_INCREF(x);
+        }
+        else {
+            PyObject *basetd = get_primitive_type(e->type_prim);
+            if (basetd == NULL)
+                return NULL;
+
+            PyObject *args = Py_BuildValue("(s()()O)", e->name, basetd);
+            if (args == NULL)
+                return NULL;
+
+            x = b_new_enum_type(NULL, args);
+            Py_DECREF(args);
+            if (x == NULL)
+                return NULL;
+
+            /* Update the "primary" _CFFI_OP_ENUM slot, which
+               may be the same or a different slot than the "current" one */
+            assert((((uintptr_t)x) & 1) == 0);
+            assert(builder->ctx.types[e->type_index] == op2);
+            Py_INCREF(x);
+            builder->ctx.types[e->type_index] = x;
+
+            /* Done, leave without updating the "current" slot because
+               it may be done already above.  If not, never mind, the
+               next call to realize_c_type() will do it. */
+            return x;
+        }
         break;
     }
 
diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -589,19 +589,14 @@
         is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
         self._generate_cpy_const(is_int, name, tp)
 
-    def _generate_const_int_ctx(self, name):
-        self._lsts["global"].append(
-            '  { "%s", _cffi_const_%s, _CFFI_OP(_CFFI_OP_CONSTANT_INT, 0) },' %
-            (name, name))
-
     def _generate_cpy_constant_ctx(self, tp, name):
         if isinstance(tp, model.PrimitiveType) and tp.is_integer_type():
-            self._generate_const_int_ctx(name)
+            type_op = '_CFFI_OP(_CFFI_OP_CONSTANT_INT, 0)'
         else:
             type_index = self._typesdict[tp]
             type_op = '_CFFI_OP(_CFFI_OP_CONSTANT, %d)' % type_index
-            self._lsts["global"].append(
-                '  { "%s", _cffi_const_%s, %s },' % (name, name, type_op))
+        self._lsts["global"].append(
+            '  { "%s", _cffi_const_%s, %s },' % (name, name, type_op))
 
     # ----------
     # enums
@@ -614,8 +609,13 @@
             self._generate_cpy_const(True, enumerator)
 
     def _enum_ctx(self, tp, cname):
+        type_index = self._typesdict[tp]
+        type_op = '_CFFI_OP(_CFFI_OP_ENUM, %d)' % type_index
         for enumerator in tp.enumerators:
-            self._generate_const_int_ctx(enumerator)
+            self._lsts["global"].append(
+                '  { "%s", _cffi_const_%s, %s },' % (enumerator, enumerator,
+                                                     type_op))
+        #
         if cname is not None:
             size = "sizeof(%s)" % cname
             signed = "((%s)-1) <= 0" % cname
@@ -623,7 +623,7 @@
         else:
             size = xxxx
         self._lsts["enum"].append(
-            '  { "%s", %s },' % (tp.name, prim))
+            '  { "%s", %d, %s },' % (tp.name, type_index, prim))
 
     def _generate_cpy_enum_ctx(self, tp, name):
         if tp.has_c_name():


More information about the pypy-commit mailing list