feat: impl 关键字改为 extend

This commit is contained in:
2026-06-05 19:50:40 +08:00
parent 175f8a6658
commit 6fc599e6c2
8 changed files with 16 additions and 16 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ graph TB
- 多参数、递归、struct 参数/返回值 - 多参数、递归、struct 参数/返回值
- 返回类型校验 - 返回类型校验
- `impl StructName { fn method(self: Type) -> Ret { ... } }` - `extend StructName { fn method(self: Type) -> Ret { ... } }`
- `instance.method(args)` 调用 - `instance.method(args)` 调用
- 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str` - 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str`
+5 -5
View File
@@ -297,10 +297,10 @@ fn print_point(p: Point) -> void {
} }
``` ```
### impl — 方法 ### extend — 方法
```rust ```rust
impl Point { extend Point {
fn new(x: i64, y: i64) -> Point { fn new(x: i64, y: i64) -> Point {
return Point { x: x, y: y }; return Point { x: x, y: y };
} }
@@ -314,7 +314,7 @@ let p = Point.new(10, 20); // 方法调用
print_i64(p.get_x()); // 10 print_i64(p.get_x()); // 10
``` ```
- `impl StructName { fn ... }` 定义方法 - `extend StructName { fn ... }` 为结构体扩展方法
- 第一个参数必须是 `self: StructName` - 第一个参数必须是 `self: StructName`
- 调用: `instance.method(args)` - 调用: `instance.method(args)`
@@ -456,7 +456,7 @@ struct Student {
score: i64, score: i64,
} }
impl Student { extend Student {
fn new(id: i64, score: i64) -> Student { fn new(id: i64, score: i64) -> Student {
return Student { name_id: id, score: score }; 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; } 函数: fn name(p: T) -> Ret { return expr; }
结构体: struct Name { f: Type } Name { f: val } 结构体: struct Name { f: Type } Name { f: val }
枚举: enum Name { A, B, C } Name::B 枚举: 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 内建: print_i64 print_f64 print_bool print_str
运算符: + - * / % == != < > <= >= && || ! += -= *= /= 运算符: + - * / % == != < > <= >= && || ! += -= *= /=
注释: // 行注释 /* 块注释 */ 注释: // 行注释 /* 块注释 */
+1 -1
View File
@@ -64,7 +64,7 @@ static TokenKind check_keyword(const Token* tok) {
KW("bool", TOK_BOOL); KW("str", TOK_STR); KW("bool", TOK_BOOL); KW("str", TOK_STR);
KW("void", TOK_VOID); KW("void", TOK_VOID);
KW("struct", TOK_STRUCT); KW("type", TOK_TYPE); 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("_", TOK_UNDERSCORE);
KW("true", TOK_TRUE); KW("false", TOK_FALSE); KW("true", TOK_TRUE); KW("false", TOK_FALSE);
#undef KW #undef KW
+1 -1
View File
@@ -7,7 +7,7 @@
static const char* NAMES[] = { static const char* NAMES[] = {
[TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if", [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_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_MATCH] = "match",
[TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void", [TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void",
[TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串", [TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串",
+1 -1
View File
@@ -7,7 +7,7 @@
typedef enum { typedef enum {
// 关键字 // 关键字
TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, 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, TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
// 字面量 // 字面量
+5 -5
View File
@@ -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)); 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; } 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; 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* 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 (!st_name) return NULL;
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL; if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
AstNode* methods[64]; int mcount = 0; AstNode* methods[64]; int mcount = 0;
while (peek(&p)->kind != TOK_RBRACE && !error->message) { 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 (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); methods[mcount++] = parse_function(&p, error);
} }
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL; if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*)); AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
memcpy(m_arr, methods, 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, impls[impl_count++] = ast_make_impl_block(p.arena,
arena_strdup_impl(p.arena, st_name->start, st_name->length), arena_strdup_impl(p.arena, st_name->start, st_name->length),
m_arr, mcount, tok_loc(i_tok)); 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; } 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); functions[fn_count++] = parse_function(&p, error);
} else { } else {
error->message = "顶层只允许 fn、struct、type、enum 或 impl"; error->message = "顶层只允许 fn、struct、type、enum 或 extend";
error->filename = p.filename; error->filename = p.filename;
error->line = peek(&p)->line; error->line = peek(&p)->line;
error->col = peek(&p)->col; error->col = peek(&p)->col;
+1 -1
View File
@@ -1,6 +1,6 @@
struct Point { x: i64, y: i64 } struct Point { x: i64, y: i64 }
impl Point { extend Point {
fn get_x(self: Point) -> i64 { fn get_x(self: Point) -> i64 {
return self.x; return self.x;
} }
+1 -1
View File
@@ -335,7 +335,7 @@ void test_method_call_ok() {
Arena a = arena_create(1); Arena a = arena_create(1);
size_t tc; ErrorInfo lex_err = {0}; size_t tc; ErrorInfo lex_err = {0};
Token* toks = lex(&a, 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); "test", &tc, &lex_err);
ASSERT(toks != NULL); ASSERT(toks != NULL);
ErrorInfo parse_err = {0}; ErrorInfo parse_err = {0};