child_attrs = ["base", "dimension"]
def analyse(self, base_type, env, nonempty = 0):
+ if base_type.is_cpp_class:
+ from ExprNodes import TupleNode
+ if isinstance(self.dimension, TupleNode):
+ args = self.dimension.args
+ else:
+ args = self.dimension,
+ values = [v.analyse_as_type(env) for v in args]
+ if None in values:
+ ix = values.index(None)
+ error(args[ix].pos, "Template parameter not a type.")
+ return error_type
+ base_type = base_type.specialize_here(self.pos, values)
+ return self.base.analyse(base_type, env, nonempty = nonempty)
if self.dimension:
self.dimension.analyse_const_expression(env)
if not self.dimension.type.is_int:
self.operators = []
self.templates = templates
self.template_type = template_type
+ self.specializations = {}
def specialize_here(self, pos, template_values = None):
if self.templates is None:
return self.specialize(dict(zip(self.templates, template_values)))
def specialize(self, values):
- # TODO(danilo): Cache for efficiency.
+ key = tuple(values.items())
+ if key in self.specializations:
+ return self.specializations[key]
template_values = [t.specialize(values) for t in self.templates]
- return CppClassType(self.name, self.scope.specialize(values), self.cname, self.base_classes,
- template_values, template_type=self)
+ specialized = self.specializations[key] = \
+ CppClassType(self.name, None, self.cname, self.base_classes, template_values, template_type=self)
+ specialized.scope = self.scope.specialize(values)
+ return specialized
def declaration_code(self, entity_code, for_display = 0, dll_linkage = None, pyrex = 0):
if self.templates: