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")
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")
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
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:
# (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
# 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
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)
# 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
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):
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
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:
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:
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: