diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-18 12:46:05 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-18 12:46:05 +0000 |
| commit | a7eceb21faf04762379f2ce4d23d21bbc8c11929 (patch) | |
| tree | 96816551dab17c4255e9fce32fbb48ce47bb539e | |
| parent | 1d25e066fc1092ecc71a9e593b55427903d697ed (diff) | |
Deprecate 'repeat' (superfluous), and add named uses.
| -rw-r--r-- | README.md | 17 | ||||
| -rw-r--r-- | examples/features/composition.zc | 38 | ||||
| -rw-r--r-- | src/parser/parser_stmt.c | 33 |
3 files changed, 83 insertions, 5 deletions
@@ -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); |
