Skip to content

Commit

Permalink
clean up special casing of non-portable builtin types, add option for…
Browse files Browse the repository at this point in the history
… disabling errors on unknown names
  • Loading branch information
Stefan Behnel committed Apr 16, 2011
1 parent c0cd989 commit c13aff5
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 31 deletions.
31 changes: 15 additions & 16 deletions Cython/Compiler/Code.py
Expand Up @@ -23,6 +23,14 @@
except ImportError:
from builtins import str as basestring


non_portable_builtins_map = {
'bytes' : ('PY_MAJOR_VERSION < 3', 'str'),
'unicode' : ('PY_MAJOR_VERSION >= 3', 'str'),
'xrange' : ('PY_MAJOR_VERSION >= 3', 'range'),
'BaseException' : ('PY_VERSION_HEX < 0x02050000', 'Exception'),
}

class UtilityCode(object):
# Stores utility code to add during code generation.
#
Expand Down Expand Up @@ -651,31 +659,22 @@ def new_const_cname(self, prefix=''):
return "%s%s%d" % (Naming.const_prefix, prefix, n)

def add_cached_builtin_decl(self, entry):
if Options.cache_builtins:
if entry.is_builtin and entry.is_const:
if self.should_declare(entry.cname, entry):
self.put_pyobject_decl(entry)
w = self.parts['cached_builtins']
conditional_name = False
if entry.name == 'xrange':
# replaced by range() in Py3
conditional_name = True
w.putln('#if PY_MAJOR_VERSION >= 3')
self.put_cached_builtin_init(
entry.pos, StringEncoding.EncodedString('range'),
entry.cname)
elif entry.name == 'BaseException':
# replace BaseException by Exception in Py<2.5
conditional_name = True
w.putln('#if PY_VERSION_HEX < 0x02050000')
condition = None
if entry.name in non_portable_builtins_map:
condition, replacement = non_portable_builtins_map[entry.name]
w.putln('#if %s' % condition)
self.put_cached_builtin_init(
entry.pos, StringEncoding.EncodedString('Exception'),
entry.pos, StringEncoding.EncodedString(replacement),
entry.cname)
if conditional_name:
w.putln('#else')
self.put_cached_builtin_init(
entry.pos, StringEncoding.EncodedString(entry.name),
entry.cname)
if conditional_name:
if condition:
w.putln('#endif')

def put_cached_builtin_init(self, pos, name, cname):
Expand Down
22 changes: 12 additions & 10 deletions Cython/Compiler/ModuleNode.py
Expand Up @@ -2134,27 +2134,29 @@ def generate_type_import_call(self, type, code, error_code):
else:
objstruct = "struct %s" % type.objstruct_cname
module_name = type.module_name
condition = None
if module_name not in ('__builtin__', 'builtins'):
module_name = '"%s"' % module_name
else:
module_name = '__Pyx_BUILTIN_MODULE_NAME'
if type.name in self.py3_type_name_map:
code.putln("#if PY_MAJOR_VERSION >= 3")
code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), 1); %s' % (
type.typeptr_cname,
module_name,
self.py3_type_name_map[type.name],
objstruct,
error_code))
code.putln("#else")
if type.name in Code.non_portable_builtins_map:
condition, replacement = Code.non_portable_builtins_map[entry.name]
code.putln("#if %s" % condition)
code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), 1); %s' % (
type.typeptr_cname,
module_name,
replacement,
objstruct,
error_code))
code.putln("#else")
code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), %i); %s' % (
type.typeptr_cname,
module_name,
type.name,
objstruct,
not type.is_external or type.is_subclassed,
error_code))
if type.name in self.py3_type_name_map:
if condition:
code.putln("#endif")

def generate_type_ready_code(self, env, entry, code):
Expand Down
11 changes: 10 additions & 1 deletion Cython/Compiler/Options.py
Expand Up @@ -2,7 +2,10 @@
# Cython - Compilation-wide options and pragma declarations
#

cache_builtins = True # Perform lookups on builtin names only once
# Perform lookups on builtin names only once, at module initialisation
# time. This will prevent the module from getting imported if a
# builtin name that it uses cannot be found during initialisation.
cache_builtins = True

embed_pos_in_docstring = False
gcc_branch_hints = True
Expand All @@ -25,6 +28,12 @@
# Make all warnings into errors.
warning_errors = False

# Make unknown names an error. Python raises a NameError when
# encountering unknown names at runtime, whereas this option makes
# them a compile time error. If you want full Python compatibility,
# you should disable this option and also 'cache_builtins'.
error_on_unknown_names = True

# This will convert statements of the form "for i in range(...)"
# to "for i from ..." when i is a cdef'd integer type, and the direction
# (i.e. sign of step) can be determined.
Expand Down
16 changes: 12 additions & 4 deletions Cython/Compiler/Symtab.py
Expand Up @@ -760,7 +760,10 @@ def declare_builtin(self, name, pos):
if self.outer_scope is not None:
return self.outer_scope.declare_builtin(name, pos)
else:
warning(pos, "undeclared name not builtin: %s" % name, 2)
if Options.error_on_unknown_names:
error(pos, "undeclared name not builtin: %s" % name)
else:
warning(pos, "undeclared name not builtin: %s" % name, 2)

def declare_builtin_cfunction(self, name, type, cname, python_equiv = None,
utility_code = None):
Expand Down Expand Up @@ -802,6 +805,8 @@ def declare_builtin_type(self, name, cname, utility_code = None, objstruct_cname
var_entry.is_readonly = 1
var_entry.is_builtin = 1
var_entry.utility_code = utility_code
if Options.cache_builtins:
var_entry.is_const = True
entry.as_variable = var_entry

return type
Expand Down Expand Up @@ -911,7 +916,7 @@ def lookup(self, name):
return self.outer_scope.lookup(name, language_level = self.context.language_level)

def declare_builtin(self, name, pos):
if not hasattr(builtins, name) and name not in ('xrange', 'BaseException'):
if not hasattr(builtins, name) and name not in Code.non_portable_builtins_map:
# 'xrange' and 'BaseException' are special cased in Code.py
if self.has_import_star:
entry = self.declare_var(name, py_object_type, pos)
Expand All @@ -922,7 +927,10 @@ def declare_builtin(self, name, pos):
## return entry
else:
# unknown - assume it's builtin and look it up at runtime
warning(pos, "undeclared name not builtin: %s" % name, 2)
if Options.error_on_unknown_names:
error(pos, "undeclared name not builtin: %s" % name)
else:
warning(pos, "undeclared name not builtin: %s" % name, 2)
entry = self.declare(name, None, py_object_type, pos, 'private')
entry.is_builtin = 1
return entry
Expand All @@ -933,7 +941,7 @@ def declare_builtin(self, name, pos):
entry = self.declare(None, None, py_object_type, pos, 'private')
if Options.cache_builtins:
entry.is_builtin = 1
entry.is_const = 1
entry.is_const = 1 # cached
entry.name = name
entry.cname = Naming.builtin_prefix + name
self.cached_builtins.append(entry)
Expand Down

0 comments on commit c13aff5

Please sign in to comment.