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
Boxiang Sun
cython
Commits
774b88c6
Commit
774b88c6
authored
Mar 29, 2013
by
Robert Bradshaw
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #200 from nnemkin/module_level_literal_arrays
Allow module-level literal lists (Fixes #113).
parents
16cb9327
71d13da9
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
42 additions
and
8 deletions
+42
-8
Cython/Compiler/Code.py
Cython/Compiler/Code.py
+11
-7
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+11
-1
tests/run/literal_lists.pyx
tests/run/literal_lists.pyx
+20
-0
No files found.
Cython/Compiler/Code.py
View file @
774b88c6
...
@@ -484,7 +484,7 @@ class FunctionState(object):
...
@@ -484,7 +484,7 @@ class FunctionState(object):
self.in_try_finally = 0
self.in_try_finally = 0
self.exc_vars = None
self.exc_vars = None
self.temps_allocated = [] # of (name, type, manage_ref)
self.temps_allocated = [] # of (name, type, manage_ref
, static
)
self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
self.temps_free = {} # (type, manage_ref) -> list of free vars with same type/managed status
self.temps_used_type = {} # name -> (type, manage_ref)
self.temps_used_type = {} # name -> (type, manage_ref)
self.temp_counter = 0
self.temp_counter = 0
...
@@ -563,7 +563,7 @@ class FunctionState(object):
...
@@ -563,7 +563,7 @@ class FunctionState(object):
# temp handling
# temp handling
def allocate_temp(self, type, manage_ref):
def allocate_temp(self, type, manage_ref
, static=False
):
"""
"""
Allocates a temporary (which may create a new one or get a previously
Allocates a temporary (which may create a new one or get a previously
allocated and released one of the same type). Type is simply registered
allocated and released one of the same type). Type is simply registered
...
@@ -578,6 +578,10 @@ class FunctionState(object):
...
@@ -578,6 +578,10 @@ class FunctionState(object):
still has to be passed. It is recommended to pass False by convention
still has to be passed. It is recommended to pass False by convention
if it is known that type will never be a Python object.
if it is known that type will never be a Python object.
static=True marks the temporary declaration with "static".
This is only used when allocating backing store for a module-level
C array literals.
A C string referring to the variable is returned.
A C string referring to the variable is returned.
"""
"""
if type.is_const:
if type.is_const:
...
@@ -595,7 +599,7 @@ class FunctionState(object):
...
@@ -595,7 +599,7 @@ class FunctionState(object):
self.temp_counter += 1
self.temp_counter += 1
result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
result = "%s%d" % (Naming.codewriter_temp_prefix, self.temp_counter)
if not result in self.names_taken: break
if not result in self.names_taken: break
self.temps_allocated.append((result, type, manage_ref))
self.temps_allocated.append((result, type, manage_ref
, static
))
self.temps_used_type[result] = (type, manage_ref)
self.temps_used_type[result] = (type, manage_ref)
if DebugFlags.debug_temp_code_comments:
if DebugFlags.debug_temp_code_comments:
self.owner.putln("/* %s allocated */" % result)
self.owner.putln("/* %s allocated */" % result)
...
@@ -626,7 +630,7 @@ class FunctionState(object):
...
@@ -626,7 +630,7 @@ class FunctionState(object):
that are currently in use.
that are currently in use.
"""
"""
used = []
used = []
for name, type, manage_ref in self.temps_allocated:
for name, type, manage_ref
, static
in self.temps_allocated:
freelist = self.temps_free.get((type, manage_ref))
freelist = self.temps_free.get((type, manage_ref))
if freelist is None or name not in freelist:
if freelist is None or name not in freelist:
used.append((name, type, manage_ref and type.is_pyobject))
used.append((name, type, manage_ref and type.is_pyobject))
...
@@ -645,7 +649,7 @@ class FunctionState(object):
...
@@ -645,7 +649,7 @@ class FunctionState(object):
"""Return a list of (cname, type) tuples of refcount-managed Python objects.
"""Return a list of (cname, type) tuples of refcount-managed Python objects.
"""
"""
return [(cname, type)
return [(cname, type)
for cname, type, manage_ref in self.temps_allocated
for cname, type, manage_ref
, static
in self.temps_allocated
if manage_ref]
if manage_ref]
def all_free_managed_temps(self):
def all_free_managed_temps(self):
...
@@ -1604,7 +1608,7 @@ class CCodeWriter(object):
...
@@ -1604,7 +1608,7 @@ class CCodeWriter(object):
self
.
putln
(
";"
)
self
.
putln
(
";"
)
def
put_temp_declarations
(
self
,
func_context
):
def
put_temp_declarations
(
self
,
func_context
):
for
name
,
type
,
manage_ref
in
func_context
.
temps_allocated
:
for
name
,
type
,
manage_ref
,
static
in
func_context
.
temps_allocated
:
decl
=
type
.
declaration_code
(
name
)
decl
=
type
.
declaration_code
(
name
)
if
type
.
is_pyobject
:
if
type
.
is_pyobject
:
self
.
putln
(
"%s = NULL;"
%
decl
)
self
.
putln
(
"%s = NULL;"
%
decl
)
...
@@ -1612,7 +1616,7 @@ class CCodeWriter(object):
...
@@ -1612,7 +1616,7 @@ class CCodeWriter(object):
import
MemoryView
import
MemoryView
self
.
putln
(
"%s = %s;"
%
(
decl
,
MemoryView
.
memslice_entry_init
))
self
.
putln
(
"%s = %s;"
%
(
decl
,
MemoryView
.
memslice_entry_init
))
else
:
else
:
self
.
putln
(
"%s
;"
%
decl
)
self
.
putln
(
"%s
%s;"
%
(
static
and
"static "
or
""
,
decl
)
)
def
put_h_guard
(
self
,
guard
):
def
put_h_guard
(
self
,
guard
):
self
.
putln
(
"#ifndef %s"
%
guard
)
self
.
putln
(
"#ifndef %s"
%
guard
)
...
...
Cython/Compiler/ExprNodes.py
View file @
774b88c6
...
@@ -1815,7 +1815,7 @@ class NameNode(AtomicExprNode):
...
@@ -1815,7 +1815,7 @@ class NameNode(AtomicExprNode):
return
# There was an error earlier
return
# There was an error earlier
if
(
self
.
entry
.
type
.
is_ptr
and
isinstance
(
rhs
,
ListNode
)
if
(
self
.
entry
.
type
.
is_ptr
and
isinstance
(
rhs
,
ListNode
)
and
not
self
.
lhs_of_first_assignment
):
and
not
self
.
lhs_of_first_assignment
and
not
rhs
.
in_module_scope
):
error
(
self
.
pos
,
"Literal list must be assigned to pointer at time of declaration"
)
error
(
self
.
pos
,
"Literal list must be assigned to pointer at time of declaration"
)
# is_pyglobal seems to be True for module level-globals only.
# is_pyglobal seems to be True for module level-globals only.
...
@@ -5914,6 +5914,7 @@ class ListNode(SequenceNode):
...
@@ -5914,6 +5914,7 @@ class ListNode(SequenceNode):
obj_conversion_errors
=
[]
obj_conversion_errors
=
[]
type
=
list_type
type
=
list_type
in_module_scope
=
False
gil_message
=
"Constructing Python list"
gil_message
=
"Constructing Python list"
...
@@ -5934,6 +5935,8 @@ class ListNode(SequenceNode):
...
@@ -5934,6 +5935,8 @@ class ListNode(SequenceNode):
node
=
SequenceNode
.
analyse_types
(
self
,
env
)
node
=
SequenceNode
.
analyse_types
(
self
,
env
)
node
.
obj_conversion_errors
=
held_errors
()
node
.
obj_conversion_errors
=
held_errors
()
release_errors
(
ignore
=
True
)
release_errors
(
ignore
=
True
)
if
env
.
is_module_scope
:
self
.
in_module_scope
=
True
return
node
return
node
def
coerce_to
(
self
,
dst_type
,
env
):
def
coerce_to
(
self
,
dst_type
,
env
):
...
@@ -5975,6 +5978,13 @@ class ListNode(SequenceNode):
...
@@ -5975,6 +5978,13 @@ class ListNode(SequenceNode):
t
.
constant_result
=
tuple
(
self
.
constant_result
)
t
.
constant_result
=
tuple
(
self
.
constant_result
)
return
t
return
t
def
allocate_temp_result
(
self
,
code
):
if
self
.
type
.
is_array
and
self
.
in_module_scope
:
self
.
temp_code
=
code
.
funcstate
.
allocate_temp
(
self
.
type
,
manage_ref
=
False
,
static
=
True
)
else
:
SequenceNode
.
allocate_temp_result
(
self
,
code
)
def
release_temp_result
(
self
,
env
):
def
release_temp_result
(
self
,
env
):
if
self
.
type
.
is_array
:
if
self
.
type
.
is_array
:
# To be valid C++, we must allocate the memory on the stack
# To be valid C++, we must allocate the memory on the stack
...
...
tests/run/literal_lists.pyx
View file @
774b88c6
...
@@ -55,6 +55,26 @@ def test_struct(int x, y):
...
@@ -55,6 +55,26 @@ def test_struct(int x, y):
print_struct
(
aa
[
0
])
print_struct
(
aa
[
0
])
print_struct
([
1
,
2
,
<
double
**>
1
])
print_struct
([
1
,
2
,
<
double
**>
1
])
cdef
int
m_int
=
-
1
cdef
int
*
m_iarray
=
[
4
,
m_int
]
cdef
int
**
m_piarray
=
[
m_iarray
,
&
m_int
]
cdef
char
**
m_carray
=
[
b"a"
,
b"bc"
]
cdef
MyStruct
*
m_structarray
=
[[
m_int
,
0
,
NULL
],
[
1
,
m_int
+
1
,
NULL
]]
def
test_module_level
():
"""
>>> test_module_level()
4 -1
4 -1
True True
1 0 True
"""
print
m_iarray
[
0
],
m_iarray
[
1
]
print
m_piarray
[
0
][
0
],
m_piarray
[
1
][
0
]
print
m_carray
[
0
]
==
b"a"
,
m_carray
[
1
]
==
b"bc"
print_struct
(
m_structarray
[
1
])
# Make sure it's still naturally an object.
# Make sure it's still naturally an object.
[
0
,
1
,
2
,
3
].
append
(
4
)
[
0
,
1
,
2
,
3
].
append
(
4
)
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