Commit 88aea80c authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Main.py has transformation pipelines for pxds; allowing buffer funcs in pxds

parent eaa6d477
......@@ -104,7 +104,7 @@ def report_error(err):
def error(position, message):
#print "Errors.error:", repr(position), repr(message) ###
err = CompileError(position, message)
# if position is not None: raise Exception(err) # debug
# if position is not None: raise Exception(err) # debug
report_error(err)
return err
......
......@@ -27,6 +27,11 @@ module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_
verbose = 0
def dumptree(t):
# For quick debugging in pipelines
print t.dump()
return t
class Context:
# This class encapsulates the context needed for compiling
# one or more Cython implementation files along with their
......@@ -42,18 +47,78 @@ class Context:
#self.modules = {"__builtin__" : BuiltinScope()}
import Builtin
self.modules = {"__builtin__" : Builtin.builtin_scope}
self.pxds = {}
self.pyxs = {}
self.include_directories = include_directories
self.future_directives = set()
import os.path
standard_include_path = os.path.abspath(
os.path.join(os.path.dirname(__file__), '..', 'Includes'))
self.include_directories = include_directories + [standard_include_path]
def create_pipeline(self, pxd):
from Visitor import PrintTree
from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse
from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from Optimize import FlattenInListTransform, SwitchTransform, OptimizeRefcounting
from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_classes
if pxd:
_check_c_classes = None
_specific_post_parse = PxdPostParse(self)
else:
_check_c_classes = check_c_classes
_specific_post_parse = None
return [
NormalizeTree(self),
PostParse(self),
_specific_post_parse,
FlattenInListTransform(),
WithTransform(self),
DecoratorTransform(self),
AnalyseDeclarationsTransform(self),
IntroduceBufferAuxiliaryVars(self),
_check_c_classes,
AnalyseExpressionsTransform(self),
SwitchTransform(),
OptimizeRefcounting(self),
# CreateClosureClasses(context),
]
def create_pyx_pipeline(self, options, result):
return [create_parse(self)] + self.create_pipeline(pxd=False) + [
create_generate_code(self, options, result)
]
def create_pxd_pipeline(self, scope, module_name):
def parse_pxd(source_desc):
tree = self.parse(source_desc, scope, pxd=True,
full_module_name=module_name)
tree.scope = scope
tree.is_pxd = True
return tree
return [parse_pxd] + self.create_pipeline(pxd=True)
def process_pxd(self, source_desc, scope, module_name):
pipeline = self.create_pxd_pipeline(scope, module_name)
return self.run_pipeline(pipeline, source_desc)
def nonfatal_error(self, exc):
return Errors.report_error(exc)
def run_pipeline(self, pipeline, source):
errors_occurred = False
data = source
try:
for phase in pipeline:
if phase is not None:
data = phase(data)
except CompileError, err:
errors_occurred = True
Errors.report_error(err)
return (errors_occurred, data)
def find_module(self, module_name,
relative_to = None, pos = None, need_pxd = 1):
# Finds and returns the module scope corresponding to
......@@ -106,9 +171,7 @@ class Context:
if debug_find_module:
print("Context.find_module: Parsing %s" % pxd_pathname)
source_desc = FileSourceDescriptor(pxd_pathname)
pxd_tree = self.parse(source_desc, scope, pxd = 1,
full_module_name = module_name)
pxd_tree.analyse_declarations(scope)
self.process_pxd(source_desc, scope, module_name)
except CompileError:
pass
return scope
......@@ -330,20 +393,6 @@ class Context:
verbose_flag = options.show_version,
cplus = options.cplus)
def nonfatal_error(self, exc):
return Errors.report_error(exc)
def run_pipeline(self, pipeline, source):
errors_occurred = False
data = source
try:
for phase in pipeline:
data = phase(data)
except CompileError, err:
errors_occurred = True
Errors.report_error(err)
return (errors_occurred, data)
def create_parse(context):
def parse(compsrc):
source_desc = compsrc.source_desc
......@@ -353,6 +402,7 @@ def create_parse(context):
tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
tree.compilation_source = compsrc
tree.scope = scope
tree.is_pxd = False
return tree
return parse
......@@ -364,34 +414,6 @@ def create_generate_code(context, options, result):
return result
return generate_code
def create_default_pipeline(context, options, result):
from Visitor import PrintTree
from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse
from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
from Optimize import FlattenInListTransform, SwitchTransform, OptimizeRefcounting
from Buffer import IntroduceBufferAuxiliaryVars
from ModuleNode import check_c_classes
def printit(x): print x.dump()
return [
create_parse(context),
# printit,
NormalizeTree(context),
PostParse(context),
FlattenInListTransform(),
WithTransform(context),
DecoratorTransform(context),
AnalyseDeclarationsTransform(context),
IntroduceBufferAuxiliaryVars(context),
check_c_classes,
AnalyseExpressionsTransform(context),
# BufferTransform(context),
SwitchTransform(),
OptimizeRefcounting(context),
# CreateClosureClasses(context),
create_generate_code(context, options, result)
]
def create_default_resultobj(compilation_source, options):
result = CompilationResult()
result.main_source_file = compilation_source.source_desc.filename
......@@ -428,7 +450,7 @@ def run_pipeline(source, options, full_module_name = None):
result = create_default_resultobj(source, options)
# Get pipeline
pipeline = create_default_pipeline(context, options, result)
pipeline = context.create_pyx_pipeline(options, result)
context.setup_errors(options)
errors_occurred, enddata = context.run_pipeline(pipeline, source)
......
......@@ -213,6 +213,42 @@ class PostParse(CythonTransform):
node.keyword_args = None
return node
class PxdPostParse(CythonTransform):
"""
Basic interpretation/validity checking that should only be
done on pxd trees.
"""
ERR_FUNCDEF_NOT_ALLOWED = 'function definition not allowed here'
def __call__(self, node):
self.scope_type = 'pxd'
return super(PxdPostParse, self).__call__(node)
def visit_CClassDefNode(self, node):
old = self.scope_type
self.scope_type = 'cclass'
self.visitchildren(node)
self.scope_type = old
return node
def visit_FuncDefNode(self, node):
# FuncDefNode always come with an implementation (without
# an imp they are CVarDefNodes..)
ok = False
if (isinstance(node, DefNode) and self.scope_type == 'cclass'
and node.name in ('__getbuffer__', '__releasebuffer__')):
ok = True
if not ok:
self.context.nonfatal_error(PostParseError(node.pos,
self.ERR_FUNCDEF_NOT_ALLOWED))
return None
else:
return node
class WithTransform(CythonTransform):
# EXCINFO is manually set to a variable that contains
......
......@@ -1398,7 +1398,7 @@ def p_statement(s, ctx, first_statement = 0):
if ctx.api:
error(s.pos, "'api' not allowed with this statement")
elif s.sy == 'def':
if ctx.level not in ('module', 'class', 'c_class', 'property'):
if ctx.level not in ('module', 'class', 'c_class', 'c_class_pxd', 'property'):
s.error('def statement not allowed here')
s.level = ctx.level
return p_def_statement(s)
......
......@@ -2,16 +2,25 @@ cdef extern from "Python.h":
ctypedef int Py_intptr_t
cdef extern from "numpy/arrayobject.h":
ctypedef void PyArrayObject
ctypedef class numpy.ndarray [object PyArrayObject]:
cdef char *data
cdef int nd
cdef Py_intptr_t *dimensions
cdef Py_intptr_t *strides
cdef object base
# descr not implemented yet here...
cdef int flags
cdef int itemsize
cdef object weakreflist
cdef:
char *data
int nd
Py_intptr_t *dimensions
Py_intptr_t *strides
object base
# descr not implemented yet here...
int flags
int itemsize
object weakreflist
def __getbuffer__(self, Py_buffer* info, int flags):
pass
ctypedef unsigned int npy_uint8
ctypedef unsigned int npy_uint16
......@@ -27,4 +36,5 @@ cdef extern from "numpy/arrayobject.h":
ctypedef float npy_float96
ctypedef float npy_float128
ctypedef npy_int64 Tint64
cimport e_pxdimpl_imported
_ERRORS = """
6:4: function definition not allowed here
18:4: function definition not allowed here
23:8: function definition not allowed here
"""
cdef class A:
cdef int test(self)
# Should give error:
def somefunc(self):
pass
# While this should *not* be an error...:
def __getbuffer__(self, Py_buffer* info, int flags):
pass
# This neither:
def __releasebuffer__(self, Py_buffer* info):
pass
# Terminate with an error to be sure the compiler is
# not terminating prior to previous errors
def terminate(self):
pass
cdef extern from "foo.h":
cdef class pxdimpl.B [object MyB]:
def otherfunc(self):
pass
......@@ -11,7 +11,7 @@
cimport stdlib
cimport python_buffer
# Add all test_X function docstrings as unit tests
cimport stdio
__test__ = {}
setup_string = """
......@@ -571,8 +571,6 @@ available_flags = (
('WRITABLE', python_buffer.PyBUF_WRITABLE)
)
cimport stdio
cdef class MockBuffer:
cdef object format
cdef void* buffer
......
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