Convert CVarDefNode to use explicit visibilities.
authorW. Trevor King <wking@drexel.edu>
Wed, 2 Mar 2011 16:19:17 +0000 (11:19 -0500)
committerW. Trevor King <wking@drexel.edu>
Wed, 2 Mar 2011 21:31:13 +0000 (16:31 -0500)
This required some cleanups in Parsing.p_visibility, and the explicit
return to private visibility (for both C and Python) when parsing
C-backed class bodies.

Cython/Compiler/Nodes.py
Cython/Compiler/Parsing.py

index 087e474bcaa0aa81105258d75dccf60272f4f7e3..23ca71ef0b1ebcec7bd08681404d12adef6a8108 100644 (file)
@@ -15,6 +15,7 @@ cython.declare(sys=object, os=object, time=object, copy=object,
 import sys, os, time, copy
 
 import Builtin
+from Binding import Binding
 from Errors import error, warning, InternalError
 import Naming
 import PyrexTypes
@@ -907,11 +908,13 @@ class CComplexBaseTypeNode(CBaseTypeNode):
 class CVarDefNode(StatNode):
     #  C variable definition or forward/extern function declaration.
     #
-    #  visibility    'private' or 'public' or 'extern'
+    #  extern        (same as Binding.extern)
+    #  c_visibility  (same as Binding.c_visibility)
+    #  visibility    (same as Binding.visibility)
     #  base_type     CBaseTypeNode
     #  declarators   [CDeclaratorNode]
     #  in_pxd        boolean
-    #  api           boolean
+    #  api           (same as Binding.api)
 
     #  decorators    [cython.locals(...)] or None
     #  directive_locals { string : NameNode } locals defined by cython.locals(...)
@@ -930,20 +933,18 @@ class CVarDefNode(StatNode):
         # If the field is an external typedef, we cannot be sure about the type,
         # so do conversion ourself rather than rely on the CPython mechanism (through
         # a property; made in AnalyseDeclarationsTransform).
-        if (dest_scope.is_c_class_scope
-            and self.visibility in ('public', 'readonly')):
+        if dest_scope.is_c_class_scope and self.c_visibility == 'public':
             need_property = True
         else:
             need_property = False
-        visibility = self.visibility
 
         for declarator in self.declarators:
             name_declarator, type = declarator.analyse(base_type, env)
             if not type.is_complete():
-                if not (self.visibility == 'extern' and type.is_array):
+                if not (self.extern and type.is_array):
                     error(declarator.pos,
                         "Variable type '%s' is incomplete" % type)
-            if self.visibility == 'extern' and type.is_pyobject:
+            if self.extern and type.is_pyobject:
                 error(declarator.pos,
                     "Python object cannot be declared extern")
             name = name_declarator.name
@@ -951,20 +952,22 @@ class CVarDefNode(StatNode):
             if name == '':
                 error(declarator.pos, "Missing name in declaration.")
                 return
+            binding = Binding(name=name, cname=cname)
+            binding.pull(self)
             if type.is_cfunction:
-                entry = dest_scope.declare_cfunction(name, type, declarator.pos,
-                    cname = cname, visibility = self.visibility, in_pxd = self.in_pxd,
-                    api = self.api)
+                entry = dest_scope.WTK_declare_cfunction(
+                    binding, type = type, pos = declarator.pos,
+                    in_pxd = self.in_pxd)
                 if entry is not None:
                     entry.directive_locals = self.directive_locals
             else:
                 if self.directive_locals:
                     error(self.pos, "Decorators can only be followed by functions")
-                if self.in_pxd and self.visibility != 'extern':
+                if self.in_pxd and not self.extern:
                     error(self.pos,
                         "Only 'extern' C variable declaration allowed in .pxd file")
-                entry = dest_scope.declare_var(name, type, declarator.pos,
-                            cname = cname, visibility = visibility, is_cdef = 1)
+                entry = dest_scope.WTK_declare_var(
+                    binding, type = type, is_cdef = 1, pos = declarator.pos)
                 entry.needs_property = need_property
 
 
index 2a2eff3ba4365db163a444027054e8f12c5dad17..e3fe4c749d643736d53b91e82195bedcf1c4da41 100644 (file)
@@ -2659,22 +2659,23 @@ def p_visibility(s, ctx):
     _LOG.debug('p_visibility(s=<s sy:%s systring:%s>)'
                % (s.sy, s.systring))
     pos = s.position()
-    prev_visibility = 'private'
-    if ctx.extern:
-        prev_visibility = 'extern'
-    elif ctx.c_visibility != 'private':
-        prev_visibility = ctx.c_visibility
-    visibility = prev_visibility
     if s.sy == 'IDENT' and s.systring in ('extern', 'public', 'readonly'):
         visibility = s.systring
-        if prev_visibility != 'private' and visibility != prev_visibility:
-            s.error("Conflicting visibility options '%s' and '%s'"
-                % (prev_visibility, visibility))
+        outer_scope = ctx.level in ('module', 'module_pxd')
+        if visibility == 'extern':
+            #if prev_visibility != 'private' and visibility != prev_visibility:
+            #    s.error("Conflicting visibility options '%s' and '%s'"
+            #            % (prev_visibility, visibility))
+            ctx.extern = 1
+            ctx.c_visibility = 'public'
+            # Need to restore/set default value for Python visibility?
+        elif outer_scope and visibility not in ('readonly',):
+            ctx.c_visibility = visibility
+        else:
+            ctx.visibility = visibility
+            if ctx.visibility != 'private':
+                ctx.c_visibility = 'public'
         s.next()
-    if visibility == 'extern':
-        ctx.extern = 1
-    else:
-        ctx.c_visibility = visibility
     return ctx
 
 def p_c_modifiers(s):
@@ -2752,13 +2753,10 @@ def p_c_func_or_var_declaration(s, pos, ctx, decorators=None):
                                         assignable = 1, nonempty = 1)
             declarators.append(declarator)
         s.expect_newline("Syntax error in C variable declaration")
-        visibility = 'private'
-        if ctx.extern:
-            visibility = 'extern'
-        elif ctx.c_visibility != 'private':
-            visibility = ctx.c_visibility
         result = Nodes.CVarDefNode(pos,
-            visibility = visibility,
+            extern = ctx.extern,
+            c_visibility = ctx.c_visibility,
+            visibility = ctx.visibility,
             api = ctx.api,
             overridable = ctx.overridable,
             base_type = base_type,
@@ -2935,7 +2933,11 @@ def p_c_class_definition(s, pos,  ctx, decorators=None):
             body_level = 'c_class_pxd'
         else:
             body_level = 'c_class'
-        doc, body = p_suite(s, Ctx(level = body_level), with_doc = 1)
+        body_ctx = Ctx(
+            level = body_level,
+            visibility = 'private',
+            c_visibility = 'private')
+        doc, body = p_suite(s, body_ctx, with_doc = 1)
     else:
         s.expect_newline("Syntax error in C class definition")
         doc = None