Commit 4f3af12a authored by Stefan Behnel's avatar Stefan Behnel

clean up special casing of non-portable builtin types, add option for...

clean up special casing of non-portable builtin types, add option for disabling errors on unknown names
parent 664dc7c8
......@@ -23,6 +23,14 @@ try:
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.
#
......@@ -651,31 +659,22 @@ class GlobalState(object):
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):
......
......@@ -2134,16 +2134,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
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")
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,
self.py3_type_name_map[type.name],
replacement,
objstruct,
error_code))
code.putln("#else")
......@@ -2154,7 +2156,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
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):
......
......@@ -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
......@@ -25,6 +28,12 @@ fast_fail = False
# 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.
......
......@@ -759,6 +759,9 @@ class BuiltinScope(Scope):
if not hasattr(builtins, name):
if self.outer_scope is not None:
return self.outer_scope.declare_builtin(name, pos)
else:
if Options.error_on_unknown_names:
error(pos, "undeclared name not builtin: %s" % name)
else:
warning(pos, "undeclared name not builtin: %s" % name, 2)
......@@ -802,6 +805,8 @@ class BuiltinScope(Scope):
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
......@@ -911,7 +916,7 @@ class ModuleScope(Scope):
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)
......@@ -922,6 +927,9 @@ class ModuleScope(Scope):
## return entry
else:
# unknown - assume it's builtin and look it up at runtime
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
......@@ -933,7 +941,7 @@ class ModuleScope(Scope):
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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment