Commit e6185bed authored by Danilo Freitas's avatar Danilo Freitas

Templates

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