+ # Generate a polymorphic attribute is_set test
+ fun isset_attribute(a: MAttribute, recv: RuntimeVariable): RuntimeVariable
+ do
+ var types = self.collect_types(recv)
+
+ var res = self.new_var(bool_type)
+
+ if types.is_empty then
+ self.add("/*BUG: no live types for {recv.inspect} . {a}*/")
+ return res
+ end
+ self.add("/* isset {a} on {recv.inspect} */")
+ self.add("switch({recv}->classid) \{")
+ var last = types.last
+ for t in types do
+ if not self.compiler.hardening and t == last then
+ self.add("default: /*{self.compiler.classid(t)}*/")
+ else
+ self.add("case {self.compiler.classid(t)}:")
+ end
+ var recv2 = self.autoadapt(recv, t)
+ var ta = a.intro.static_mtype.as(not null)
+ ta = self.resolve_for(ta, recv2)
+ var attr = self.new_expr("((struct {t.c_name}*){recv})->{a.intro.c_name}", ta)
+ if not ta isa MNullableType then
+ if ta.ctype == "val*" then
+ self.add("{res} = ({attr} != NULL);")
+ else
+ self.add("{res} = 1; /*NOTYET isset on primitive attributes*/")
+ end
+ end
+ self.add("break;")
+ end
+ if self.compiler.hardening then
+ self.add("default: /* Bug */")
+ self.bugtype(recv)
+ end
+ self.add("\}")
+
+ return res
+ end
+