summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-18 12:46:05 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-18 12:46:05 +0000
commita7eceb21faf04762379f2ce4d23d21bbc8c11929 (patch)
tree96816551dab17c4255e9fce32fbb48ce47bb539e
parent1d25e066fc1092ecc71a9e593b55427903d697ed (diff)
Deprecate 'repeat' (superfluous), and add named uses.
-rw-r--r--README.md17
-rw-r--r--examples/features/composition.zc38
-rw-r--r--src/parser/parser_stmt.c33
3 files changed, 83 insertions, 5 deletions
diff --git a/README.md b/README.md
index e47f6ea..fcf1634 100644
--- a/README.md
+++ b/README.md
@@ -225,8 +225,8 @@ outer: loop {
if done { break outer; }
}
-// Repeat
-repeat 5 { ... }
+// Repeat N times
+for _ in 0..5 { ... }
```
#### Advanced Control
@@ -358,13 +358,22 @@ var drawable: Drawable = &circle;
```
#### Composition
-Use `use` to mixin fields from another struct.
+Use `use` to embed other structs. You can either mix them in (flatten fields) or name them (nest fields).
+
```zc
struct Entity { id: int; }
+
struct Player {
- use Entity; // Adds 'id' field
+ // Mixin (Unnamed): Flattens fields
+ use Entity; // Adds 'id' to Player directly
name: string;
}
+
+struct Match {
+ // Composition (Named): Nests fields
+ use p1: Player; // Accessed via match.p1
+ use p2: Player; // Accessed via match.p2
+}
```
### 10. Generics
diff --git a/examples/features/composition.zc b/examples/features/composition.zc
new file mode 100644
index 0000000..883c348
--- /dev/null
+++ b/examples/features/composition.zc
@@ -0,0 +1,38 @@
+
+struct Vector2 {
+ x: float;
+ y: float;
+}
+
+// Unnamed use (Mixin)
+// Transform "is a" Vector2 (inherits x and y)
+struct Transform {
+ use Vector2;
+ rotation: float;
+}
+
+// Named use (Composition)
+// Rigidbody "has a" velocity and position
+struct Rigidbody {
+ use position: Vector2;
+ use velocity: Vector2;
+ mass: float;
+}
+
+fn main() {
+ // Mixin usage - flattened fields
+ var t = Transform{ x: 10.0, y: 5.0, rotation: 90.0 };
+ println "Transform pos: ({t.x}, {t.y})";
+
+ // Named usage - nested fields
+ var rb = Rigidbody{
+ position: Vector2{x: 0.0, y: 10.0},
+ velocity: Vector2{x: 1.0, y: 0.0},
+ mass: 50.0
+ };
+
+ // Access using dot notation
+ rb.position.x += rb.velocity.x;
+
+ println "Rigidbody pos: ({rb.position.x}, {rb.position.y})";
+}
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c
index d78a9e8..6a0f50d 100644
--- a/src/parser/parser_stmt.c
+++ b/src/parser/parser_stmt.c
@@ -382,7 +382,8 @@ ASTNode *parse_loop(ParserContext *ctx, Lexer *l)
ASTNode *parse_repeat(ParserContext *ctx, Lexer *l)
{
- lexer_next(l);
+ Token t = lexer_next(l);
+ zwarn_at(t, "repeat is deprecated. Use 'for _ in 0..N' instead.");
char *c = rewrite_expr_methods(ctx, parse_condition_raw(ctx, l));
ASTNode *b = parse_block(ctx, l);
ASTNode *n = ast_create(NODE_REPEAT);
@@ -3330,6 +3331,36 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union)
if (t.type == TOK_USE)
{
lexer_next(l); // eat use
+
+ // Check for named use: use name: Type;
+ Token t1 = lexer_peek(l);
+ Token t2 = lexer_peek2(l);
+
+ if (t1.type == TOK_IDENT && t2.type == TOK_COLON)
+ {
+ // Named use -> Composition (Add field, don't flatten)
+ Token field_name = lexer_next(l);
+ lexer_next(l); // eat :
+ char *field_type_str = parse_type(ctx, l);
+ expect(l, TOK_SEMICOLON, "Expected ;");
+
+ ASTNode *nf = ast_create(NODE_FIELD);
+ nf->field.name = token_strdup(field_name);
+ nf->field.type = field_type_str;
+
+ if (!h)
+ {
+ h = nf;
+ }
+ else
+ {
+ tl->next = nf;
+ }
+ tl = nf;
+ continue;
+ }
+
+ // Normal use -> Mixin (Flatten)
// Parse the type (e.g. Header<I32>)
Type *use_type = parse_type_formal(ctx, l);
char *use_name = type_to_string(use_type);