Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
64275702
Commit
64275702
authored
Mar 20, 2009
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
major cleanup, move argument default value caching to code generation phase
parent
0e92b4fc
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
81 additions
and
128 deletions
+81
-128
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+33
-0
Cython/Compiler/ModuleNode.py
Cython/Compiler/ModuleNode.py
+20
-22
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+26
-77
Cython/Compiler/Symtab.py
Cython/Compiler/Symtab.py
+2
-29
No files found.
Cython/Compiler/Code.py
View file @
64275702
...
...
@@ -214,6 +214,16 @@ class IntConst(object):
self
.
value
=
value
self
.
is_long
=
is_long
class
PyObjectConst
(
object
):
"""Global info about a generic constant held by GlobalState.
"""
# cname string
# type PyrexType
def
__init__
(
self
,
cname
,
type
):
self
.
cname
=
cname
self
.
type
=
type
possible_identifier
=
re
.
compile
(
ur"(?![0-9])\
w+$
", re.U).match
nice_identifier = re.compile('^[a-zA-Z0-0_]+$').match
...
...
@@ -321,6 +331,7 @@ class GlobalState(object):
self.const_cname_counter = 1
self.string_const_index = {}
self.int_const_index = {}
self.py_constants = []
def initwriters(self, rootwriter):
self.utilprotowriter = rootwriter.new_writer()
...
...
@@ -394,6 +405,10 @@ class GlobalState(object):
c = self.new_int_const(str_value, longness)
return c
def get_py_const(self, type):
# create a new Python object constant
return self.new_py_const(type)
def get_string_const(self, text):
# return a C string constant, creating a new one if necessary
if text.is_unicode:
...
...
@@ -424,6 +439,12 @@ class GlobalState(object):
self.int_const_index[(value, longness)] = c
return c
def new_py_const(self, type):
cname = self.new_const_cname()
c = PyObjectConst(cname, type)
self.py_constants.append(c)
return c
def new_string_const_cname(self, value, intern=None):
# Create a new globally-unique nice name for a C string constant.
if len(value) < 20 and nice_identifier(value):
...
...
@@ -458,6 +479,15 @@ class GlobalState(object):
def generate_const_declarations(self):
self.generate_string_constants()
self.generate_int_constants()
self.generate_object_constant_decls()
def generate_object_constant_decls(self):
consts = [ (len(c.cname), c.cname, c)
for c in self.py_constants ]
consts.sort()
for _, cname, c in consts:
self.decls_writer.putln(
"
static
%
s
;
" % c.type.declaration_code(cname))
def generate_string_constants(self):
c_consts = [ (len(c.cname), c.cname, c)
...
...
@@ -762,6 +792,9 @@ class CCodeWriter(object):
def get_py_string_const(self, text, identifier=None):
return self.globalstate.get_py_string_const(text, identifier).cname
def get_argument_default_const(self, type):
return self.globalstate.get_py_const(type).cname
def intern(self, text):
return self.get_py_string_const(text)
...
...
Cython/Compiler/ModuleNode.py
View file @
64275702
...
...
@@ -255,10 +255,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
putln
(
""
)
code
.
putln
(
"/* Implementation of %s */"
%
env
.
qualified_name
)
self
.
generate_const_definitions
(
env
,
code
)
self
.
generate_interned_num_decls
(
env
,
code
)
self
.
generate_interned_string_decls
(
env
,
code
)
self
.
generate_py_string_decls
(
env
,
code
)
code
.
globalstate
.
insert_global_var_declarations_into
(
code
)
...
...
@@ -663,13 +659,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
" 'cdef extern from' block"
)
else
:
last_entry
=
enum_values
[
-
1
]
# this does not really generate code, just builds the result value
for
value_entry
in
enum_values
:
if
value_entry
.
value
==
value_entry
.
name
:
if
value_entry
.
value_node
is
not
None
:
value_entry
.
value_node
.
generate_evaluation_code
(
code
)
for
value_entry
in
enum_values
:
if
value_entry
.
value_node
is
None
:
value_code
=
value_entry
.
cname
else
:
value_code
=
(
"%s = %s"
%
(
value_entry
.
cname
,
value_entry
.
value
))
value_entry
.
value
_node
.
result
()
))
if
value_entry
is
not
last_entry
:
value_code
+=
","
code
.
putln
(
value_code
)
...
...
@@ -761,9 +762,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
entry
.
type
.
typeptr_cname
)
code
.
put_var_declarations
(
env
.
var_entries
,
static
=
1
,
dll_linkage
=
"DL_EXPORT"
,
definition
=
definition
)
if
definition
:
code
.
put_var_declarations
(
env
.
default_entries
,
static
=
1
,
definition
=
definition
)
def
generate_cfunction_predeclarations
(
self
,
env
,
code
,
definition
):
for
entry
in
env
.
cfunc_entries
:
...
...
@@ -1702,19 +1700,19 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code
.
put_decref_clear
(
Naming
.
empty_tuple
,
PyrexTypes
.
py_object_type
,
nanny
=
False
)
for
entry
in
env
.
pynum_entries
:
code
.
put_decref_clear
(
entry
.
cname
,
PyrexTypes
.
py_object_type
,
nanny
=
False
)
for
entry
in
env
.
all_pystring_entries
:
if
entry
.
is_interned
:
code
.
put_decref_clear
(
entry
.
pystring_cname
,
PyrexTypes
.
py_object_type
,
nanny
=
False
)
for
entry
in
env
.
default_entries
:
if
entry
.
type
.
is_pyobject
and
entry
.
used
:
code
.
putln
(
"Py_DECREF(%s); %s = 0;"
%
(
code
.
entry_as_pyobject
(
entry
),
entry
.
cname
))
#
for entry in env.pynum_entries:
#
code.put_decref_clear(entry.cname,
#
PyrexTypes.py_object_type,
#
nanny=False)
#
for entry in env.all_pystring_entries:
#
if entry.is_interned:
#
code.put_decref_clear(entry.pystring_cname,
#
PyrexTypes.py_object_type,
#
nanny=False)
#
for entry in env.default_entries:
#
if entry.type.is_pyobject and entry.used:
#
code.putln("Py_DECREF(%s); %s = 0;" % (
#
code.entry_as_pyobject(entry), entry.cname))
code
.
putln
(
"Py_INCREF(Py_None); return Py_None;"
)
code
.
putln
(
'}'
)
...
...
Cython/Compiler/Nodes.py
View file @
64275702
...
...
@@ -302,38 +302,6 @@ class CompilerDirectivesNode(Node):
class
BlockNode
(
object
):
# Mixin class for nodes representing a declaration block.
def
generate_const_definitions
(
self
,
env
,
code
):
if
env
.
const_entries
:
for
entry
in
env
.
const_entries
:
if
not
entry
.
is_interned
:
code
.
globalstate
.
add_const_definition
(
entry
)
def
generate_interned_string_decls
(
self
,
env
,
code
):
entries
=
env
.
global_scope
().
new_interned_string_entries
if
entries
:
for
entry
in
entries
:
code
.
globalstate
.
add_interned_string_decl
(
entry
)
del
entries
[:]
def
generate_py_string_decls
(
self
,
env
,
code
):
if
env
is
None
:
return
# earlier error
entries
=
env
.
pystring_entries
if
entries
:
for
entry
in
entries
:
if
not
entry
.
is_interned
:
code
.
globalstate
.
add_py_string_decl
(
entry
)
def
generate_interned_num_decls
(
self
,
env
,
code
):
# Flush accumulated interned nums from the global scope
# and generate declarations for them.
genv
=
env
.
global_scope
()
entries
=
genv
.
interned_nums
if
entries
:
for
entry
in
entries
:
code
.
globalstate
.
add_interned_num_decl
(
entry
)
del
entries
[:]
def
generate_cached_builtins_decls
(
self
,
env
,
code
):
entries
=
env
.
global_scope
().
undeclared_cached_builtins
for
entry
in
entries
:
...
...
@@ -609,8 +577,7 @@ class CArgDeclNode(Node):
# declarator CDeclaratorNode
# not_none boolean Tagged with 'not None'
# default ExprNode or None
# default_entry Symtab.Entry Entry for the variable holding the default value
# default_result_code string cname or code fragment for default value
# default_value PyObjectConst constant for default value
# is_self_arg boolean Is the "self" arg of an extension type method
# is_kw_only boolean Is a keyword-only argument
...
...
@@ -620,6 +587,7 @@ class CArgDeclNode(Node):
is_generic
=
1
type
=
None
name_declarator
=
None
default_value
=
None
def
analyse
(
self
,
env
,
nonempty
=
0
):
#print "CArgDeclNode.analyse: is_self_arg =", self.is_self_arg ###
...
...
@@ -641,16 +609,15 @@ class CArgDeclNode(Node):
else
:
return
self
.
name_declarator
,
self
.
type
def
prepare_default_result_code
(
self
,
code
):
if
self
.
default
:
if
self
.
default
.
is_literal
:
# FIXME: IS IT OK TO CALL THIS HERE???
self
.
default
.
generate_evaluation_code
(
code
)
self
.
default_result_code
=
self
.
default
.
result
()
if
self
.
default
.
type
!=
self
.
type
and
not
self
.
type
.
is_int
:
self
.
default_result_code
=
self
.
type
.
cast_code
(
self
.
default_result_code
)
else
:
self
.
default_result_code
=
self
.
default_entry
.
cname
def
calculate_default_value_code
(
self
,
code
):
if
self
.
default_value
is
None
:
if
self
.
default
:
if
self
.
default
.
is_literal
:
# will not output any code, just assign the result_code
self
.
default
.
generate_evaluation_code
(
code
)
return
self
.
type
.
cast_code
(
self
.
default
.
result
())
self
.
default_value
=
code
.
get_argument_default_const
(
self
.
type
)
return
self
.
default_value
def
annotate
(
self
,
code
):
if
self
.
default
:
...
...
@@ -944,11 +911,9 @@ class CEnumDefItemNode(StatNode):
if
not
self
.
value
.
type
.
is_int
:
self
.
value
=
self
.
value
.
coerce_to
(
PyrexTypes
.
c_int_type
,
env
)
self
.
value
.
analyse_const_expression
(
env
)
value
=
self
.
value
.
get_constant_result_code
()
else
:
value
=
self
.
name
entry
=
env
.
declare_const
(
self
.
name
,
enum_entry
.
type
,
value
,
self
.
pos
,
cname
=
self
.
cname
,
visibility
=
enum_entry
.
visibility
)
self
.
value
,
self
.
pos
,
cname
=
self
.
cname
,
visibility
=
enum_entry
.
visibility
)
enum_entry
.
enum_values
.
append
(
entry
)
...
...
@@ -997,14 +962,7 @@ class FuncDefNode(StatNode, BlockNode):
if
not
hasattr
(
arg
,
'default_entry'
):
arg
.
default
.
analyse_types
(
env
)
arg
.
default
=
arg
.
default
.
coerce_to
(
arg
.
type
,
genv
)
if
arg
.
default
.
is_literal
:
arg
.
default_entry
=
arg
.
default
else
:
arg
.
default
.
allocate_temps
(
genv
)
arg
.
default_entry
=
genv
.
add_default_value
(
arg
.
type
)
if
arg
.
type
.
is_pyobject
:
arg
.
default_entry
.
init
=
0
arg
.
default_entry
.
used
=
1
arg
.
default
.
allocate_temps
(
genv
)
else
:
error
(
arg
.
pos
,
"This argument cannot have a default value"
)
...
...
@@ -1042,13 +1000,7 @@ class FuncDefNode(StatNode, BlockNode):
# ----- Top-level constants used by this function
code
.
mark_pos
(
self
.
pos
)
self
.
generate_interned_num_decls
(
lenv
,
code
)
self
.
generate_interned_string_decls
(
lenv
,
code
)
self
.
generate_py_string_decls
(
lenv
,
code
)
self
.
generate_cached_builtins_decls
(
lenv
,
code
)
#code.putln("")
#code.put_var_declarations(lenv.const_entries, static = 1)
self
.
generate_const_definitions
(
lenv
,
code
)
# ----- Function header
code
.
putln
(
""
)
if
self
.
py_func
:
...
...
@@ -1244,14 +1196,15 @@ class FuncDefNode(StatNode, BlockNode):
if
not
default
.
is_literal
:
default
.
generate_evaluation_code
(
code
)
default
.
make_owned_reference
(
code
)
result
=
default
.
result_as
(
arg
.
type
)
code
.
putln
(
"%s = %s;"
%
(
arg
.
default_entry
.
cname
,
default
.
result_as
(
arg
.
default_entry
.
type
)))
if
default
.
is_temp
and
default
.
type
.
is_pyobject
:
code
.
putln
(
"%s = 0;"
%
default
.
result
())
arg
.
calculate_default_value_code
(
code
),
result
))
if
arg
.
type
.
is_pyobject
:
code
.
put_giveref
(
default
.
result
())
default
.
generate_post_assignment_code
(
code
)
default
.
free_temps
(
code
)
code
.
put_var_giveref
(
arg
.
default_entry
)
# For Python class methods, create and store function object
if
self
.
assmt
:
self
.
assmt
.
generate_execution_code
(
code
)
...
...
@@ -1438,9 +1391,9 @@ class CFuncDefNode(FuncDefNode):
def
generate_argument_declarations
(
self
,
env
,
code
):
for
arg
in
self
.
args
:
if
arg
.
default
:
arg
.
prepare_default_result
_code
(
code
)
result
=
arg
.
calculate_default_value
_code
(
code
)
code
.
putln
(
'%s = %s;'
%
(
arg
.
type
.
declaration_code
(
arg
.
cname
),
arg
.
default_result_code
))
arg
.
type
.
declaration_code
(
arg
.
cname
),
result
))
def
generate_keyword_list
(
self
,
code
):
pass
...
...
@@ -1881,9 +1834,7 @@ class DefNode(FuncDefNode):
code
.
putln
(
"PyObject *%s = 0;"
%
arg
.
hdr_cname
)
else
:
code
.
put_var_declaration
(
arg
.
entry
)
if
arg
.
default
:
arg
.
prepare_default_result_code
(
code
)
def
generate_keyword_list
(
self
,
code
):
if
self
.
signature_has_generic_args
()
and
\
self
.
signature_has_nongeneric_args
():
...
...
@@ -2143,7 +2094,7 @@ class DefNode(FuncDefNode):
code
.
putln
(
"%s = %s;"
%
(
arg
.
entry
.
cname
,
arg
.
default_result_code
))
arg
.
calculate_default_value_code
(
code
)
))
def
generate_stararg_init_code
(
self
,
max_positional_args
,
code
):
if
self
.
starstar_arg
:
...
...
@@ -2185,7 +2136,7 @@ class DefNode(FuncDefNode):
default_args
=
[]
for
i
,
arg
in
enumerate
(
all_args
):
if
arg
.
default
and
arg
.
type
.
is_pyobject
:
default_value
=
arg
.
default_result_code
default_value
=
arg
.
calculate_default_value_code
(
code
)
if
arg
.
type
is
not
PyrexTypes
.
py_object_type
:
default_value
=
"(PyObject*)"
+
default_value
default_args
.
append
((
i
,
default_value
))
...
...
@@ -2331,7 +2282,7 @@ class DefNode(FuncDefNode):
code
.
putln
(
"%s = %s;"
%
(
arg
.
entry
.
cname
,
arg
.
default_result_code
))
arg
.
calculate_default_value_code
(
code
)
))
code
.
putln
(
'}'
)
def
generate_argument_conversion_code
(
self
,
code
):
...
...
@@ -2582,7 +2533,6 @@ class PyClassDefNode(ClassDefNode):
#self.target.release_target_temp(env)
def
generate_function_definitions
(
self
,
env
,
code
):
self
.
generate_py_string_decls
(
self
.
scope
,
code
)
self
.
body
.
generate_function_definitions
(
self
.
scope
,
code
)
def
generate_execution_code
(
self
,
code
):
...
...
@@ -2716,7 +2666,6 @@ class CClassDefNode(ClassDefNode):
self
.
body
.
analyse_expressions
(
scope
)
def
generate_function_definitions
(
self
,
env
,
code
):
self
.
generate_py_string_decls
(
self
.
entry
.
type
.
scope
,
code
)
if
self
.
body
:
self
.
body
.
generate_function_definitions
(
self
.
entry
.
type
.
scope
,
code
)
...
...
Cython/Compiler/Symtab.py
View file @
64275702
...
...
@@ -296,7 +296,7 @@ class Scope(object):
def qualify_name(self, name):
return "
%
s
.
%
s
" % (self.qualified_name, name)
def declare_const(self, name, type, value, pos, cname = None, visibility = 'private'):
# Add an entry for a named constant.
if not cname:
...
...
@@ -306,7 +306,7 @@ class Scope(object):
cname = self.mangle(Naming.enum_prefix, name)
entry = self.declare(name, cname, type, pos, visibility)
entry.is_const = 1
entry.value = value
entry.value
_node
= value
return entry
def declare_type(self, name, type, pos,
...
...
@@ -683,9 +683,7 @@ class ModuleScope(Scope):
# method_table_cname string C name of method table
# doc string Module doc string
# doc_cname string C name of module doc string
# const_counter integer Counter for naming constants (PS: MOVED TO GLOBAL)
# utility_code_list [(UtilityCode, string)] Queuing utility codes for forwarding to Code.py
# default_entries [Entry] Function argument default entries
# python_include_files [string] Standard Python headers to be included
# include_files [string] Other C headers to be included
# string_to_entry {string : Entry} Map string const to entry
...
...
@@ -697,9 +695,6 @@ class ModuleScope(Scope):
# included_files [string] Cython sources included with 'include'
# pxd_file_loaded boolean Corresponding .pxd file has been processed
# cimported_modules [ModuleScope] Modules imported with cimport
# new_interned_string_entries [Entry] New interned strings waiting to be declared
# interned_nums [int/long] Interned numeric constants
# all_pystring_entries [Entry] Python string consts from all scopes
# types_imported {PyrexType : 1} Set of types for which import code generated
# has_import_star boolean Module contains import *
...
...
@@ -723,20 +718,14 @@ class ModuleScope(Scope):
self.doc = ""
self.doc_cname = Naming.moddoc_cname
self.utility_code_list = []
self.default_entries = []
self.module_entries = {}
self.python_include_files = ["
Python
.
h
", "
structmember
.
h
"]
self.include_files = []
self.type_names = dict(outer_scope.type_names)
self.pxd_file_loaded = 0
self.cimported_modules = []
self.new_interned_string_entries = []
self.interned_nums = []
self.interned_objs = []
self.all_pystring_entries = []
self.types_imported = {}
self.included_files = []
self.pynum_entries = []
self.has_extern_class = 0
self.cached_builtins = []
self.undeclared_cached_builtins = []
...
...
@@ -869,22 +858,6 @@ class ModuleScope(Scope):
if not entry:
self.declare_var(name, py_object_type, pos)
def add_default_value(self, type):
# Add an entry for holding a function argument
# default value.
cname = self.new_const_cname()
entry = Entry("", cname, type)
self.default_entries.append(entry)
return entry
def new_const_cname(self):
global const_counter
# Create a new globally-unique name for a constant.
prefix=''
n = const_counter
const_counter = n + 1
return "
%
s
%
s
%
d
" % (Naming.const_prefix, prefix, n)
def use_utility_code(self, new_code, name=None):
if new_code is not None:
self.utility_code_list.append((new_code, name))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment