Commit c13aff5d 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 c0cd9896
...@@ -23,6 +23,14 @@ try: ...@@ -23,6 +23,14 @@ try:
except ImportError: except ImportError:
from builtins import str as basestring 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): class UtilityCode(object):
# Stores utility code to add during code generation. # Stores utility code to add during code generation.
# #
...@@ -651,31 +659,22 @@ class GlobalState(object): ...@@ -651,31 +659,22 @@ class GlobalState(object):
return "%s%s%d" % (Naming.const_prefix, prefix, n) return "%s%s%d" % (Naming.const_prefix, prefix, n)
def add_cached_builtin_decl(self, entry): 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): if self.should_declare(entry.cname, entry):
self.put_pyobject_decl(entry) self.put_pyobject_decl(entry)
w = self.parts['cached_builtins'] w = self.parts['cached_builtins']
conditional_name = False condition = None
if entry.name == 'xrange': if entry.name in non_portable_builtins_map:
# replaced by range() in Py3 condition, replacement = non_portable_builtins_map[entry.name]
conditional_name = True w.putln('#if %s' % condition)
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')
self.put_cached_builtin_init( self.put_cached_builtin_init(
entry.pos, StringEncoding.EncodedString('Exception'), entry.pos, StringEncoding.EncodedString(replacement),
entry.cname) entry.cname)
if conditional_name:
w.putln('#else') w.putln('#else')
self.put_cached_builtin_init( self.put_cached_builtin_init(
entry.pos, StringEncoding.EncodedString(entry.name), entry.pos, StringEncoding.EncodedString(entry.name),
entry.cname) entry.cname)
if conditional_name: if condition:
w.putln('#endif') w.putln('#endif')
def put_cached_builtin_init(self, pos, name, cname): def put_cached_builtin_init(self, pos, name, cname):
......
...@@ -2134,16 +2134,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2134,16 +2134,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
objstruct = "struct %s" % type.objstruct_cname objstruct = "struct %s" % type.objstruct_cname
module_name = type.module_name module_name = type.module_name
condition = None
if module_name not in ('__builtin__', 'builtins'): if module_name not in ('__builtin__', 'builtins'):
module_name = '"%s"' % module_name module_name = '"%s"' % module_name
else: else:
module_name = '__Pyx_BUILTIN_MODULE_NAME' module_name = '__Pyx_BUILTIN_MODULE_NAME'
if type.name in self.py3_type_name_map: if type.name in Code.non_portable_builtins_map:
code.putln("#if PY_MAJOR_VERSION >= 3") 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' % ( code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), 1); %s' % (
type.typeptr_cname, type.typeptr_cname,
module_name, module_name,
self.py3_type_name_map[type.name], replacement,
objstruct, objstruct,
error_code)) error_code))
code.putln("#else") code.putln("#else")
...@@ -2154,7 +2156,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2154,7 +2156,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
objstruct, objstruct,
not type.is_external or type.is_subclassed, not type.is_external or type.is_subclassed,
error_code)) error_code))
if type.name in self.py3_type_name_map: if condition:
code.putln("#endif") code.putln("#endif")
def generate_type_ready_code(self, env, entry, code): def generate_type_ready_code(self, env, entry, code):
......
...@@ -2,7 +2,10 @@ ...@@ -2,7 +2,10 @@
# Cython - Compilation-wide options and pragma declarations # 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 embed_pos_in_docstring = False
gcc_branch_hints = True gcc_branch_hints = True
...@@ -25,6 +28,12 @@ fast_fail = False ...@@ -25,6 +28,12 @@ fast_fail = False
# Make all warnings into errors. # Make all warnings into errors.
warning_errors = False 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(...)" # 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 # to "for i from ..." when i is a cdef'd integer type, and the direction
# (i.e. sign of step) can be determined. # (i.e. sign of step) can be determined.
......
...@@ -759,6 +759,9 @@ class BuiltinScope(Scope): ...@@ -759,6 +759,9 @@ class BuiltinScope(Scope):
if not hasattr(builtins, name): if not hasattr(builtins, name):
if self.outer_scope is not None: if self.outer_scope is not None:
return self.outer_scope.declare_builtin(name, pos) return self.outer_scope.declare_builtin(name, pos)
else:
if Options.error_on_unknown_names:
error(pos, "undeclared name not builtin: %s" % name)
else: else:
warning(pos, "undeclared name not builtin: %s" % name, 2) warning(pos, "undeclared name not builtin: %s" % name, 2)
...@@ -802,6 +805,8 @@ class BuiltinScope(Scope): ...@@ -802,6 +805,8 @@ class BuiltinScope(Scope):
var_entry.is_readonly = 1 var_entry.is_readonly = 1
var_entry.is_builtin = 1 var_entry.is_builtin = 1
var_entry.utility_code = utility_code var_entry.utility_code = utility_code
if Options.cache_builtins:
var_entry.is_const = True
entry.as_variable = var_entry entry.as_variable = var_entry
return type return type
...@@ -911,7 +916,7 @@ class ModuleScope(Scope): ...@@ -911,7 +916,7 @@ class ModuleScope(Scope):
return self.outer_scope.lookup(name, language_level = self.context.language_level) return self.outer_scope.lookup(name, language_level = self.context.language_level)
def declare_builtin(self, name, pos): 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 # 'xrange' and 'BaseException' are special cased in Code.py
if self.has_import_star: if self.has_import_star:
entry = self.declare_var(name, py_object_type, pos) entry = self.declare_var(name, py_object_type, pos)
...@@ -922,6 +927,9 @@ class ModuleScope(Scope): ...@@ -922,6 +927,9 @@ class ModuleScope(Scope):
## return entry ## return entry
else: else:
# unknown - assume it's builtin and look it up at runtime # 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) warning(pos, "undeclared name not builtin: %s" % name, 2)
entry = self.declare(name, None, py_object_type, pos, 'private') entry = self.declare(name, None, py_object_type, pos, 'private')
entry.is_builtin = 1 entry.is_builtin = 1
...@@ -933,7 +941,7 @@ class ModuleScope(Scope): ...@@ -933,7 +941,7 @@ class ModuleScope(Scope):
entry = self.declare(None, None, py_object_type, pos, 'private') entry = self.declare(None, None, py_object_type, pos, 'private')
if Options.cache_builtins: if Options.cache_builtins:
entry.is_builtin = 1 entry.is_builtin = 1
entry.is_const = 1 entry.is_const = 1 # cached
entry.name = name entry.name = name
entry.cname = Naming.builtin_prefix + name entry.cname = Naming.builtin_prefix + name
self.cached_builtins.append(entry) 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