|
@@ -457,6 +457,20 @@ vdynamic *hl_virtual_make_value( vvirtual *v ) {
|
|
|
return v->value;
|
|
|
}
|
|
|
|
|
|
+static bool should_recast( hl_type *t, hl_type *vt ) {
|
|
|
+ if( vt->kind == HF64 && t->kind == HI32 )
|
|
|
+ return true;
|
|
|
+ if( vt->kind == HNULL && vt->tparam->kind == t->kind )
|
|
|
+ return true;
|
|
|
+ if( vt->kind == HNULL && vt->tparam->kind == HF64 && t->kind == HI32 )
|
|
|
+ return true;
|
|
|
+ if( vt->kind == HVIRTUAL && t->kind == HDYNOBJ )
|
|
|
+ return true;
|
|
|
+ if( vt->kind == HOBJ && t->kind == HOBJ && vt->obj->rt->castFun )
|
|
|
+ return true;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
Allocate a virtual fields mapping to a given value.
|
|
|
**/
|
|
@@ -493,6 +507,7 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
|
|
|
case HDYNOBJ:
|
|
|
{
|
|
|
int i;
|
|
|
+ int64 need_recast = 0;
|
|
|
vdynobj *o = (vdynobj*)obj;
|
|
|
v = o->virtuals;
|
|
|
while( v ) {
|
|
@@ -506,11 +521,28 @@ vvirtual *hl_to_virtual( hl_type *vt, vdynamic *obj ) {
|
|
|
v->value = obj;
|
|
|
for(i=0;i<vt->virt->nfields;i++) {
|
|
|
hl_field_lookup *f = hl_lookup_find(o->lookup,o->nfields,vt->virt->fields[i].hashed_name);
|
|
|
- hl_vfields(v)[i] = f == NULL || !hl_same_type(f->t,vt->virt->fields[i].t) ? NULL : hl_dynobj_field(o,f);
|
|
|
+ hl_type *vft = vt->virt->fields[i].t;
|
|
|
+ void *addr = f == NULL || !hl_same_type(f->t,vft) ? NULL : hl_dynobj_field(o,f);
|
|
|
+ // check if we will perform recast of some fields to match the virtual definition
|
|
|
+ // recast will not work for >64 fields, but this should be pretty rare
|
|
|
+ if( addr == NULL && f && !o->virtuals && should_recast(f->t,vft) )
|
|
|
+ need_recast |= ((int64)1) << ((int64)i);
|
|
|
+ hl_vfields(v)[i] = addr;
|
|
|
}
|
|
|
// add it to the list
|
|
|
v->next = o->virtuals;
|
|
|
o->virtuals = v;
|
|
|
+ // recast
|
|
|
+ if( need_recast ) {
|
|
|
+ for(i=0;i<vt->virt->nfields;i++)
|
|
|
+ if( need_recast & (((int64)1) << ((int64)i)) ) {
|
|
|
+ hl_obj_field *f = vt->virt->fields + i;
|
|
|
+ if( hl_is_ptr(f->t) )
|
|
|
+ hl_dyn_setp(obj,f->hashed_name,f->t,hl_dyn_getp(obj,f->hashed_name,f->t));
|
|
|
+ else if( f->t->kind == HF64 )
|
|
|
+ hl_dyn_setd(obj,f->hashed_name,hl_dyn_getd(obj,f->hashed_name));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
break;
|
|
|
case HVIRTUAL:
|