diff --git a/App/lib/core/Gen/Expr/ExprGenOps.vp b/App/lib/core/Gen/Expr/ExprGenOps.vp index a28c047..96f02ce 100644 --- a/App/lib/core/Gen/Expr/ExprGenOps.vp +++ b/App/lib/core/Gen/Expr/ExprGenOps.vp @@ -203,6 +203,29 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): elif w_cd == 32: if v_cd > 2147483647: return 1 return 0 + def _attr_call_ret_entry(self, pool: memhub.MemBuddy*, at: ast.Attribute*, trans: HT.Translator*) -> GenTypes.FuncEntry*: + """FuncEntry for a `recv.attr(...)` call (method or module-qualified free function), else None.""" + if at is None or at.attr is None or trans is None: return None + # Module-qualified free function: `import mod` then mod.f(). + if at.value is not None and at.value.kind() == ast.ASTKind.Name and trans._imported_modules is not None: + rn: ast.Name* = ast.Name*(at.value) + if rn.id is not None: + if self.Gen.ImportsGen.is_module_imported(trans._imported_modules, rn.id) != 0: + fe_mod: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(at.attr) + if fe_mod is not None: return fe_mod + # Method: the receiver's class name gives the table key "Class.method". + if at.value is None: return None + cls: str = self._attr_receiver_class_name(pool, at.value, trans) + if cls is None: return None + bare: str = cls + dot: str = self.Gen.StructGen._last_dot_outside_brackets(cls) + if dot is not None: bare = dot + 1 + n: sizet = string.strlen(bare) + string.strlen(at.attr) + 2 + lu: str = pool.alloc(n) + if lu is None: return None + viperlib.snprintf(lu, n, "%s.%s", bare, at.attr) + return self.Gen.CallGenLeafKit.find_func_entry_global(lu) + def _node_type_unsigned(self, pool: memhub.MemBuddy*, node: ast.AST*, trans: HT.Translator* = None) -> int: """Return 1 if the AST node resolves to an unsigned integer type, else 0.""" if node is None: return 0 @@ -234,9 +257,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): if fe_fn_u.RetSign == GenTypes.FUNC_RET_SIGN_UNSIGNED: return 1 if fe_fn_u.Spec is not None and TSpec.SpecIsUnsigned(fe_fn_u.Spec.Ret) != 0: return 1 elif fk_u == ast.ASTKind.Attribute: - # Qualified type cast: t.CUInt16T(x) / mod.ULONG(x). + # Qualified type cast: t.CUInt16T(x); then method / module-qualified calls. at_u: ast.Attribute* = ast.Attribute*(cl.func) if at_u.attr is not None and self._type_name_unsigned(at_u.attr) != 0: return 1 + fe_at_u: GenTypes.FuncEntry* = self._attr_call_ret_entry(pool, at_u, trans) + if fe_at_u is not None and fe_at_u.RetSign == GenTypes.FUNC_RET_SIGN_UNSIGNED: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node) @@ -391,10 +416,12 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase): fe_fn_s: GenTypes.FuncEntry* = self.Gen.CallGenLeafKit.find_func_entry_global(nm_c.id) if fe_fn_s is not None and fe_fn_s.RetSign == GenTypes.FUNC_RET_SIGN_SIGNED: return 1 elif fk_s == ast.ASTKind.Attribute: - # Qualified signed cast: t.CInt16T(x) / mod.LONG(x). + # Qualified signed cast (t.CInt16T(x)) or method / module-qualified call. at_c: ast.Attribute* = ast.Attribute*(cl.func) if at_c.attr is not None: if self._spec_sign_from_annot(at_c.attr) == TSpec.TS_SIGN_SIGNED: return 1 + fe_at_c: GenTypes.FuncEntry* = self._attr_call_ret_entry(pool, at_c, trans) + if fe_at_c is not None and fe_at_c.RetSign == GenTypes.FUNC_RET_SIGN_SIGNED: return 1 return 0 if k == ast.ASTKind.Name: nm: ast.Name* = ast.Name*(node)