feat: impl 关键字改为 extend
This commit is contained in:
@@ -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`
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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,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
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user