From e2c4f3aebeb9aa49b68f26f92512759cbe43ee6b Mon Sep 17 00:00:00 2001 From: SAJJA EASWAR SAI Date: Mon, 2 Feb 2026 00:24:16 +0530 Subject: Fix: catch illegal static method calls with dot operator and fix NODE_EXPR_MEMBER token initialization --- src/parser/parser_expr.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'src/parser') diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index 5bf0089..a732448 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -4116,6 +4116,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) break; } ASTNode *node = ast_create(NODE_EXPR_MEMBER); + node->token = field; node->member.target = lhs; node->member.field = token_strdup(field); node->member.is_pointer_access = 1; @@ -4169,6 +4170,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) break; } ASTNode *node = ast_create(NODE_EXPR_MEMBER); + node->token = field; node->member.target = lhs; node->member.field = token_strdup(field); node->member.is_pointer_access = 2; @@ -4350,6 +4352,52 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) if (sig) { + // Check if this is a static method being called with dot operator + // Static methods don't have 'self' as first parameter + int is_static_method = 0; + if (sig->total_args == 0) + { + // No arguments at all - definitely static + is_static_method = 1; + } + else if (sig->arg_types[0]) + { + // Check if first parameter is a pointer to the struct type + // Instance methods have: fn method(self) where self is StructType* + // Static methods have: fn method(x: int, y: int) etc. + Type *first_param = sig->arg_types[0]; + + // If first param is not a pointer, it's likely static + // OR if it's a pointer but not to this struct type + if (first_param->kind != TYPE_POINTER) + { + is_static_method = 1; + } + else if (first_param->inner) + { + // Check if the inner type matches the struct + char *inner_name = NULL; + if (first_param->inner->kind == TYPE_STRUCT) + { + inner_name = first_param->inner->name; + } + + if (!inner_name || strcmp(inner_name, struct_name) != 0) + { + is_static_method = 1; + } + } + } + + if (is_static_method) + { + zpanic_at(lhs->token, + "Cannot call static method '%s' with dot operator\n" + " = help: Use '%s::%s(...)' instead of instance.%s(...)", + lhs->member.field, struct_name, lhs->member.field, + lhs->member.field); + } + resolved_name = xstrdup(mangled); resolved_sig = sig; @@ -4772,6 +4820,7 @@ ASTNode *parse_expr_prec(ParserContext *ctx, Lexer *l, Precedence min_prec) break; } ASTNode *node = ast_create(NODE_EXPR_MEMBER); + node->token = field; node->member.target = lhs; node->member.field = token_strdup(field); node->member.is_pointer_access = 0; -- cgit v1.2.3