Commit dfa31de0 authored by Mark's avatar Mark

Merge pull request #61 from markflorisson88/_memview_rebase

Support for typed memoryviews, memoryview objects & cython.array
parents e8527c58 2a4ffd18
This diff is collapsed.
cimport cython cimport cython
cdef class UtilityCode: cdef class UtilityCodeBase(object):
cdef public object name
cdef class UtilityCode(UtilityCodeBase):
cdef public object proto cdef public object proto
cdef public object impl cdef public object impl
cdef public object init cdef public object init
...@@ -10,6 +13,7 @@ cdef class UtilityCode: ...@@ -10,6 +13,7 @@ cdef class UtilityCode:
cdef public dict _cache cdef public dict _cache
cdef public list specialize_list cdef public list specialize_list
cdef public object proto_block cdef public object proto_block
cdef public object file
cpdef put_code(self, output) cpdef put_code(self, output)
......
This diff is collapsed.
...@@ -3,14 +3,19 @@ from PyrexTypes import * ...@@ -3,14 +3,19 @@ from PyrexTypes import *
from UtilityCode import CythonUtilityCode from UtilityCode import CythonUtilityCode
from Errors import error from Errors import error
from Scanning import StringSourceDescriptor from Scanning import StringSourceDescriptor
import Options
import Buffer
import MemoryView
class CythonScope(ModuleScope): class CythonScope(ModuleScope):
is_cython_builtin = 1 is_cython_builtin = 1
def __init__(self): def __init__(self, context):
ModuleScope.__init__(self, u'cython', None, None) ModuleScope.__init__(self, u'cython', None, None)
self.pxd_file_loaded = True self.pxd_file_loaded = True
self.populate_cython_scope() self.populate_cython_scope()
# The Main.Context object
self.context = context
def lookup_type(self, name): def lookup_type(self, name):
# This function should go away when types are all first-level objects. # This function should go away when types are all first-level objects.
...@@ -66,28 +71,40 @@ class CythonScope(ModuleScope): ...@@ -66,28 +71,40 @@ class CythonScope(ModuleScope):
# self.test_cythonscope() # self.test_cythonscope()
def test_cythonscope(self): def test_cythonscope(self):
# A special function just to make it easy to test the scope and """
# utility code functionality in isolation. It is available to Creates some entries for testing purposes and entries for
# "end-users" but nobody will know it is there anyway... cython.array() and for cython.view.*.
cython_testscope_utility_code.declare_in_scope(self) """
cython_test_extclass_utility_code.declare_in_scope(self) cython_testscope_utility_code.declare_in_scope(
self, cython_scope=self)
cython_test_extclass_utility_code.declare_in_scope(
self, cython_scope=self)
MemoryView.cython_array_utility_code.declare_in_scope(
self, cython_scope=self)
# #
# The view sub-scope # The view sub-scope
# #
self.viewscope = viewscope = ModuleScope(u'cython.view', self, None) self.viewscope = viewscope = ModuleScope(u'view', self, None)
self.declare_module('view', viewscope, None) self.declare_module('view', viewscope, None).as_module = viewscope
viewscope.is_cython_builtin = True viewscope.is_cython_builtin = True
viewscope.pxd_file_loaded = True viewscope.pxd_file_loaded = True
cythonview_testscope_utility_code.declare_in_scope(viewscope) cythonview_testscope_utility_code.declare_in_scope(
viewscope, cython_scope=self)
view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
viewscope, cython_scope=self)
# MemoryView.memview_fromslice_utility_code.from_scope = view_utility_scope
# MemoryView.memview_fromslice_utility_code.declare_in_scope(viewscope)
def create_cython_scope(context, create_testscope): def create_cython_scope(context, create_testscope):
# One could in fact probably make it a singleton, # One could in fact probably make it a singleton,
# but not sure yet whether any code mutates it (which would kill reusing # but not sure yet whether any code mutates it (which would kill reusing
# it across different contexts) # it across different contexts)
scope = CythonScope() scope = CythonScope(context)
if create_testscope: if create_testscope:
scope.test_cythonscope() scope.test_cythonscope()
...@@ -95,80 +112,29 @@ def create_cython_scope(context, create_testscope): ...@@ -95,80 +112,29 @@ def create_cython_scope(context, create_testscope):
return scope return scope
cython_testscope_utility_code = CythonUtilityCode(u""" # Load test utilities for the cython scope
@cname('__pyx_testscope')
cdef object _testscope(int value): def load_testscope_utility(cy_util_name, **kwargs):
return "hello from cython scope, value=%d" % value return CythonUtilityCode.load(cy_util_name, "TestCythonScope.pyx", **kwargs)
""")
undecorated_methods_protos = UtilityCode(proto=u""" undecorated_methods_protos = UtilityCode(proto=u"""
/* These methods are undecorated and have therefore no prototype */ /* These methods are undecorated and have therefore no prototype */
static PyObject *__pyx_TestClass_cdef_method( static PyObject *__pyx_TestClass_cdef_method(
struct __pyx_TestClass *self, int value); struct __pyx_TestClass_obj *self, int value);
static PyObject *__pyx_TestClass_cpdef_method( static PyObject *__pyx_TestClass_cpdef_method(
struct __pyx_TestClass *self, int value, int skip_dispatch); struct __pyx_TestClass_obj *self, int value, int skip_dispatch);
static PyObject *__pyx_TestClass_def_method( static PyObject *__pyx_TestClass_def_method(
PyObject *self, PyObject *value); PyObject *self, PyObject *value);
""") """)
test_cython_utility_dep = CythonUtilityCode(u""" cython_testscope_utility_code = load_testscope_utility("TestScope")
@cname('__pyx_test_dep')
cdef test_dep(obj):
print 'test_dep', obj
""")
cython_test_extclass_utility_code = CythonUtilityCode(
name="TestClassUtilityCode",
prefix="__pyx_prefix_TestClass_",
requires=[undecorated_methods_protos, test_cython_utility_dep],
impl=u"""
cdef extern from *:
cdef object __pyx_test_dep(object)
@cname('__pyx_TestClass')
cdef class TestClass(object):
cdef public int value
def __init__(self, int value):
self.value = value
def __str__(self):
return 'TestClass(%d)' % self.value
cdef cdef_method(self, int value): test_cython_utility_dep = load_testscope_utility("TestDep")
print 'Hello from cdef_method', value
cpdef cpdef_method(self, int value): cython_test_extclass_utility_code = \
print 'Hello from cpdef_method', value load_testscope_utility("TestClass", name="TestClass",
requires=[undecorated_methods_protos,
test_cython_utility_dep])
def def_method(self, int value): cythonview_testscope_utility_code = load_testscope_utility("View.TestScope")
print 'Hello from def_method', value \ No newline at end of file
@cname('cdef_cname')
cdef cdef_cname_method(self, int value):
print "Hello from cdef_cname_method", value
@cname('cpdef_cname')
cpdef cpdef_cname_method(self, int value):
print "Hello from cpdef_cname_method", value
@cname('def_cname')
def def_cname_method(self, int value):
print "Hello from def_cname_method", value
@cname('__pyx_test_call_other_cy_util')
cdef test_call(obj):
print 'test_call'
__pyx_test_dep(obj)
@cname('__pyx_TestClass_New')
cdef _testclass_new(int value):
return TestClass(value)
""")
cythonview_testscope_utility_code = CythonUtilityCode(u"""
@cname('__pyx_view_testscope')
cdef object _testscope(int value):
return "hello from cython.view scope, value=%d" % value
""")
This diff is collapsed.
...@@ -430,7 +430,7 @@ def create_default_resultobj(compilation_source, options): ...@@ -430,7 +430,7 @@ def create_default_resultobj(compilation_source, options):
def run_pipeline(source, options, full_module_name = None): def run_pipeline(source, options, full_module_name = None):
import Pipeline import Pipeline
# Set up context
context = options.create_context() context = options.create_context()
# Set up source object # Set up source object
...@@ -438,6 +438,7 @@ def run_pipeline(source, options, full_module_name = None): ...@@ -438,6 +438,7 @@ def run_pipeline(source, options, full_module_name = None):
abs_path = os.path.abspath(source) abs_path = os.path.abspath(source)
source_ext = os.path.splitext(source)[1] source_ext = os.path.splitext(source)[1]
full_module_name = full_module_name or context.extract_module_name(source, options) full_module_name = full_module_name or context.extract_module_name(source, options)
if options.relative_path_in_code_position_comments: if options.relative_path_in_code_position_comments:
rel_path = full_module_name.replace('.', os.sep) + source_ext rel_path = full_module_name.replace('.', os.sep) + source_ext
if not abs_path.endswith(rel_path): if not abs_path.endswith(rel_path):
...@@ -520,7 +521,7 @@ class CompilationOptions(object): ...@@ -520,7 +521,7 @@ class CompilationOptions(object):
def create_context(self): def create_context(self):
return Context(self.include_path, self.compiler_directives, return Context(self.include_path, self.compiler_directives,
self.cplus, self.language_level, options=self) self.cplus, self.language_level, options=self)
class CompilationResult(object): class CompilationResult(object):
...@@ -584,7 +585,8 @@ def compile_multiple(sources, options): ...@@ -584,7 +585,8 @@ def compile_multiple(sources, options):
a CompilationResultSet. Performs timestamp checking and/or recursion a CompilationResultSet. Performs timestamp checking and/or recursion
if these are specified in the options. if these are specified in the options.
""" """
context = options.create_context() # run_pipeline creates the context
# context = options.create_context()
sources = [os.path.abspath(source) for source in sources] sources = [os.path.abspath(source) for source in sources]
processed = set() processed = set()
results = CompilationResultSet() results = CompilationResultSet()
......
This diff is collapsed.
...@@ -65,10 +65,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -65,10 +65,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.body.stats.extend(tree.stats) self.body.stats.extend(tree.stats)
else: else:
self.body.stats.append(tree) self.body.stats.append(tree)
selfscope = self.scope
selfscope.utility_code_list.extend(scope.utility_code_list) self.scope.utility_code_list.extend(scope.utility_code_list)
def extend_if_not_in(L1, L2):
for x in L2:
if x not in L1:
L1.append(x)
extend_if_not_in(self.scope.include_files, scope.include_files)
extend_if_not_in(self.scope.included_files, scope.included_files)
extend_if_not_in(self.scope.python_include_files,
scope.python_include_files)
if merge_scope: if merge_scope:
selfscope.merge_in(scope) # Ensure that we don't generate import code for these entries!
for entry in scope.c_class_entries:
entry.type.module_name = self.full_module_name
self.scope.merge_in(scope)
def analyse_declarations(self, env): def analyse_declarations(self, env):
if Options.embed_pos_in_docstring: if Options.embed_pos_in_docstring:
...@@ -126,7 +141,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -126,7 +141,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if (h_types or h_vars or h_funcs or h_extension_types): if (h_types or h_vars or h_funcs or h_extension_types):
result.h_file = replace_suffix(result.c_file, ".h") result.h_file = replace_suffix(result.c_file, ".h")
h_code = Code.CCodeWriter() h_code = Code.CCodeWriter()
Code.GlobalState(h_code) Code.GlobalState(h_code, self)
if options.generate_pxi: if options.generate_pxi:
result.i_file = replace_suffix(result.c_file, ".pxi") result.i_file = replace_suffix(result.c_file, ".pxi")
i_code = Code.PyrexCodeWriter(result.i_file) i_code = Code.PyrexCodeWriter(result.i_file)
...@@ -195,7 +210,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -195,7 +210,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if api_vars or api_funcs or api_extension_types: if api_vars or api_funcs or api_extension_types:
result.api_file = replace_suffix(result.c_file, "_api.h") result.api_file = replace_suffix(result.c_file, "_api.h")
h_code = Code.CCodeWriter() h_code = Code.CCodeWriter()
Code.GlobalState(h_code) Code.GlobalState(h_code, self)
api_guard = Naming.api_guard_prefix + self.api_name(env) api_guard = Naming.api_guard_prefix + self.api_name(env)
h_code.put_h_guard(api_guard) h_code.put_h_guard(api_guard)
h_code.putln('#include "Python.h"') h_code.putln('#include "Python.h"')
...@@ -293,7 +308,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -293,7 +308,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
else: else:
emit_linenums = options.emit_linenums emit_linenums = options.emit_linenums
rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums, c_line_in_traceback=options.c_line_in_traceback) rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums, c_line_in_traceback=options.c_line_in_traceback)
globalstate = Code.GlobalState(rootwriter, emit_linenums) globalstate = Code.GlobalState(rootwriter, self, emit_linenums)
globalstate.initialize_main_c_code() globalstate.initialize_main_c_code()
h_code = globalstate['h_code'] h_code = globalstate['h_code']
...@@ -334,7 +349,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -334,7 +349,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
self.generate_declarations_for_modules(env, modules, globalstate) self.generate_declarations_for_modules(env, modules, globalstate)
h_code.write('\n') h_code.write('\n')
for utilcode in env.utility_code_list: for utilcode in env.utility_code_list[:]:
globalstate.use_utility_code(utilcode) globalstate.use_utility_code(utilcode)
globalstate.finalize_main_c_code() globalstate.finalize_main_c_code()
...@@ -1185,10 +1200,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1185,10 +1200,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type = scope.parent_type type = scope.parent_type
base_type = type.base_type base_type = type.base_type
py_attrs = [] py_attrs = []
memviewslice_attrs = []
for entry in scope.var_entries: for entry in scope.var_entries:
if entry.type.is_pyobject: if entry.type.is_pyobject:
py_attrs.append(entry) py_attrs.append(entry)
need_self_cast = type.vtabslot_cname or py_attrs elif entry.type.is_memoryviewslice:
memviewslice_attrs.append(entry)
need_self_cast = type.vtabslot_cname or py_attrs or memviewslice_attrs
code.putln("") code.putln("")
code.putln( code.putln(
"static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {" "static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
...@@ -1231,6 +1249,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -1231,6 +1249,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("p->%s = 0;" % entry.cname) code.putln("p->%s = 0;" % entry.cname)
else: else:
code.put_init_var_to_py_none(entry, "p->%s", nanny=False) code.put_init_var_to_py_none(entry, "p->%s", nanny=False)
for entry in memviewslice_attrs:
code.putln("p->%s.data = NULL;" % entry.cname)
code.putln("p->%s.memview = NULL;" % entry.cname)
entry = scope.lookup_here("__new__") entry = scope.lookup_here("__new__")
if entry and entry.is_special: if entry and entry.is_special:
if entry.trivial_signature: if entry.trivial_signature:
...@@ -2134,8 +2155,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2134,8 +2155,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# variables to None. # variables to None.
for entry in env.var_entries: for entry in env.var_entries:
if entry.visibility != 'extern': if entry.visibility != 'extern':
if entry.type.is_pyobject and entry.used: if entry.used:
code.put_init_var_to_py_none(entry, nanny=False) entry.type.global_init_code(entry, code)
def generate_c_variable_export_code(self, env, code): def generate_c_variable_export_code(self, env, code):
# Generate code to create PyCFunction wrappers for exported C functions. # Generate code to create PyCFunction wrappers for exported C functions.
...@@ -2237,7 +2258,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2237,7 +2258,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
# Generate type import code for extern extension types # Generate type import code for extern extension types
# and type ready code for non-extern ones. # and type ready code for non-extern ones.
for entry in env.c_class_entries: for entry in env.c_class_entries:
if entry.visibility == 'extern': if entry.visibility == 'extern' and not entry.utility_code_definition:
self.generate_type_import_code(env, entry.type, entry.pos, code) self.generate_type_import_code(env, entry.type, entry.pos, code)
else: else:
self.generate_base_type_import_code(env, entry, code) self.generate_base_type_import_code(env, entry, code)
...@@ -2247,8 +2268,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2247,8 +2268,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
def generate_base_type_import_code(self, env, entry, code): def generate_base_type_import_code(self, env, entry, code):
base_type = entry.type.base_type base_type = entry.type.base_type
if base_type and base_type.module_name != env.qualified_name \ if (base_type and base_type.module_name != env.qualified_name and not
and not base_type.is_builtin_type: base_type.is_builtin_type and not entry.utility_code_definition):
self.generate_type_import_code(env, base_type, self.pos, code) self.generate_type_import_code(env, base_type, self.pos, code)
def use_type_import_utility_code(self, env): def use_type_import_utility_code(self, env):
...@@ -2419,8 +2440,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -2419,8 +2440,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
type.typeptr_cname, type.typeobj_cname)) type.typeptr_cname, type.typeobj_cname))
def generate_cfunction_declaration(entry, env, code, definition): def generate_cfunction_declaration(entry, env, code, definition):
from_cy_utility = entry.used and entry.utility_code_definition
if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition
or entry.defined_in_pxd or entry.visibility == 'extern')): or entry.defined_in_pxd or entry.visibility == 'extern' or from_cy_utility)):
if entry.visibility == 'extern': if entry.visibility == 'extern':
storage_class = "%s " % Naming.extern_c_macro storage_class = "%s " % Naming.extern_c_macro
dll_linkage = "DL_IMPORT" dll_linkage = "DL_IMPORT"
......
...@@ -38,10 +38,8 @@ typeobj_prefix = pyrex_prefix + "type_" ...@@ -38,10 +38,8 @@ typeobj_prefix = pyrex_prefix + "type_"
var_prefix = pyrex_prefix + "v_" var_prefix = pyrex_prefix + "v_"
varptr_prefix = pyrex_prefix + "vp_" varptr_prefix = pyrex_prefix + "vp_"
wrapperbase_prefix= pyrex_prefix + "wrapperbase_" wrapperbase_prefix= pyrex_prefix + "wrapperbase_"
bufstruct_prefix = pyrex_prefix + "bstruct_" pybuffernd_prefix = pyrex_prefix + "pybuffernd_"
bufstride_prefix = pyrex_prefix + "bstride_" pybufferstruct_prefix = pyrex_prefix + "pybuffer_"
bufshape_prefix = pyrex_prefix + "bshape_"
bufsuboffset_prefix = pyrex_prefix + "boffset_"
vtable_prefix = pyrex_prefix + "vtable_" vtable_prefix = pyrex_prefix + "vtable_"
vtabptr_prefix = pyrex_prefix + "vtabptr_" vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_" vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
......
This diff is collapsed.
...@@ -67,11 +67,15 @@ old_style_globals = False ...@@ -67,11 +67,15 @@ old_style_globals = False
cimport_from_pyx = False cimport_from_pyx = False
# max # of dims for buffers -- set to same value as max # of dims for numpy
# arrays.
buffer_max_dims = 32
# Declare compiler directives # Declare compiler directives
directive_defaults = { directive_defaults = {
'boundscheck' : True, 'boundscheck' : True,
'nonecheck' : False, 'nonecheck' : False,
'initializedcheck' : True,
'embedsignature' : False, 'embedsignature' : False,
'locals' : {}, 'locals' : {},
'auto_cpdef': False, 'auto_cpdef': False,
......
...@@ -1037,7 +1037,8 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations): ...@@ -1037,7 +1037,8 @@ class ParallelRangeTransform(CythonTransform, SkipDeclarations):
directive = directive.rstrip('.') directive = directive.rstrip('.')
cls = self.directive_to_node.get(directive) cls = self.directive_to_node.get(directive)
if cls is None: if cls is None and not (self.namenode_is_cython_module and
self.parallel_directive[0] != 'parallel'):
error(node.pos, "Invalid directive: %s" % directive) error(node.pos, "Invalid directive: %s" % directive)
self.namenode_is_cython_module = False self.namenode_is_cython_module = False
...@@ -1255,7 +1256,7 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations): ...@@ -1255,7 +1256,7 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
""" """
def handle_function(self, node): def handle_function(self, node):
if not node.decorators: if not getattr(node, 'decorators', None):
return self.visit_Node(node) return self.visit_Node(node)
for i, decorator in enumerate(node.decorators): for i, decorator in enumerate(node.decorators):
...@@ -1289,6 +1290,8 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations): ...@@ -1289,6 +1290,8 @@ class CnameDirectivesTransform(CythonTransform, SkipDeclarations):
visit_FuncDefNode = handle_function visit_FuncDefNode = handle_function
visit_CClassDefNode = handle_function visit_CClassDefNode = handle_function
visit_CEnumDefNode = handle_function
visit_CStructOrUnionDefNode = handle_function
class ForwardDeclareTypes(CythonTransform): class ForwardDeclareTypes(CythonTransform):
...@@ -1576,6 +1579,14 @@ if VALUE is not None: ...@@ -1576,6 +1579,14 @@ if VALUE is not None:
self.visitchildren(node) self.visitchildren(node)
return None return None
def visit_CnameDecoratorNode(self, node):
self.visitchildren(node)
if not node.node:
return None
return node
def create_Property(self, entry): def create_Property(self, entry):
if entry.visibility == 'public': if entry.visibility == 'public':
if entry.type.is_pyobject: if entry.type.is_pyobject:
...@@ -2213,6 +2224,7 @@ class GilCheck(VisitorTransform): ...@@ -2213,6 +2224,7 @@ class GilCheck(VisitorTransform):
if self.env_stack and self.nogil and node.nogil_check: if self.env_stack and self.nogil and node.nogil_check:
node.nogil_check(self.env_stack[-1]) node.nogil_check(self.env_stack[-1])
self.visitchildren(node) self.visitchildren(node)
node.in_nogil_context = self.nogil
return node return node
......
...@@ -7,8 +7,8 @@ ctypedef object (*p_sub_expr_func)(object) ...@@ -7,8 +7,8 @@ ctypedef object (*p_sub_expr_func)(object)
# entry points # entry points
cpdef p_module(PyrexScanner s, pxd, full_module_name) cpdef p_module(PyrexScanner s, pxd, full_module_name, ctx=*)
cpdef p_code(PyrexScanner s, level= *) cpdef p_code(PyrexScanner s, level= *, ctx=*)
# internal parser states # internal parser states
...@@ -131,6 +131,8 @@ cdef p_calling_convention(PyrexScanner s) ...@@ -131,6 +131,8 @@ cdef p_calling_convention(PyrexScanner s)
cdef p_c_complex_base_type(PyrexScanner s) cdef p_c_complex_base_type(PyrexScanner s)
cpdef p_c_simple_base_type(PyrexScanner s, bint self_flag, bint nonempty, templates = *) cpdef p_c_simple_base_type(PyrexScanner s, bint self_flag, bint nonempty, templates = *)
cdef p_buffer_or_template(PyrexScanner s, base_type_node, templates) cdef p_buffer_or_template(PyrexScanner s, base_type_node, templates)
cdef is_memoryviewslice_access(PyrexScanner s)
cdef p_memoryviewslice_access(PyrexScanner s, base_type_node)
cdef bint looking_at_name(PyrexScanner s) except -2 cdef bint looking_at_name(PyrexScanner s) except -2
cdef bint looking_at_expr(PyrexScanner s) except -2 cdef bint looking_at_expr(PyrexScanner s) except -2
cdef bint looking_at_base_type(PyrexScanner s) except -2 cdef bint looking_at_base_type(PyrexScanner s) except -2
......
...@@ -33,6 +33,7 @@ class Ctx(object): ...@@ -33,6 +33,7 @@ class Ctx(object):
nogil = 0 nogil = 0
namespace = None namespace = None
templates = None templates = None
allow_struct_enum_decorator = False
def __init__(self, **kwds): def __init__(self, **kwds):
self.__dict__.update(kwds) self.__dict__.update(kwds)
...@@ -296,7 +297,8 @@ def p_typecast(s): ...@@ -296,7 +297,8 @@ def p_typecast(s):
pos = s.position() pos = s.position()
s.next() s.next()
base_type = p_c_base_type(s) base_type = p_c_base_type(s)
if base_type.name is None: is_memslice = isinstance(base_type, Nodes.MemoryViewSliceTypeNode)
if not is_memslice and base_type.name is None:
s.error("Unknown type") s.error("Unknown type")
declarator = p_c_declarator(s, empty = 1) declarator = p_c_declarator(s, empty = 1)
if s.sy == '?': if s.sy == '?':
...@@ -306,6 +308,10 @@ def p_typecast(s): ...@@ -306,6 +308,10 @@ def p_typecast(s):
typecheck = 0 typecheck = 0
s.expect(">") s.expect(">")
operand = p_factor(s) operand = p_factor(s)
if is_memslice:
return ExprNodes.CythonArrayNode(pos, base_type_node=base_type,
operand=operand)
return ExprNodes.TypecastNode(pos, return ExprNodes.TypecastNode(pos,
base_type = base_type, base_type = base_type,
declarator = declarator, declarator = declarator,
...@@ -1754,7 +1760,8 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1754,7 +1760,8 @@ def p_statement(s, ctx, first_statement = 0):
s.error('decorator not allowed here') s.error('decorator not allowed here')
s.level = ctx.level s.level = ctx.level
decorators = p_decorators(s) decorators = p_decorators(s)
if s.sy not in ('def', 'cdef', 'cpdef', 'class'): bad_toks = 'def', 'cdef', 'cpdef', 'class'
if not ctx.allow_struct_enum_decorator and s.sy not in bad_toks:
s.error("Decorators can only be followed by functions or classes") s.error("Decorators can only be followed by functions or classes")
elif s.sy == 'pass' and cdef_flag: elif s.sy == 'pass' and cdef_flag:
# empty cdef block # empty cdef block
...@@ -1774,7 +1781,10 @@ def p_statement(s, ctx, first_statement = 0): ...@@ -1774,7 +1781,10 @@ def p_statement(s, ctx, first_statement = 0):
s.level = ctx.level s.level = ctx.level
node = p_cdef_statement(s, ctx(overridable = overridable)) node = p_cdef_statement(s, ctx(overridable = overridable))
if decorators is not None: if decorators is not None:
if not isinstance(node, (Nodes.CFuncDefNode, Nodes.CVarDefNode, Nodes.CClassDefNode)): tup = Nodes.CFuncDefNode, Nodes.CVarDefNode, Nodes.CClassDefNode
if ctx.allow_struct_enum_decorator:
tup += Nodes.CStructOrUnionDefNode, Nodes.CEnumDefNode
if not isinstance(node, tup):
s.error("Decorators can only be followed by functions or classes") s.error("Decorators can only be followed by functions or classes")
node.decorators = decorators node.decorators = decorators
return node return node
...@@ -2002,8 +2012,12 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None): ...@@ -2002,8 +2012,12 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
complex = complex, longness = longness, complex = complex, longness = longness,
is_self_arg = self_flag, templates = templates) is_self_arg = self_flag, templates = templates)
# declarations here.
if s.sy == '[': if s.sy == '[':
type_node = p_buffer_or_template(s, type_node, templates) if is_memoryviewslice_access(s):
type_node = p_memoryviewslice_access(s, type_node)
else:
type_node = p_buffer_or_template(s, type_node, templates)
if s.sy == '.': if s.sy == '.':
s.next() s.next()
...@@ -2034,6 +2048,63 @@ def p_buffer_or_template(s, base_type_node, templates): ...@@ -2034,6 +2048,63 @@ def p_buffer_or_template(s, base_type_node, templates):
base_type_node = base_type_node) base_type_node = base_type_node)
return result return result
def p_bracketed_base_type(s, base_type_node, nonempty, empty):
# s.sy == '['
if empty and not nonempty:
# sizeof-like thing. Only anonymous C arrays allowed (int[SIZE]).
return base_type_node
elif not empty and nonempty:
# declaration of either memoryview slice or buffer.
if is_memoryviewslice_access(s):
return p_memoryviewslice_access(s, base_type_node)
else:
return p_buffer_or_template(s, base_type_node, None)
# return p_buffer_access(s, base_type_node)
elif not empty and not nonempty:
# only anonymous C arrays and memoryview slice arrays here. We
# disallow buffer declarations for now, due to ambiguity with anonymous
# C arrays.
if is_memoryviewslice_access(s):
return p_memoryviewslice_access(s, base_type_node)
else:
return base_type_node
def is_memoryviewslice_access(s):
# s.sy == '['
# a memoryview slice declaration is distinguishable from a buffer access
# declaration by the first entry in the bracketed list. The buffer will
# not have an unnested colon in the first entry; the memoryview slice will.
saved = [(s.sy, s.systring)]
s.next()
retval = False
if s.systring == ':':
retval = True
elif s.sy == 'INT':
saved.append((s.sy, s.systring))
s.next()
if s.sy == ':':
retval = True
for sv in saved[::-1]:
s.put_back(*sv)
return retval
def p_memoryviewslice_access(s, base_type_node):
# s.sy == '['
pos = s.position()
s.next()
subscripts = p_subscript_list(s)
# make sure each entry in subscripts is a slice
for subscript in subscripts:
if len(subscript) < 2:
s.error("An axis specification in memoryview declaration does not have a ':'.")
s.expect(']')
indexes = make_slice_nodes(pos, subscripts)
result = Nodes.MemoryViewSliceTypeNode(pos,
base_type_node = base_type_node,
axes = indexes)
return result
def looking_at_name(s): def looking_at_name(s):
return s.sy == 'IDENT' and not s.systring in calling_convention_words return s.sy == 'IDENT' and not s.systring in calling_convention_words
...@@ -2831,8 +2902,8 @@ def p_doc_string(s): ...@@ -2831,8 +2902,8 @@ def p_doc_string(s):
else: else:
return None return None
def p_code(s, level=None): def p_code(s, level=None, ctx=Ctx):
body = p_statement_list(s, Ctx(level = level), first_statement = 1) body = p_statement_list(s, ctx(level = level), first_statement = 1)
if s.sy != 'EOF': if s.sy != 'EOF':
s.error("Syntax error in statement [%s,%s]" % ( s.error("Syntax error in statement [%s,%s]" % (
repr(s.sy), repr(s.systring))) repr(s.sy), repr(s.systring)))
...@@ -2854,7 +2925,7 @@ def p_compiler_directive_comments(s): ...@@ -2854,7 +2925,7 @@ def p_compiler_directive_comments(s):
s.next() s.next()
return result return result
def p_module(s, pxd, full_module_name): def p_module(s, pxd, full_module_name, ctx=Ctx):
pos = s.position() pos = s.position()
directive_comments = p_compiler_directive_comments(s) directive_comments = p_compiler_directive_comments(s)
...@@ -2869,7 +2940,7 @@ def p_module(s, pxd, full_module_name): ...@@ -2869,7 +2940,7 @@ def p_module(s, pxd, full_module_name):
else: else:
level = 'module' level = 'module'
body = p_statement_list(s, Ctx(level = level), first_statement = 1) body = p_statement_list(s, ctx(level=level), first_statement = 1)
if s.sy != 'EOF': if s.sy != 'EOF':
s.error("Syntax error in statement [%s,%s]" % ( s.error("Syntax error in statement [%s,%s]" % (
repr(s.sy), repr(s.systring))) repr(s.sy), repr(s.systring)))
...@@ -2977,4 +3048,3 @@ def print_parse_tree(f, node, level, key = None): ...@@ -2977,4 +3048,3 @@ def print_parse_tree(f, node, level, key = None):
f.write("%s]\n" % ind) f.write("%s]\n" % ind)
return return
f.write("%s%s\n" % (ind, node)) f.write("%s%s\n" % (ind, node))
...@@ -4,6 +4,7 @@ from time import time ...@@ -4,6 +4,7 @@ from time import time
import Errors import Errors
import DebugFlags import DebugFlags
import Options import Options
from Visitor import CythonTransform
from Errors import PyrexError, CompileError, InternalError, AbortError, error from Errors import PyrexError, CompileError, InternalError, AbortError, error
# #
...@@ -72,22 +73,41 @@ def use_utility_code_definitions(scope, target): ...@@ -72,22 +73,41 @@ def use_utility_code_definitions(scope, target):
def inject_utility_code_stage_factory(context): def inject_utility_code_stage_factory(context):
def inject_utility_code_stage(module_node): def inject_utility_code_stage(module_node):
# First, make sure any utility code pulled in by using symbols in the cython
# scope is included
use_utility_code_definitions(context.cython_scope, module_node.scope)
added = [] added = []
# Note: the list might be extended inside the loop (if some utility code # Note: the list might be extended inside the loop (if some utility code
# pulls in other utility code) # pulls in other utility code, explicitly or implicitly)
for utilcode in module_node.scope.utility_code_list: for utilcode in module_node.scope.utility_code_list:
if utilcode in added: continue if utilcode in added: continue
added.append(utilcode) added.append(utilcode)
if utilcode.requires:
for dep in utilcode.requires:
if not dep in added and not dep in module_node.scope.utility_code_list:
module_node.scope.utility_code_list.append(dep)
tree = utilcode.get_tree() tree = utilcode.get_tree()
if tree: if tree:
module_node.merge_in(tree.body, tree.scope, merge_scope=True) module_node.merge_in(tree.body, tree.scope, merge_scope=True)
return module_node return module_node
return inject_utility_code_stage return inject_utility_code_stage
class UseUtilityCodeDefinitions(CythonTransform):
# Temporary hack to use any utility code in nodes' "utility_code_definitions".
# This should be moved to the code generation phase of the relevant nodes once
# it is safe to generate CythonUtilityCode at code generation time.
def __call__(self, node):
self.scope = node.scope
return super(UseUtilityCodeDefinitions, self).__call__(node)
def visit_AttributeNode(self, node):
if node.entry and node.entry.utility_code_definition:
self.scope.use_utility_code(node.entry.utility_code_definition)
return node
def visit_NameNode(self, node):
for e in (node.entry, node.type_entry):
if e and e.utility_code_definition:
self.scope.use_utility_code(e.utility_code_definition)
return node
# #
# Pipeline factories # Pipeline factories
# #
...@@ -113,6 +133,8 @@ def create_pipeline(context, mode, exclude_classes=()): ...@@ -113,6 +133,8 @@ def create_pipeline(context, mode, exclude_classes=()):
from Optimize import DropRefcountingTransform from Optimize import DropRefcountingTransform
from Buffer import IntroduceBufferAuxiliaryVars from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_declarations, check_c_declarations_pxd from ModuleNode import check_c_declarations, check_c_declarations_pxd
from ModuleNode import check_c_declarations
if mode == 'pxd': if mode == 'pxd':
_check_c_declarations = check_c_declarations_pxd _check_c_declarations = check_c_declarations_pxd
...@@ -165,6 +187,7 @@ def create_pipeline(context, mode, exclude_classes=()): ...@@ -165,6 +187,7 @@ def create_pipeline(context, mode, exclude_classes=()):
DropRefcountingTransform(), DropRefcountingTransform(),
FinalOptimizePhase(context), FinalOptimizePhase(context),
GilCheck(), GilCheck(),
UseUtilityCodeDefinitions(context),
] ]
filtered_stages = [] filtered_stages = []
for s in stages: for s in stages:
...@@ -265,7 +288,9 @@ def insert_into_pipeline(pipeline, transform, before=None, after=None): ...@@ -265,7 +288,9 @@ def insert_into_pipeline(pipeline, transform, before=None, after=None):
# Running a pipeline # Running a pipeline
# #
def run_pipeline(pipeline, source): def run_pipeline(pipeline, source, printtree=True):
from Cython.Compiler.Visitor import PrintTree
error = None error = None
data = source data = source
try: try:
...@@ -275,6 +300,8 @@ def run_pipeline(pipeline, source): ...@@ -275,6 +300,8 @@ def run_pipeline(pipeline, source):
if DebugFlags.debug_verbose_pipeline: if DebugFlags.debug_verbose_pipeline:
t = time() t = time()
print "Entering pipeline phase %r" % phase print "Entering pipeline phase %r" % phase
if not printtree and isinstance(phase, PrintTree):
continue
data = phase(data) data = phase(data)
if DebugFlags.debug_verbose_pipeline: if DebugFlags.debug_verbose_pipeline:
print " %.3f seconds" % (time() - t) print " %.3f seconds" % (time() - t)
......
This diff is collapsed.
...@@ -39,12 +39,9 @@ def c_safe_identifier(cname): ...@@ -39,12 +39,9 @@ def c_safe_identifier(cname):
class BufferAux(object): class BufferAux(object):
writable_needed = False writable_needed = False
def __init__(self, buffer_info_var, stridevars, shapevars, def __init__(self, buflocal_nd_var, rcbuf_var):
suboffsetvars): self.buflocal_nd_var = buflocal_nd_var
self.buffer_info_var = buffer_info_var self.rcbuf_var = rcbuf_var
self.stridevars = stridevars
self.shapevars = shapevars
self.suboffsetvars = suboffsetvars
def __repr__(self): def __repr__(self):
return "<BufferAux %r>" % self.__dict__ return "<BufferAux %r>" % self.__dict__
...@@ -127,6 +124,8 @@ class Entry(object): ...@@ -127,6 +124,8 @@ class Entry(object):
# used uninitialized # used uninitialized
# cf_used boolean Entry is used # cf_used boolean Entry is used
# TODO: utility_code and utility_code_definition serves the same purpose...
inline_func_in_pxd = False inline_func_in_pxd = False
borrowed = 0 borrowed = 0
init = "" init = ""
...@@ -292,22 +291,21 @@ class Scope(object): ...@@ -292,22 +291,21 @@ class Scope(object):
entries = [(name, entry) entries = [(name, entry)
for name, entry in other.entries.iteritems() for name, entry in other.entries.iteritems()
if entry.used or merge_unused] if entry.used or merge_unused]
# !@#$ py23
entries = dict(entries)
self.entries.update(entries) self.entries.update(entries)
for attr in ('const_entries', for attr in ('const_entries',
'type_entries', 'type_entries',
'sue_entries', 'sue_entries',
'arg_entries', 'arg_entries',
'var_entries', 'var_entries',
'pyfunc_entries', 'pyfunc_entries',
'cfunc_entries', 'cfunc_entries',
'c_class_entries'): 'c_class_entries'):
self_entries = getattr(self, attr) self_entries = getattr(self, attr)
names = set([e.name for e in self_entries])
for entry in getattr(other, attr): for entry in getattr(other, attr):
if entry.used or merge_unused: if (entry.used or merge_unused) and entry.name not in names:
self_entries.append(entry) self_entries.append(entry)
def __str__(self): def __str__(self):
...@@ -383,6 +381,11 @@ class Scope(object): ...@@ -383,6 +381,11 @@ class Scope(object):
# entries[name] = entry # entries[name] = entry
if not shadow: if not shadow:
entries[name] = entry entries[name] = entry
if type.is_memoryviewslice:
import MemoryView
entry.init = MemoryView.memslice_entry_init
entry.scope = self entry.scope = self
entry.visibility = visibility entry.visibility = visibility
return entry return entry
...@@ -1163,7 +1166,7 @@ class ModuleScope(Scope): ...@@ -1163,7 +1166,7 @@ class ModuleScope(Scope):
def declare_c_class(self, name, pos, defining = 0, implementing = 0, def declare_c_class(self, name, pos, defining = 0, implementing = 0,
module_name = None, base_type = None, objstruct_cname = None, module_name = None, base_type = None, objstruct_cname = None,
typeobj_cname = None, visibility = 'private', typedef_flag = 0, api = 0, typeobj_cname = None, typeptr_cname = None, visibility = 'private', typedef_flag = 0, api = 0,
buffer_defaults = None, shadow = 0): buffer_defaults = None, shadow = 0):
# If this is a non-extern typedef class, expose the typedef, but use # If this is a non-extern typedef class, expose the typedef, but use
# the non-typedef struct internally to avoid needing forward # the non-typedef struct internally to avoid needing forward
...@@ -1205,7 +1208,10 @@ class ModuleScope(Scope): ...@@ -1205,7 +1208,10 @@ class ModuleScope(Scope):
type.module_name = module_name type.module_name = module_name
else: else:
type.module_name = self.qualified_name type.module_name = self.qualified_name
type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name) if typeptr_cname:
type.typeptr_cname = typeptr_cname
else:
type.typeptr_cname = self.mangle(Naming.typeptr_prefix, name)
entry = self.declare_type(name, type, pos, visibility = visibility, entry = self.declare_type(name, type, pos, visibility = visibility,
defining = 0, shadow = shadow) defining = 0, shadow = shadow)
entry.is_cclass = True entry.is_cclass = True
......
...@@ -98,3 +98,8 @@ class TestBufferOptions(CythonTest): ...@@ -98,3 +98,8 @@ class TestBufferOptions(CythonTest):
self.assert_(stats[1].base_type.ndim == 3) self.assert_(stats[1].base_type.ndim == 3)
# add exotic and impossible combinations as they come along... # add exotic and impossible combinations as they come along...
if __name__ == '__main__':
import unittest
unittest.main()
from Cython.TestUtils import CythonTest
import Cython.Compiler.Errors as Errors
from Cython.Compiler.Nodes import *
from Cython.Compiler.ParseTreeTransforms import *
from Cython.Compiler.Buffer import *
class TestMemviewParsing(CythonTest):
def parse(self, s):
return self.should_not_fail(lambda: self.fragment(s)).root
def not_parseable(self, expected_error, s):
e = self.should_fail(lambda: self.fragment(s), Errors.CompileError)
self.assertEqual(expected_error, e.message_only)
def test_default_1dim(self):
self.parse(u"cdef int[:] x")
self.parse(u"cdef short int[:] x")
def test_default_ndim(self):
self.parse(u"cdef int[:,:,:,:,:] x")
self.parse(u"cdef unsigned long int[:,:,:,:,:] x")
self.parse(u"cdef unsigned int[:,:,:,:,:] x")
def test_zero_offset(self):
self.parse(u"cdef long double[0:] x")
self.parse(u"cdef int[0:] x")
def test_zero_offset_ndim(self):
self.parse(u"cdef int[0:,0:,0:,0:] x")
def test_def_arg(self):
self.parse(u"def foo(int[:,:] x): pass")
def test_cdef_arg(self):
self.parse(u"cdef foo(int[:,:] x): pass")
def test_general_slice(self):
self.parse(u'cdef float[::ptr, ::direct & contig, 0::full & strided] x')
def test_non_slice_memview(self):
self.not_parseable(u"An axis specification in memoryview declaration does not have a ':'.",
u"cdef double[:foo, bar] x")
self.not_parseable(u"An axis specification in memoryview declaration does not have a ':'.",
u"cdef double[0:foo, bar] x")
def test_basic(self):
t = self.parse(u"cdef int[:] x")
memv_node = t.stats[0].base_type
self.assert_(isinstance(memv_node, MemoryViewSliceTypeNode))
# we also test other similar declarations (buffers, anonymous C arrays)
# since the parsing has to distinguish between them.
def disable_test_no_buf_arg(self): # TODO
self.not_parseable(u"Expected ']'",
u"cdef extern foo(object[int, ndim=2])")
def disable_test_parse_sizeof(self): # TODO
self.parse(u"sizeof(int[NN])")
self.parse(u"sizeof(int[])")
self.parse(u"sizeof(int[][NN])")
self.not_parseable(u"Expected an identifier or literal",
u"sizeof(int[:NN])")
self.not_parseable(u"Expected ']'",
u"sizeof(foo[dtype=bar]")
if __name__ == '__main__':
import unittest
unittest.main()
import unittest
from Cython.Compiler import Code, UtilityCode
def strip_2tup(tup):
return tup[0] and tup[0].strip(), tup[1] and tup[1].strip()
class TestUtilityLoader(unittest.TestCase):
"""
Test loading UtilityCodes
"""
expected = "test {{loader}} prototype", "test {{loader}} impl"
expected_tempita = (expected[0].replace('{{loader}}', 'Loader'),
expected[1].replace('{{loader}}', 'Loader'))
required = "I am a dependency proto", "I am a dependency impl"
context = dict(loader='Loader')
name = "TestUtilityLoader"
filename = "TestUtilityLoader.c"
cls = Code.UtilityCode
def test_load_as_string(self):
got = strip_2tup(self.cls.load_as_string(self.name))
self.assertEquals(got, self.expected)
got = strip_2tup(self.cls.load_as_string(self.name, self.filename))
self.assertEquals(got, self.expected)
got = strip_2tup(self.cls.load_as_string(self.name, context=self.context))
self.assertEquals(got, self.expected_tempita)
def test_load(self):
utility = self.cls.load(self.name)
got = strip_2tup((utility.proto, utility.impl))
self.assertEquals(got, self.expected)
# Not implemented yet
#required, = utility.requires
#self.assertEquals((required.proto, required.impl), self.required)
utility = self.cls.load(self.name, from_file=self.filename)
got = strip_2tup((utility.proto, utility.impl))
self.assertEquals(got, self.expected)
class TestCythonUtilityLoader(TestUtilityLoader):
"""
Test loading CythonUtilityCodes
"""
# Just change the attributes and run the same tests
expected = None, "test {{cy_loader}} impl"
expected_tempita = None, "test CyLoader impl"
required = None, "I am a Cython dependency impl"
context = dict(cy_loader='CyLoader')
name = "TestCyUtilityLoader"
filename = "TestCyUtilityLoader.pyx"
cls = UtilityCode.CythonUtilityCode
# Small hack to pass our tests above
cls.proto = None
\ No newline at end of file
...@@ -32,7 +32,7 @@ class StringParseContext(Main.Context): ...@@ -32,7 +32,7 @@ class StringParseContext(Main.Context):
return ModuleScope(module_name, parent_module = None, context = self) return ModuleScope(module_name, parent_module = None, context = self)
def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None, def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None,
context=None): context=None, allow_struct_enum_decorator=False):
""" """
Utility method to parse a (unicode) string of code. This is mostly Utility method to parse a (unicode) string of code. This is mostly
used for internal Cython compiler purposes (creating code snippets used for internal Cython compiler purposes (creating code snippets
...@@ -66,12 +66,15 @@ def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None, ...@@ -66,12 +66,15 @@ def parse_from_strings(name, code, pxds={}, level=None, initial_pos=None,
scanner = PyrexScanner(buf, code_source, source_encoding = encoding, scanner = PyrexScanner(buf, code_source, source_encoding = encoding,
scope = scope, context = context, initial_pos = initial_pos) scope = scope, context = context, initial_pos = initial_pos)
ctx = Parsing.Ctx(allow_struct_enum_decorator=allow_struct_enum_decorator)
if level is None: if level is None:
tree = Parsing.p_module(scanner, 0, module_name) tree = Parsing.p_module(scanner, 0, module_name, ctx=ctx)
tree.scope = scope tree.scope = scope
tree.is_pxd = False tree.is_pxd = False
else: else:
tree = Parsing.p_code(scanner, level=level) tree = Parsing.p_code(scanner, level=level, ctx=ctx)
tree.scope = scope tree.scope = scope
return tree return tree
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
########## TestCyUtilityLoader ##########
test {{cy_loader}} impl
This diff is collapsed.
////////// TestUtilityLoader.proto //////////
test {{loader}} prototype
////////// TestUtilityLoader //////////
test {{loader}} impl
This diff is collapsed.
This diff is collapsed.
...@@ -17,7 +17,8 @@ include Demos/embed/* ...@@ -17,7 +17,8 @@ include Demos/embed/*
include Demos/freeze/* include Demos/freeze/*
include Demos/libraries/* include Demos/libraries/*
include Demos/Makefile* include Demos/Makefile*
recursive-include Cython/Debugger/Tests * recursive-include Cython/Debugger/Tests *.pyx *.pxd *.c *.h
recursive-include Cython/Utility *.pyx *.pxd *.c *.h .cpp
recursive-include Tools * recursive-include Tools *
recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt recursive-include tests *.pyx *.pxd *.pxi *.py *.h *.BROKEN bugs.txt
recursive-include tests *_lib.cpp *.srctree recursive-include tests *_lib.cpp *.srctree
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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