From ec140e5e1823ed72e1ac8ab4af121dbe1b3f85d7 Mon Sep 17 00:00:00 2001 From: sudokit <64897647+sudokit@users.noreply.github.com> Date: Fri, 30 Jan 2026 15:01:42 +0200 Subject: Added missing brackets for enum match expression --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f03f605..8c8e3e2 100644 --- a/README.md +++ b/README.md @@ -465,9 +465,9 @@ match val { // Destructuring Enums match shape { - Shape::Circle(r) => println "Radius: {r}", - Shape::Rect(w, h) => println "Area: {w*h}", - Shape::Point => println "Point" + Shape::Circle(r) => { println "Radius: {r}" }, + Shape::Rect(w, h) => { println "Area: {w*h}" }, + Shape::Point => { println "Point" }, } ``` -- cgit v1.2.3 From fcc9210aa32d671e16b392cf48546c4e2001ff8f Mon Sep 17 00:00:00 2001 From: Lam Wei Lun Date: Sun, 1 Feb 2026 14:46:46 +0800 Subject: Added detach/cancel and equality check for std/thread --- std/thread.zc | 56 ++++++++++++++++++++++++++++++++++++++++++------ tests/std/test_thread.zc | 42 ++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 tests/std/test_thread.zc diff --git a/std/thread.zc b/std/thread.zc index 16f3ca1..0ab02e4 100644 --- a/std/thread.zc +++ b/std/thread.zc @@ -25,9 +25,13 @@ raw { z_closure_T *closure = (z_closure_T*)c; void (*f)(void*) = (void(*)(void*))closure->func; f(closure->ctx); - free(c); + free(c); return NULL; } + + static int _z_thread_equal(void* handle1, void* handle2) { + return pthread_equal((pthread_t)handle1, (pthread_t)handle2); + } static int _z_thread_spawn(void *ctx_copy, size_t *out_handle) { pthread_t pt; @@ -41,6 +45,14 @@ raw { static int _z_thread_join(void *handle) { return pthread_join((pthread_t)handle, NULL); } + + static int _z_thread_detach(void* handle) { + return pthread_detach((pthread_t)handle); + } + + static int _z_thread_cancel(void* handle) { + return pthread_cancel((pthread_t)handle); + } static void _z_mutex_init(void *ptr) { pthread_mutex_init((pthread_mutex_t*)ptr, NULL); @@ -63,8 +75,11 @@ raw { } } +extern fn _z_thread_equal(handle1: void*, handle2: void*) -> int; extern fn _z_thread_spawn(ctx: void*, out: usize*) -> int; extern fn _z_thread_join(handle: void*) -> int; +extern fn _z_thread_detach(handle: void*) -> int; +extern fn _z_thread_cancel(handle: void*) -> int; extern fn _z_mutex_init(ptr: void*); extern fn _z_mutex_lock(ptr: void*); extern fn _z_mutex_unlock(ptr: void*); @@ -74,21 +89,30 @@ extern fn _z_usleep(micros: int); struct Thread { - handle: void*; + handle: void*; } impl Thread { + fn eq(self, other: const Thread) -> bool { + return _z_thread_equal(self.handle, other.handle); + } + fn neq(self, other: const Thread) -> bool { + return !(self == other); + } + fn spawn(func: fn()) -> Result { let t: usize = 0; let ctx_copy = malloc(16); // z_closure_T is 16 bytes - if (ctx_copy == NULL) return Result::Err("OOM"); + if ctx_copy == NULL { + return Result::Err("OOM"); + } memcpy(ctx_copy, &func, 16); let ret = _z_thread_spawn(ctx_copy, &t); - if (ret != 0) { + if ret != 0 { free(ctx_copy); return Result::Err("Failed to create thread"); } @@ -97,8 +121,26 @@ impl Thread { } fn join(self) -> Result { - let ret = _z_thread_join(self.handle); - if (ret != 0) return Result::Err("Join failed"); + let err = _z_thread_join(self.handle); + if err { + return Result::Err("Join failed"); + } + return Result::Ok(true); + } + + fn detach(self) -> Result { + let err = _z_thread_detach(self.handle); + if err { + return Result::Err("Detach failed"); + } + return Result::Ok(true); + } + + fn cancel(self) -> Result { + let err = _z_thread_cancel(self.handle); + if err { + return Result::Err("Cancel failed"); + } return Result::Ok(true); } } @@ -123,7 +165,7 @@ impl Mutex { } fn free(self) { - if (self.handle) { + if self.handle { _z_mutex_destroy(self.handle); free(self.handle); self.handle = NULL; diff --git a/tests/std/test_thread.zc b/tests/std/test_thread.zc new file mode 100644 index 0000000..42fa82e --- /dev/null +++ b/tests/std/test_thread.zc @@ -0,0 +1,42 @@ +import "std/thread.zc" + +test "Thread Spawn and Join" { + "Testing thread spawn and join"; + + let spawn_result = Thread::spawn(fn(){ + "Running on a separate thread"; + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let join_result = thr.join(); + assert(join_result.is_ok(), "Thread join has failed"); +} + +test "Thread Spawn and Detach" { + "Testing thread spawn and detach"; + + let spawn_result = Thread::spawn(fn(){ + "Detached thread, this line might print later."; + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let detach_result = thr.detach(); + assert(detach_result.is_ok(), "Thread detach has failed"); +} + +test "Thread Spawn and Cancel" { + "Testing thread spawn and cancel"; + + let spawn_result = Thread::spawn(fn(){ + "Thread running indefinitely..."; + while true { + } + }); + assert(spawn_result.is_ok(), "Thread spawn has failed"); + + let thr = spawn_result.unwrap(); + let cancel_result = thr.cancel(); + assert(cancel_result.is_ok(), "Thread cancel has failed"); +} -- cgit v1.2.3 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(+) 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 From d51c9d091951bd4e5d2d0ccd5f72dfcbbfb412ec Mon Sep 17 00:00:00 2001 From: SAJJA EASWAR SAI Date: Mon, 2 Feb 2026 02:44:34 +0530 Subject: Fix:#170 Detect incorrectly swapped struct and trait in impl block --- src/parser/parser_struct.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c index c89ad34..0c984a6 100644 --- a/src/parser/parser_struct.c +++ b/src/parser/parser_struct.c @@ -315,6 +315,16 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) register_generic(ctx, target_gen_param); } + // Check for common error: swapped Struct and Trait + // impl MyStruct for MyTrait (Wrong) vs impl MyTrait for MyStruct (Correct) + if (!is_trait(name1) && is_trait(name2)) + { + zpanic_at(t1, + "Incorrect usage of impl. Did you mean 'impl %s for %s'? Syntax is 'impl " + " for '", + name2, name1); + } + // Auto-import std/mem.zc if implementing Drop, Copy, or Clone traits if (strcmp(name1, "Drop") == 0 || strcmp(name1, "Copy") == 0 || strcmp(name1, "Clone") == 0) { -- cgit v1.2.3 From dadabf8b9d11d099777acc261068a3ed8ca06f24 Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Mon, 2 Feb 2026 00:33:12 +0000 Subject: Fix concurrency suite compilation errors involving C types --- src/ast/ast.c | 3 +++ src/parser/parser_expr.c | 3 +-- std/thread.zc | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ast/ast.c b/src/ast/ast.c index 1b35500..28fe678 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -101,6 +101,9 @@ int is_integer_type(Type *t) t->kind == TYPE_ISIZE || t->kind == TYPE_BYTE || t->kind == TYPE_RUNE || t->kind == TYPE_UINT || t->kind == TYPE_I128 || t->kind == TYPE_U128 || t->kind == TYPE_BITINT || t->kind == TYPE_UBITINT || + t->kind == TYPE_C_INT || t->kind == TYPE_C_UINT || t->kind == TYPE_C_LONG || + t->kind == TYPE_C_ULONG || t->kind == TYPE_C_SHORT || t->kind == TYPE_C_USHORT || + t->kind == TYPE_C_CHAR || t->kind == TYPE_C_UCHAR || (t->kind == TYPE_STRUCT && t->name && (0 == strcmp(t->name, "int8_t") || 0 == strcmp(t->name, "uint8_t") || 0 == strcmp(t->name, "int16_t") || 0 == strcmp(t->name, "uint16_t") || diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index a732448..f27e2c3 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -370,8 +370,7 @@ static void check_format_string(ASTNode *call, Token t) if (spec == 'd' || spec == 'i' || spec == 'u' || spec == 'x' || spec == 'X' || spec == 'o') { - if (vt && vt->kind != TYPE_INT && vt->kind != TYPE_I64 && !type_is_unsigned(vt) && - vt->kind != TYPE_CHAR) + if (vt && !is_integer_type(vt)) { warn_format_string(t, arg_num, "integer", got_type); } diff --git a/std/thread.zc b/std/thread.zc index da21772..0722b60 100644 --- a/std/thread.zc +++ b/std/thread.zc @@ -108,10 +108,10 @@ impl Thread { memcpy(ctx, &func, 16); - let ret = _z_thread_spawn(ctx_copy, &t); + let ret = _z_thread_spawn(ctx, &out_handle); if ret != 0 { - free(ctx_copy); + free(ctx); return Result::Err("Failed to create thread"); } -- cgit v1.2.3 From f86ef2bbc1248bba9ebfd322c96a0f4c8e028148 Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Mon, 2 Feb 2026 00:51:44 +0000 Subject: Extended fix to all languages --- README_ES.md | 6 +++--- README_IT.md | 6 +++--- README_ZH_CN.md | 6 +++--- README_ZH_TW.md | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README_ES.md b/README_ES.md index 07234f0..815968f 100644 --- a/README_ES.md +++ b/README_ES.md @@ -475,9 +475,9 @@ match val { // Desestructuración de Enums match shape { - Shape::Circle(r) => println "Radio: {r}", - Shape::Rect(w, h) => println "Área: {w*h}", - Shape::Point => println "Punto" + Shape::Circle(r) => { println "Radio: {r}" }, + Shape::Rect(w, h) => { println "Área: {w*h}" }, + Shape::Point => { println "Punto" }, } ``` diff --git a/README_IT.md b/README_IT.md index be48cda..9e505d9 100644 --- a/README_IT.md +++ b/README_IT.md @@ -477,9 +477,9 @@ match val { // Destrutturazione degli Enums match forma { - Forma::Cerchio(r) => println "Raggio: {r}", - Forma::Rettangolo(w, h) => println "Area: {w*h}", - Forma::Punto => println "Punto" + Forma::Cerchio(r) => { println "Raggio: {r}" }, + Forma::Rettangolo(w, h) => { println "Area: {w*h}" }, + Forma::Punto => { println "Punto" }, } ``` diff --git a/README_ZH_CN.md b/README_ZH_CN.md index af83e8c..4fd4b39 100644 --- a/README_ZH_CN.md +++ b/README_ZH_CN.md @@ -475,9 +475,9 @@ match val { // 解构枚举 match shape { - Shape::Circle(r) => println "半径: {r}", - Shape::Rect(w, h) => println "面积: {w*h}", - Shape::Point => println "点" + Shape::Circle(r) => { println "半径: {r}" }, + Shape::Rect(w, h) => { println "面积: {w*h}" }, + Shape::Point => { println "点" }, } ``` diff --git a/README_ZH_TW.md b/README_ZH_TW.md index 3a18a53..05c08d3 100644 --- a/README_ZH_TW.md +++ b/README_ZH_TW.md @@ -475,9 +475,9 @@ match val { // 解構枚舉 match shape { - Shape::Circle(r) => println "半徑: {r}", - Shape::Rect(w, h) => println "面積: {w*h}", - Shape::Point => println "點" + Shape::Circle(r) => { println "半徑: {r}" }, + Shape::Rect(w, h) => { println "面積: {w*h}" }, + Shape::Point => { println "點" }, } ``` -- cgit v1.2.3