Commit e6185bed authored by Danilo Freitas's avatar Danilo Freitas

Templates

parent 181d2df5
......@@ -1123,6 +1123,7 @@ class ImagNode(AtomicNewTempExprNode):
class NewExprNode(AtomicExprNode):
def analyse_types(self, env):
print self.cppclass
entry = env.lookup(self.cppclass)
if entry is None or not entry.is_cpp_class:
error(self.pos, "new operator can only be applied to a C++ class")
......
......@@ -721,11 +721,13 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
else:
type = py_object_type
self.arg_name = self.name
elif self.templates:
if not self.name in self.templates:
error(self.pos, "'%s' is not a type identifier" % self.name)
else:
error(self.pos, "'%s' is not a type identifier" % self.name)
if self.templates:
if not self.name in self.templates:
error(self.pos, "'%s' is not a type identifier" % self.name)
type = PyrexTypes.TemplatedType(self.name)
else:
error(self.pos, "'%s' is not a type identifier" % self.name)
if self.complex:
if not type.is_numeric or type.is_complex:
error(self.pos, "can only complexify c numeric types")
......@@ -736,6 +738,24 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
else:
return PyrexTypes.error_type
class TemplatedTypeNode(CBaseTypeNode):
# name
# base_type_node CSimpleBaseTypeNode
# templates [CSimpleBaseTypeNode]
child_attrs = ["base_type_node", "templates"]
def analyse(self, env, could_be_name = False):
entry = env.lookup(self.base_type_node.name)
base_types = entry.type.templates
if not base_types:
error(self.pos, "%s type is not a template" % entry.type)
if len(base_types) != len(self.templates):
error(self.pos, "%s templated type receives %d arguments, got %d" %
(entry.type, len(base_types), len(self.templates)))
print entry.type
return entry.type
class CBufferAccessTypeNode(CBaseTypeNode):
# After parsing:
# positional_args [ExprNode] List of positional arguments
......@@ -935,7 +955,7 @@ class CppClassNode(CStructOrUnionDefNode):
base_class_types.append(base_class_entry.type)
self.entry = env.declare_cpp_class(
self.name, "cppclass", scope, 0, self.pos,
self.cname, base_class_types, visibility = self.visibility)
self.cname, base_class_types, visibility = self.visibility, templates = self.templates)
self.entry.is_cpp_class = 1
if self.attributes is not None:
if self.in_pxd and not env.in_cinclude:
......
......@@ -1787,29 +1787,50 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
# (This means that buffers cannot occur where there can be empty declarators,
# which is an ok restriction to make.)
if nonempty and s.sy == '[':
return p_buffer_access(s, type_node)
return p_buffer_or_template(s, type_node)
else:
return type_node
def p_buffer_access(s, base_type_node):
def p_buffer_or_template(s, base_type_node):
# s.sy == '['
pos = s.position()
s.next()
positional_args, keyword_args = (
p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
)
s.expect(']')
if s.systring == 'int' or s.systring == 'long':
positional_args, keyword_args = (
p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
)
if keyword_args:
error(pos, "Keyword arguments not allowed for template types")
s.expect(']')
keyword_dict = ExprNodes.DictNode(pos,
key_value_pairs = [
ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
for key, value in keyword_args
])
result = Nodes.TemplatedTypeNode(pos, base_type_node = base_type_node,
templates = positional_args)
else:
positional_args, keyword_args = (
p_positional_and_keyword_args(s, (']',), (0,), ('dtype',))
)
if positional_args:
if positional_args[0] != 'int' or positional_args != 'long':
if keyword_args:
error(pos, "Keyword arguments not allowed for template types")
s.expect(']')
result = Nodes.CBufferAccessTypeNode(pos,
positional_args = positional_args,
keyword_args = keyword_dict,
base_type_node = base_type_node)
result = Nodes.TemplatedTypeNode(pos, base_type_node = base_type_node,
templates = positional_args)
else:
s.expect(']')
keyword_dict = ExprNodes.DictNode(pos,
key_value_pairs = [
ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
for key, value in keyword_args
])
result = Nodes.CBufferAccessTypeNode(pos,
positional_args = positional_args,
keyword_args = keyword_dict,
base_type_node = base_type_node)
return result
......
......@@ -1015,13 +1015,15 @@ class CFuncType(CType):
# calling_convention string Function calling convention
# nogil boolean Can be called without gil
# with_gil boolean Acquire gil around function body
# templates [string] or None
is_cfunction = 1
original_sig = None
def __init__(self, return_type, args, has_varargs = 0,
exception_value = None, exception_check = 0, calling_convention = "",
nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0):
nogil = 0, with_gil = 0, is_overridable = 0, optional_arg_count = 0,
templates = None):
self.return_type = return_type
self.args = args
self.has_varargs = has_varargs
......@@ -1032,6 +1034,7 @@ class CFuncType(CType):
self.nogil = nogil
self.with_gil = with_gil
self.is_overridable = is_overridable
self.templates = templates
def __repr__(self):
arg_reprs = map(repr, self.args)
......@@ -1370,12 +1373,14 @@ class CppClassType(CType):
# scope CppClassScope
# typedef_flag boolean
# packed boolean
# templates [string] or None
is_cpp_class = 1
has_attributes = 1
base_classes = []
def __init__(self, name, kind, scope, typedef_flag, cname, base_classes, packed=False):
def __init__(self, name, kind, scope, typedef_flag, cname, base_classes, packed=False,
templates = None):
self.name = name
self.cname = cname
self.kind = kind
......@@ -1386,13 +1391,24 @@ class CppClassType(CType):
self.packed = packed
self.base_classes = base_classes
self.operators = []
self.templates = templates
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
templates = ""
if self.templates:
templates = "<"
for i in range(len(self.templates)-1):
templates += "class "
templates += self.templates[i]
templates += ','
templates += "class "
templates += self.templates[-1]
templates += ">"
if for_display or pyrex:
name = self.name
else:
name = self.cname
return "%s %s" % (name, entity_code)
return "%s %s%s" % (name, entity_code, templates)
def is_subclass(self, other_type):
if self.same_as_resolved_type(other_type):
......@@ -1405,6 +1421,14 @@ class CppClassType(CType):
def attributes_known(self):
return self.scope is not None
class TemplatedType(CType):
def __init__(self, name):
self.name = name
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
return ""
class CEnumType(CType):
# name string
# cname string or None
......
......@@ -473,10 +473,6 @@ class Scope(object):
else:
entry = self.add_cfunction(name, type, pos, cname, visibility, modifiers)
entry.func_cname = cname
#try:
# print entry.name, entry.type, entry.overloaded_alternatives
#except:
# pass
if in_pxd and visibility != 'extern':
entry.defined_in_pxd = 1
if api:
......@@ -1116,7 +1112,7 @@ class ModuleScope(Scope):
def declare_cpp_class(self, name, kind, scope,
typedef_flag, pos, cname = None, base_classes = [],
visibility = 'extern', packed = False):
visibility = 'extern', packed = False, templates = None):
if visibility != 'extern':
error(pos, "C++ classes may only be extern")
if cname is None:
......@@ -1124,7 +1120,7 @@ class ModuleScope(Scope):
entry = self.lookup(name)
if not entry:
type = PyrexTypes.CppClassType(
name, kind, scope, typedef_flag, cname, base_classes, packed)
name, kind, scope, typedef_flag, cname, base_classes, packed, templates = templates)
entry = self.declare_type(name, type, pos, cname,
visibility = visibility, defining = scope is not None)
else:
......
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