diff --git a/App/lib/core/Gen/AssignGenMixin.vp b/App/lib/core/Gen/AssignGenMixin.vp index 4375b13..424f376 100644 --- a/App/lib/core/Gen/AssignGenMixin.vp +++ b/App/lib/core/Gen/AssignGenMixin.vp @@ -517,6 +517,24 @@ novirtual class AssignGenMixin: if self._annotation_contains_name(bop.right, name) != 0: return 1 return 0 + def _annotation_has_cptr_marker(self, annot: ast.AST*) -> int: + """Return 1 if the annotation union carries a CPtr marker (the star form ` | t.CPtr`).""" + if annot is None: return 0 + k: int = annot.kind() + if k == ast.ASTKind.Attribute: + at: ast.Attribute* = ast.Attribute*(annot) + if at.attr is not None and string.strcmp(at.attr, "CPtr") == 0: return 1 + return 0 + if k == ast.ASTKind.Name: + nm: ast.Name* = ast.Name*(annot) + if nm.id is not None and string.strcmp(nm.id, "CPtr") == 0: return 1 + return 0 + if k == ast.ASTKind.BinOp: + bop: ast.BinOp* = ast.BinOp*(annot) + if self._annotation_has_cptr_marker(bop.left) != 0: return 1 + if self._annotation_has_cptr_marker(bop.right) != 0: return 1 + return 0 + # _is_ptr_element_annotation - check whether an annotation is bytes* or str* # bytes*/str* => 8-byte element stride (i8**); char*/int8* => 1-byte stride. def _is_ptr_element_annotation(self, annot: ast.AST*) -> int: @@ -526,8 +544,12 @@ novirtual class AssignGenMixin: if k != ast.ASTKind.BinOp: return 0 bop: ast.BinOp* = ast.BinOp*(annot) if bop.op != ast.OpKind.BitOr: return 0 - if self._annotation_contains_name(annot, "str") != 0: return 1 - if self._annotation_contains_name(annot, "bytes") != 0: return 1 + # str/bytes are already i8*; only the union WITH a pointer marker (str*/bytes*) is i8** and + # needs 8-byte element slots. A union that merely carries them (e.g. `const str`, which is + # t.CConst | str and stays i8*) must keep the 1-byte stride. + if self._annotation_has_cptr_marker(annot) != 0: + if self._annotation_contains_name(annot, "str") != 0: return 1 + if self._annotation_contains_name(annot, "bytes") != 0: return 1 # Generic type param / nested union | t.CPtr: scalars use their own size, pointers use 8-byte slots if self._is_generic_tp_or_nested(bop.left) != 0 or self._is_generic_tp_or_nested(bop.right) != 0: gp_nm: str = None diff --git a/App/lib/core/Gen/TranslatorGenMixin.vp b/App/lib/core/Gen/TranslatorGenMixin.vp index 7fc7df0..6a0d8f2 100644 --- a/App/lib/core/Gen/TranslatorGenMixin.vp +++ b/App/lib/core/Gen/TranslatorGenMixin.vp @@ -859,8 +859,9 @@ novirtual class TranslatorGenMixin: if aa_ml.annotation.kind() == ast.ASTKind.BinOp: bop_ml: ast.BinOp* = ast.BinOp*(aa_ml.annotation) if bop_ml.op == ast.OpKind.BitOr: - if self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "str") != 0 or self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "bytes") != 0: - self.Gen.VarGen.set_var_ptr_element(trans.SymTab, var_name) + if self.Gen.AssignGen._annotation_has_cptr_marker(aa_ml.annotation) != 0: + if self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "str") != 0 or self.Gen.AssignGen._annotation_contains_name(aa_ml.annotation, "bytes") != 0: + self.Gen.VarGen.set_var_ptr_element(trans.SymTab, var_name) return 1 return 0