summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md6
-rw-r--r--README_ES.md6
-rw-r--r--README_IT.md6
-rw-r--r--README_ZH_CN.md6
-rw-r--r--README_ZH_TW.md6
-rw-r--r--src/ast/ast.c3
-rw-r--r--src/parser/parser_expr.c52
-rw-r--r--src/parser/parser_struct.c10
-rw-r--r--std/thread.zc56
-rw-r--r--tests/std/test_thread.zc42
10 files changed, 167 insertions, 26 deletions
diff --git a/README.md b/README.md
index 2f16362..2c36216 100644
--- a/README.md
+++ b/README.md
@@ -476,9 +476,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" },
}
```
diff --git a/README_ES.md b/README_ES.md
index 956436d..be8e47e 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 5b9e3ab..3d70a65 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 926eb9f..e5f8f54 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 df6a320..2f32656 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 "點" },
}
```
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 5bf0089..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);
}
@@ -4116,6 +4115,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 +4169,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 +4351,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 +4819,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;
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 "
+ "<Trait> for <Struct>'",
+ 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)
{
diff --git a/std/thread.zc b/std/thread.zc
index 78d2547..0722b60 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 (int)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*) -> c_int;
extern fn _z_thread_spawn(ctx: void*, out: usize*) -> c_int;
extern fn _z_thread_join(handle: void*) -> c_int;
+extern fn _z_thread_detach(handle: void*) -> c_int;
+extern fn _z_thread_cancel(handle: void*) -> c_int;
extern fn _z_mutex_init(ptr: void*);
extern fn _z_mutex_lock(ptr: void*);
extern fn _z_mutex_unlock(ptr: void*);
@@ -74,10 +89,17 @@ extern fn _z_usleep(micros: c_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<Thread> {
let out_handle: usize = 0;
@@ -87,9 +109,8 @@ impl Thread {
memcpy(ctx, &func, 16);
let ret = _z_thread_spawn(ctx, &out_handle);
- let zero: c_int = 0;
- if (ret != zero) {
- // Failed to spawn
+
+ if ret != 0 {
free(ctx);
return Result<Thread>::Err("Failed to create thread");
}
@@ -98,9 +119,26 @@ impl Thread {
}
fn join(self) -> Result<bool> {
- let ret = _z_thread_join(self.handle);
- let zero: c_int = 0;
- if (ret != zero) return Result<bool>::Err("Join failed");
+ let err = _z_thread_join(self.handle);
+ if err {
+ return Result<bool>::Err("Join failed");
+ }
+ return Result<bool>::Ok(true);
+ }
+
+ fn detach(self) -> Result<bool> {
+ let err = _z_thread_detach(self.handle);
+ if err {
+ return Result<bool>::Err("Detach failed");
+ }
+ return Result<bool>::Ok(true);
+ }
+
+ fn cancel(self) -> Result<bool> {
+ let err = _z_thread_cancel(self.handle);
+ if err {
+ return Result<bool>::Err("Cancel failed");
+ }
return Result<bool>::Ok(true);
}
}
@@ -125,7 +163,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");
+}