summaryrefslogtreecommitdiff
path: root/tests/features
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-14 23:59:54 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-14 23:59:54 +0000
commitdcfdc053cb5f9fb4d5eac0a2233c75126b7a8188 (patch)
treef34f30b382fa22d6fd0af46875a5b4b26d00feff /tests/features
parenta918df69269a39ef7350a645b5db025d66ecb18a (diff)
Added some of the tests.
Diffstat (limited to 'tests/features')
-rw-r--r--tests/features/test_asm.zc54
-rw-r--r--tests/features/test_build_directives.zc19
-rw-r--r--tests/features/test_comptime_suite.zc29
-rw-r--r--tests/features/test_concurrency_suite.zc98
-rw-r--r--tests/features/test_destructuring.zc38
-rw-r--r--tests/features/test_embed.zc57
-rw-r--r--tests/features/test_intel.zc22
-rw-r--r--tests/features/test_operators_suite.zc144
-rw-r--r--tests/features/test_traits_suite.zc104
9 files changed, 565 insertions, 0 deletions
diff --git a/tests/features/test_asm.zc b/tests/features/test_asm.zc
new file mode 100644
index 0000000..01f35d5
--- /dev/null
+++ b/tests/features/test_asm.zc
@@ -0,0 +1,54 @@
+fn test_nop() {
+ asm { nop }
+}
+
+fn test_pause() {
+ asm { pause }
+}
+
+fn test_multiline() {
+ asm {
+ mov $1, %rax
+ mov $2, %rbx
+ add %rbx, %rax
+ }
+}
+
+fn test_volatile() {
+ asm volatile {
+ mfence
+ }
+}
+
+test "test_asm" {
+ println "Testing inline assembly...";
+
+ test_nop();
+ test_pause();
+ test_multiline();
+ test_volatile();
+
+ println "-> Assembly blocks compiled successfully!";
+}
+
+fn add_five(x: int) -> int {
+ var result: int;
+ asm {
+ "mov {x}, {result}"
+ "add $5, {result}"
+ : out(result)
+ : in(x)
+ }
+ return result;
+}
+
+test "test_asm_params" {
+ println "Testing assembly parameters...";
+ var val = add_five(10);
+ if (val == 15) {
+ println "-> Success! add_five(10) = 15";
+ } else {
+ println "-> Failed: expected 15, got {val}";
+ exit(1);
+ }
+}
diff --git a/tests/features/test_build_directives.zc b/tests/features/test_build_directives.zc
new file mode 100644
index 0000000..d6e35b3
--- /dev/null
+++ b/tests/features/test_build_directives.zc
@@ -0,0 +1,19 @@
+//> link: -lm
+//> cflags: -O2
+
+// Declare C math function (since we don't have a math stdlib module yet)
+extern fn sin(x: double) -> double;
+
+test "test_build_directives" {
+ println "Running Build Directives Test...";
+ var x = 3.14159 / 2.0; // PI/2
+ var s = sin(x);
+ // sin(PI/2) should be 1.0
+ println "sin(PI/2) = {s}";
+
+ if (s > 0.99 && s < 1.01) {
+ println "Math Link Success!";
+ } else {
+ println "Math Link Failure (Value wrong)";
+ }
+}
diff --git a/tests/features/test_comptime_suite.zc b/tests/features/test_comptime_suite.zc
new file mode 100644
index 0000000..b8127ec
--- /dev/null
+++ b/tests/features/test_comptime_suite.zc
@@ -0,0 +1,29 @@
+
+comptime {
+ printf("fn generated_func() {\n");
+ printf(" println \" I was generated at compile time!\";\n");
+ printf("}\n");
+}
+
+@comptime
+fn double_ct(x: int) -> int {
+ return x * 2;
+}
+
+test "test_comptime_block" {
+ println "Running Comptime Test...";
+ generated_func();
+ println "Comptime Test Complete.";
+}
+
+test "test_comptime_attr" {
+ var x = double_ct(21);
+ assert(x == 42, "Comptime function failed");
+ println "Comptime function called successfully";
+}
+
+test "test_comptime_fn" {
+ comptime {
+ println "println \"Hello from comptime fn!\";";
+ }
+}
diff --git a/tests/features/test_concurrency_suite.zc b/tests/features/test_concurrency_suite.zc
new file mode 100644
index 0000000..836594d
--- /dev/null
+++ b/tests/features/test_concurrency_suite.zc
@@ -0,0 +1,98 @@
+//> link: -lpthread
+import "std/thread.zc"
+
+async fn double_slowly(x: int) -> int {
+ usleep(1000);
+ return x * 2;
+}
+
+async fn add_async(a: int, b: int) -> int {
+ return a + b;
+}
+
+async fn say_hello() {
+ puts("Hello from async!");
+}
+
+struct Point {
+ x: int;
+ y: int;
+}
+
+async fn make_point(x: int, y: int) -> Point {
+ return Point{x: x, y: y};
+}
+
+struct Counter {
+ val: int;
+ lock: Mutex;
+}
+
+test "test_async_basics" {
+ var future1 = double_slowly(21);
+ var future2 = add_async(10, 20);
+
+ var result1 = await future1;
+ var result2 = await future2;
+
+ assert(result1 == 42, "Async double failed");
+ assert(result2 == 30, "Async add failed");
+}
+
+test "test_async_struct_return" {
+ var f = make_point(5, 7);
+ var p = await f;
+
+ assert(p.x == 5, "Async struct x failed");
+ assert(p.y == 7, "Async struct y failed");
+}
+
+test "test_async_void" {
+ var f = say_hello();
+ await f;
+}
+
+test "test_thread" {
+ println "Testing Concurrency...";
+
+ var c = (Counter*)malloc(sizeof(Counter));
+ c.val = 0;
+ c.lock = Mutex::new();
+
+ const N = 10000;
+
+ var t1_res = Thread::spawn(fn() {
+ for (var i=0; i<N; ++i) {
+ c.lock.lock();
+ c.val = c.val + 1;
+ c.lock.unlock();
+ }
+ });
+
+ var t2_res = Thread::spawn(fn() {
+ for (var i=0; i<N; ++i) {
+ c.lock.lock();
+ c.val = c.val + 1;
+ c.lock.unlock();
+ }
+ });
+
+ assert(t1_res.is_err() == false, "T1 failed to spawn");
+ assert(t2_res.is_err() == false, "T2 failed to spawn");
+
+ var t1 = t1_res.unwrap();
+ var t2 = t2_res.unwrap();
+
+ t1.join();
+ t2.join();
+
+ println "Final Count: {c.val} (Expected {2 * N})";
+
+ var final_val = c.val;
+
+ c.lock.free();
+ free(c);
+
+ assert(final_val == 2 * N, "Concurrency count mismatch");
+ println "Concurrency Test Passed!";
+}
diff --git a/tests/features/test_destructuring.zc b/tests/features/test_destructuring.zc
new file mode 100644
index 0000000..b898582
--- /dev/null
+++ b/tests/features/test_destructuring.zc
@@ -0,0 +1,38 @@
+struct Point {
+ x: int;
+ y: int;
+}
+
+struct Rect {
+ w: int;
+ h: int;
+}
+
+fn tuple_ret() -> (int, int) {
+ return (10, 20);
+}
+
+test "test_destructuring" {
+ var p = Point{x: 1, y: 2};
+
+ // Explicit Struct Destructuring (Shorthand)
+ var Point{x, y} = p;
+ assert(x == 1, "x is 1");
+ assert(y == 2, "y is 2");
+
+ // Explicit Struct Destructuring (Renamed)
+ var Point{x: a, y: b} = p;
+ assert(a == 1, "a is 1");
+ assert(b == 2, "b is 2");
+
+ // Anonymous Struct Destructuring (Inferred)
+ // Note: Anonymous block only supports shorthand {x, y} currently.
+ // var {x: x2} = p; // Not supported yet in anonymous block parser
+
+ // Tuple Destructuring
+ var (t1, t2) = tuple_ret();
+ assert(t1 == 10, "t1 is 10");
+ assert(t2 == 20, "t2 is 20");
+
+ println "Destructuring OK";
+}
diff --git a/tests/features/test_embed.zc b/tests/features/test_embed.zc
new file mode 100644
index 0000000..f6d9468
--- /dev/null
+++ b/tests/features/test_embed.zc
@@ -0,0 +1,57 @@
+
+test "test_embed" {
+ "=> Static File Analyzer";
+
+ var data = embed "std.zc";
+
+ "Target File: 'std.zc'";
+ "File Size: {data.len} bytes";
+ "";
+
+ var lines: I32 = 1;
+ var words: I32 = 0;
+ var sum: U64 = 0;
+ var in_word: bool = 0;
+
+ "Analyzing content...";
+
+ var i: int = 0;
+ while (i < data.len) {
+ var c: char = data.data[i];
+
+ match c {
+ '\n' => {
+ lines++;
+ in_word = 0;
+ }
+
+ ' ', '\t', '\r' => {
+ in_word = 0;
+ }
+
+ _ => {
+ if (!in_word) {
+ words++;
+ in_word = 1;
+ }
+ }
+ }
+
+ var b: U8 = c;
+ sum = sum + b;
+
+ i++;
+ }
+
+ "";
+ "*** Report ***";
+ "Total Lines: {lines}";
+ "Total Words: {words}";
+
+ "Checksum: 0x{sum:X} (Simple Sum)";
+ "Average Byte: {sum / data.len}";
+
+ "";
+ "Analysis successfully completed.";
+
+}
diff --git a/tests/features/test_intel.zc b/tests/features/test_intel.zc
new file mode 100644
index 0000000..8547501
--- /dev/null
+++ b/tests/features/test_intel.zc
@@ -0,0 +1,22 @@
+//> cflags: -masm=intel
+
+fn add_five_intel(x: int) -> int {
+ var result: int;
+ asm {
+ "mov {result}, {x}"
+ "add {result}, 5"
+ : out(result)
+ : in(x)
+ }
+ return result;
+}
+
+test "test_intel" {
+ var val = add_five_intel(10);
+ "Sum Intel: 10 + 5 = {val}";
+
+ match val {
+ 15 => printf("-> Success!\n")
+ _ => printf("-> Failed: expected 15, got {val}\n")
+ }
+}
diff --git a/tests/features/test_operators_suite.zc b/tests/features/test_operators_suite.zc
new file mode 100644
index 0000000..68b73fe
--- /dev/null
+++ b/tests/features/test_operators_suite.zc
@@ -0,0 +1,144 @@
+
+struct Flags {
+ bits: int;
+}
+
+impl Flags {
+ fn new(b: int) -> Flags { return Flags{bits: b}; }
+
+ fn bitor(self, other: Flags) -> Flags {
+ " [DEBUG] Custom bitor called! combining {self.bits} | {other.bits}";
+ return Flags { bits: self.bits | other.bits };
+ }
+}
+
+struct Container {
+ val: int;
+}
+
+impl Container {
+ fn new(v: int) -> Container { return Container { val: v }; }
+
+ fn get(self, idx: int) -> int {
+ return self.val + idx;
+ }
+
+ fn set(self, idx: int, v: int) {
+ self.val = v + idx;
+ }
+
+ fn neg(self) -> Container {
+ return Container { val: -self.val };
+ }
+
+ fn not(self) -> bool {
+ return self.val == 0;
+ }
+
+ fn bitnot(self) -> Container {
+ return Container { val: ~self.val };
+ }
+}
+
+enum Result {
+ Ok(int),
+ Err(int)
+}
+
+fn make_ok(v: int) -> Result {
+ return Result_Ok(v);
+}
+
+fn make_err(e: int) -> Result {
+ return Result_Err(e);
+}
+
+fn process_result(fail: int) -> Result {
+ var val = make_ok(10)?;
+
+ if (fail) {
+ var v2 = make_err(500)?;
+ return Result_Ok(v2 + 1000);
+ }
+
+ return Result_Ok(val + 20);
+}
+
+fn add(a: int, b: int) -> int {
+ return a + b;
+}
+
+fn twice(x: int) -> int {
+ return x * 2;
+}
+
+test "test_operator_overloading" {
+ "=> Bitwise Primitives";
+ var a = 0b1100;
+ var b = 0b1010;
+
+ "{a} | {b} = {a | b} (Expected 14)";
+ "{a} & {b} = {a & b} (Expected 8)";
+ "{a} ^ {b} = {a ^ b} (Expected 6)";
+ "{a} << 1 = {a << 1} (Expected 24)";
+
+ "=> Compound Assignment Desugaring";
+ var x = 10;
+ x += 5; // 15
+ x <<= 1; // 30
+
+ "=> Struct Overloading + Compound (|=)";
+ var f1 = Flags::new(1);
+ var f2 = Flags::new(4);
+ f1 |= f2;
+ "Result bits: {f1.bits} (Expected 5)";
+
+ const MAX_LIMIT = 100;
+}
+
+test "test_extended_overloading" {
+ var c = Container::new(10);
+
+ // Index Get
+ assert(c[5] == 15, "Get Failed");
+
+ // Index Set
+ c[2] = 20;
+ assert(c.val == 22, "Set Failed");
+
+ // Compound Assignment
+ c[0] += 5;
+ assert(c.val == 27, "Compound Set Failed");
+
+ // Unary Neg
+ var n = -c;
+ assert(n.val == -27, "Neg Failed");
+
+ // Unary Not
+ assert(!c == false, "Not Operator Failed");
+
+ // Unary Bitnot
+ var b = ~c;
+ assert(b.val == ~27, "Bitnot Failed");
+}
+
+test "test_pipe_operator" {
+ var res = 5 |> twice;
+ assert(res == 10, "Pipe twice failed");
+
+ var res2 = 10 |> add(20);
+ assert(res2 == 30, "Pipe add failed");
+
+ var res3 = 5 |> twice |> add(10); // 20
+ assert(res3 == 20, "Multi-pipe failed");
+}
+
+test "test_try_operator" {
+ var res_ok = process_result(0);
+ assert(res_ok.tag == Result_Ok_Tag, "Expected Ok");
+ assert(res_ok.data.Ok == 30, "Expected 30");
+
+ var res_err = process_result(1);
+ assert(res_err.tag == Result_Err_Tag, "Expected Err");
+ assert(res_err.data.Err == 500, "Expected Err(500)");
+}
diff --git a/tests/features/test_traits_suite.zc b/tests/features/test_traits_suite.zc
new file mode 100644
index 0000000..7fe7d1c
--- /dev/null
+++ b/tests/features/test_traits_suite.zc
@@ -0,0 +1,104 @@
+
+trait Greeter {
+ fn greet(self, msg: string);
+ fn shout(self);
+}
+
+struct Robot {
+ id: int;
+}
+
+impl Greeter for Robot {
+ fn greet(self, msg: string) {
+ println "Robot {self.id} says: {msg}";
+ }
+ fn shout(self) {
+ println "ROBOT {self.id} ACTIVATED";
+ }
+}
+
+trait Shape {
+ fn area(self) -> float;
+ fn name(self) -> string;
+}
+
+struct Circle {
+ radius: float;
+}
+
+impl Shape for Circle {
+ fn area(self) -> float {
+ return 3.14159 * self.radius * self.radius;
+ }
+ fn name(self) -> string {
+ return "Circle";
+ }
+}
+
+struct Rectangle {
+ width: float;
+ height: float;
+}
+
+impl Shape for Rectangle {
+ fn area(self) -> float {
+ return self.width * self.height;
+ }
+ fn name(self) -> string {
+ return "Rectangle";
+ }
+}
+
+@derive(Debug, Clone, Eq)
+struct Point {
+ x: int;
+ y: int;
+}
+
+
+fn print_shape_info(s: Shape) {
+ println "Shape: {s.name()}, Area: {s.area()}";
+}
+
+test "basic_traits" {
+ var r: Robot = Robot { id: 42 };
+ var g: Greeter = &r;
+
+ g.greet("Hello World");
+ g.shout();
+}
+
+test "advanced_traits" {
+ var c = Circle { radius: 5.0 };
+ var r = Rectangle { width: 4.0, height: 6.0 };
+
+ var s_c: Shape = &c;
+ var s_r: Shape = &r;
+
+ print_shape_info(s_c);
+ print_shape_info(s_r);
+
+ if (s_c.area() > s_r.area()) {
+ println "Circle is larger";
+ } else {
+ println "Rectangle is larger";
+ }
+}
+
+test "test_derive" {
+ var p1 = Point{x: 10, y: 20};
+
+ // Debug
+ var s = p1.to_string();
+ assert(strcmp(s, "Point { ... }") == 0, "Debug string matches");
+
+ // Clone
+ var p2 = p1.clone();
+ assert(p2.x == 10, "Clone x matches");
+
+ // Eq
+ assert(p1.eq(p2) == true, "Eq works (true)");
+
+ var p3 = Point{x: 10, y: 21};
+ assert(p1.eq(p3) == false, "Eq works (false)");
+}