diff --git a/README.md b/README.md index 5c4ca3a..d673d8c 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ graph TB - 多参数、递归、struct 参数/返回值 - 返回类型校验 -- `impl StructName { fn method(self: Type) -> Ret { ... } }` +- `extend StructName { fn method(self: Type) -> Ret { ... } }` - `instance.method(args)` 调用 - 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str` diff --git a/docs/language-reference.md b/docs/language-reference.md index 87784b9..704586b 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -297,10 +297,10 @@ fn print_point(p: Point) -> void { } ``` -### impl — 方法 +### extend — 方法 ```rust -impl Point { +extend Point { fn new(x: i64, y: i64) -> Point { return Point { x: x, y: y }; } @@ -314,7 +314,7 @@ let p = Point.new(10, 20); // 方法调用 print_i64(p.get_x()); // 10 ``` -- `impl StructName { fn ... }` 定义方法 +- `extend StructName { fn ... }` 为结构体扩展方法 - 第一个参数必须是 `self: StructName` - 调用: `instance.method(args)` @@ -456,7 +456,7 @@ struct Student { score: i64, } -impl Student { +extend Student { fn new(id: i64, score: i64) -> Student { return Student { name_id: id, score: score }; } @@ -570,7 +570,7 @@ l_lang.exe source.l --emit-ir 函数: fn name(p: T) -> Ret { return expr; } 结构体: struct Name { f: Type } Name { f: val } 枚举: enum Name { A, B, C } Name::B -方法: impl T { fn m(self: T) } obj.m() +方法: extend T { fn m(self: T) } obj.m() 内建: print_i64 print_f64 print_bool print_str 运算符: + - * / % == != < > <= >= && || ! += -= *= /= 注释: // 行注释 /* 块注释 */ diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 9d55eaa..080e4d5 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -64,7 +64,7 @@ static TokenKind check_keyword(const Token* tok) { KW("bool", TOK_BOOL); KW("str", TOK_STR); KW("void", TOK_VOID); KW("struct", TOK_STRUCT); KW("type", TOK_TYPE); - KW("enum", TOK_ENUM); KW("impl", TOK_IMPL); KW("match", TOK_MATCH); + KW("enum", TOK_ENUM); KW("extend", TOK_EXTEND); KW("match", TOK_MATCH); KW("_", TOK_UNDERSCORE); KW("true", TOK_TRUE); KW("false", TOK_FALSE); #undef KW diff --git a/src/lexer/token.c b/src/lexer/token.c index fcf7a73..2176c0d 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -7,7 +7,7 @@ static const char* NAMES[] = { [TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", [TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return", - [TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_IMPL] = "impl", + [TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_EXTEND] = "extend", [TOK_MATCH] = "match", [TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void", [TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串", diff --git a/src/lexer/token.h b/src/lexer/token.h index fb2e8d3..55cf139 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -7,7 +7,7 @@ typedef enum { // 关键字 TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, - TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_IMPL, TOK_MATCH, + TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_MATCH, // 类型关键字 TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID, // 字面量 diff --git a/src/parser/parser.c b/src/parser/parser.c index 00b84f3..9acec1f 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -777,21 +777,21 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count, AstNode* enum_decl = ast_make_enum_decl(p.arena, arena_strdup_impl(p.arena, name->start, name->length), v_arr, vcount, tok_loc(name)); if (enum_count >= 64) { error->message = "枚举过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } enums[enum_count++] = enum_decl; - } else if (peek(&p)->kind == TOK_IMPL) { + } else if (peek(&p)->kind == TOK_EXTEND) { const Token* i_tok = advance(&p); - const Token* st_name = expect(&p, TOK_IDENT, error, "impl 后应为结构体名"); + const Token* st_name = expect(&p, TOK_IDENT, error, "extend 后应为结构体名"); if (!st_name) return NULL; if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL; AstNode* methods[64]; int mcount = 0; while (peek(&p)->kind != TOK_RBRACE && !error->message) { if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } - if (peek(&p)->kind != TOK_FN) { error->message = "impl 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } + if (peek(&p)->kind != TOK_FN) { error->message = "extend 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } methods[mcount++] = parse_function(&p, error); } if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL; AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*)); memcpy(m_arr, methods, mcount * sizeof(AstNode*)); - if (impl_count >= 64) { error->message = "impl 块过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } + if (impl_count >= 64) { error->message = "extend 块过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } impls[impl_count++] = ast_make_impl_block(p.arena, arena_strdup_impl(p.arena, st_name->start, st_name->length), m_arr, mcount, tok_loc(i_tok)); @@ -799,7 +799,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count, if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; } functions[fn_count++] = parse_function(&p, error); } else { - error->message = "顶层只允许 fn、struct、type、enum 或 impl"; + error->message = "顶层只允许 fn、struct、type、enum 或 extend"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; diff --git a/test/programs/19_struct_method.l b/test/programs/19_struct_method.l index c6f2c8b..f9a3793 100644 --- a/test/programs/19_struct_method.l +++ b/test/programs/19_struct_method.l @@ -1,6 +1,6 @@ struct Point { x: i64, y: i64 } -impl Point { +extend Point { fn get_x(self: Point) -> i64 { return self.x; } diff --git a/test/test_sema.c b/test/test_sema.c index 16b19c7..ed7a986 100644 --- a/test/test_sema.c +++ b/test/test_sema.c @@ -335,7 +335,7 @@ void test_method_call_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; Token* toks = lex(&a, - "struct Point { x: i64, y: i64 } impl Point { fn get_x(self: Point) -> i64 { return self.x; } } fn main() -> i64 { let p: Point = Point { x: 42, y: 0 }; return p.get_x(); }", + "struct Point { x: i64, y: i64 } extend Point { fn get_x(self: Point) -> i64 { return self.x; } } fn main() -> i64 { let p: Point = Point { x: 42, y: 0 }; return p.get_x(); }", "test", &tc, &lex_err); ASSERT(toks != NULL); ErrorInfo parse_err = {0};