diff --git a/src/vsc/types.py b/src/vsc/types.py index 013ad7c..82bc5fb 100644 --- a/src/vsc/types.py +++ b/src/vsc/types.py @@ -176,31 +176,33 @@ def not_inside(self, rhs): raise Exception("Unsupported 'not_inside' argument of type " + str(type(rhs))) def __getattr__(self, name): - ret = None - em = object.__getattribute__(self, "em") - fm_t = Expr2FieldTypeVisitor().fieldtype(em) - - # This pops 'this expr' off the stack, so we can - # replace it with an extended expression - pop_expr() - - if fm_t is not None: - if name in fm_t.field_id_m.keys(): - idx = fm_t.field_id_m[name] - ret = expr(ExprIndexedFieldRefModel(em, [idx])) - else: - raise Exception("Field %s not in type %s" % (name, fm_t.name)) + if not expr_mode(): + return object.__getattribute__(self, name) else: - fm = Expr2FieldVisitor().field(em) + ret = None + em = object.__getattribute__(self, "em") + fm_t = Expr2FieldTypeVisitor().fieldtype(em) - if name in fm.field_id_m.keys(): - idx = fm.field_id_m[name] - ret = expr(ExprIndexedFieldRefModel(em, [idx])) + # This pops 'this expr' off the stack, so we can + # replace it with an extended expression + pop_expr() + + if fm_t is not None: + if name in fm_t.field_id_m.keys(): + idx = fm_t.field_id_m[name] + ret = expr(ExprIndexedFieldRefModel(em, [idx])) + else: + raise Exception("Field %s not in type %s" % (name, fm_t.name)) else: - raise Exception("Composite %s does not contain a field \"%s\"" % ( - fm.name, name)) + fm = Expr2FieldVisitor().field(em) - return ret + if name in fm.field_id_m.keys(): + idx = fm.field_id_m[name] + ret = expr(ExprIndexedFieldRefModel(em, [idx])) + else: + raise Exception("Composite %s does not contain a field \"%s\"" % ( + fm.name, name)) + return ret def __getitem__(self, k): if is_expr_mode(): @@ -859,15 +861,16 @@ def _id_fields(self, it, parent): fid = 0 for fn in dir(it): - fo = getattr(it, fn) - if hasattr(fo, "_int_field_info"): - fi = fo._int_field_info - fi.id = fid - fi.parent = it._int_field_info - fid += 1 + if not fn.startswith("__") and fn not in ("sum","product","size"): + fo = getattr(it, fn) + if hasattr(fo, "_int_field_info"): + fi = fo._int_field_info + fi.id = fid + fi.parent = it._int_field_info + fid += 1 - if fi.is_composite: - self._id_fields(fo, fi) + if fi.is_composite: + self._id_fields(fo, fi) def get_model(self): if self._int_field_info.model is None: diff --git a/src/vsc/visitors/expr2fieldtype_visitor.py b/src/vsc/visitors/expr2fieldtype_visitor.py index 652a2eb..1c5a085 100644 --- a/src/vsc/visitors/expr2fieldtype_visitor.py +++ b/src/vsc/visitors/expr2fieldtype_visitor.py @@ -57,9 +57,11 @@ def visit_expr_array_subscript(self, s : ExprArraySubscriptModel): if Expr2FieldTypeVisitor.DEBUG_EN: print("--> visit_expr_array_subscript(visit_type)") - t = self.type - self.type = None - t.accept(self) + if self.type is not None: + t = self.type + self.type = None + t.accept(self) + if Expr2FieldTypeVisitor.DEBUG_EN: print("<-- visit_expr_array_subscript(visit_type)") diff --git a/ve/unit/test_compound_obj.py b/ve/unit/test_compound_obj.py index 0fcd625..a730f50 100644 --- a/ve/unit/test_compound_obj.py +++ b/ve/unit/test_compound_obj.py @@ -572,3 +572,41 @@ def eq_c(self): item = Parent() item.randomize(debug=False) + + def test_nested_objects2(self): + @vsc.randobj + class Field(object): + def __init__(self): + self.d = vsc.rand_uint8_t() + + @vsc.randobj + class Child1(object): + def __init__(self): + self.b = vsc.rand_list_t(Child2(), 2) + + @vsc.randobj + class Child2(object): + def __init__(self): + self.c = vsc.rand_attr(Field()) + + @vsc.randobj + class Parent(object): + def __init__(self): + self.a = vsc.rand_list_t(Child1(), 2) + + @vsc.constraint + def eq_c(self): + self.a[0].b[0].c.d == self.a[1].b[0].c.d + + item = Parent() + item.randomize() + print(f"{item.a[0].b[0].c.d} {item.a[1].b[0].c.d}") + + def test_nested_objects3(self): + @vsc.randobj + class Item(object): + def __init__(self): + self.a = vsc.list_t(vsc.rand_list_t(vsc.rand_bit_t(2), 2)) + pass + + item = Item()