Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ebe551ee3 |
+6
-1
@@ -51,11 +51,16 @@ AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size
|
|||||||
}
|
}
|
||||||
|
|
||||||
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type,
|
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type,
|
||||||
const char* struct_type_name, bool is_out, SourceLoc loc) {
|
const char* struct_type_name, bool is_out,
|
||||||
|
TypeKind arr_elem, const char* arr_elem_sname,
|
||||||
|
int64_t arr_size, SourceLoc loc) {
|
||||||
NEW(alloc, AST_PARAMETER);
|
NEW(alloc, AST_PARAMETER);
|
||||||
n->as.parameter.name = name; n->as.parameter.type = type;
|
n->as.parameter.name = name; n->as.parameter.type = type;
|
||||||
n->as.parameter.struct_type_name = struct_type_name;
|
n->as.parameter.struct_type_name = struct_type_name;
|
||||||
n->as.parameter.is_out = is_out;
|
n->as.parameter.is_out = is_out;
|
||||||
|
n->as.parameter.arr_elem_type = arr_elem;
|
||||||
|
n->as.parameter.arr_elem_struct = arr_elem_sname;
|
||||||
|
n->as.parameter.arr_size = arr_size;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -76,7 +76,8 @@ struct AstNode {
|
|||||||
TypeKind* multi_ret_types; const char** multi_ret_snames; size_t multi_ret_count;
|
TypeKind* multi_ret_types; const char** multi_ret_snames; size_t multi_ret_count;
|
||||||
const char** captured; TypeKind* cap_types; size_t cap_count; } function;
|
const char** captured; TypeKind* cap_types; size_t cap_count; } function;
|
||||||
// AST_PARAMETER (也用作结构体字段: name + type)
|
// AST_PARAMETER (也用作结构体字段: name + type)
|
||||||
struct { const char* name; TypeKind type; const char* struct_type_name; bool is_out; } parameter;
|
struct { const char* name; TypeKind type; const char* struct_type_name; bool is_out;
|
||||||
|
TypeKind arr_elem_type; const char* arr_elem_struct; int64_t arr_size; } parameter;
|
||||||
// AST_BLOCK
|
// AST_BLOCK
|
||||||
struct { struct AstNode** stmts; size_t stmt_count; } block;
|
struct { struct AstNode** stmts; size_t stmt_count; } block;
|
||||||
// AST_LET_STMT
|
// AST_LET_STMT
|
||||||
@@ -158,7 +159,8 @@ AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size
|
|||||||
TypeKind ret, const char* ret_struct_name, AstNode* body,
|
TypeKind ret, const char* ret_struct_name, AstNode* body,
|
||||||
bool is_pub, const char** type_params, size_t tp_count,
|
bool is_pub, const char** type_params, size_t tp_count,
|
||||||
SourceLoc loc);
|
SourceLoc loc);
|
||||||
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, const char* struct_type_name, bool is_out, SourceLoc loc);
|
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, const char* struct_type_name, bool is_out,
|
||||||
|
TypeKind arr_elem, const char* arr_elem_sname, int64_t arr_size, SourceLoc loc);
|
||||||
AstNode* ast_make_block(void* alloc, AstNode** stmts, size_t count, SourceLoc loc);
|
AstNode* ast_make_block(void* alloc, AstNode** stmts, size_t count, SourceLoc loc);
|
||||||
AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool has_type_annot,
|
AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool has_type_annot,
|
||||||
bool is_mut, AstNode* init, const char* struct_type_name,
|
bool is_mut, AstNode* init, const char* struct_type_name,
|
||||||
|
|||||||
@@ -416,6 +416,11 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
|
|||||||
if (param->as.parameter.type == TYPE_STRUCT &&
|
if (param->as.parameter.type == TYPE_STRUCT &&
|
||||||
param->as.parameter.struct_type_name) {
|
param->as.parameter.struct_type_name) {
|
||||||
inner_ty = find_struct_type(&ctx, param->as.parameter.struct_type_name);
|
inner_ty = find_struct_type(&ctx, param->as.parameter.struct_type_name);
|
||||||
|
} else if (param->as.parameter.type == TYPE_ARRAY) {
|
||||||
|
LLVMTypeRef et = param->as.parameter.arr_elem_struct
|
||||||
|
? (find_struct_type(&ctx, param->as.parameter.arr_elem_struct) ?: LLVMInt64TypeInContext(ctx.context))
|
||||||
|
: to_llvm_type(&ctx, param->as.parameter.arr_elem_type);
|
||||||
|
inner_ty = LLVMArrayType(et, (unsigned)param->as.parameter.arr_size);
|
||||||
} else {
|
} else {
|
||||||
inner_ty = to_llvm_type(&ctx, param->as.parameter.type);
|
inner_ty = to_llvm_type(&ctx, param->as.parameter.type);
|
||||||
}
|
}
|
||||||
@@ -480,6 +485,11 @@ LLVMModuleRef codegen_module(AstNode* ast, Arena* codegen_arena,
|
|||||||
if (pnode->as.parameter.type == TYPE_STRUCT &&
|
if (pnode->as.parameter.type == TYPE_STRUCT &&
|
||||||
pnode->as.parameter.struct_type_name) {
|
pnode->as.parameter.struct_type_name) {
|
||||||
param_ty = find_struct_type(&ctx, pnode->as.parameter.struct_type_name);
|
param_ty = find_struct_type(&ctx, pnode->as.parameter.struct_type_name);
|
||||||
|
} else if (pnode->as.parameter.type == TYPE_ARRAY) {
|
||||||
|
LLVMTypeRef et = pnode->as.parameter.arr_elem_struct
|
||||||
|
? (find_struct_type(&ctx, pnode->as.parameter.arr_elem_struct) ?: LLVMInt64TypeInContext(ctx.context))
|
||||||
|
: to_llvm_type(&ctx, pnode->as.parameter.arr_elem_type);
|
||||||
|
param_ty = LLVMArrayType(et, (unsigned)pnode->as.parameter.arr_size);
|
||||||
} else {
|
} else {
|
||||||
param_ty = to_llvm_type(&ctx, pnode->as.parameter.type);
|
param_ty = to_llvm_type(&ctx, pnode->as.parameter.type);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -338,7 +338,9 @@ AstNode* parse_expr_prec(Parser* p, Precedence min_prec, ErrorInfo* error) {
|
|||||||
if (pti.kind == TYPE_ERROR) return NULL;
|
if (pti.kind == TYPE_ERROR) return NULL;
|
||||||
plist[pc++] = ast_make_parameter(p->arena,
|
plist[pc++] = ast_make_parameter(p->arena,
|
||||||
arena_strdup_impl(p->arena, pname->start, pname->length),
|
arena_strdup_impl(p->arena, pname->start, pname->length),
|
||||||
pti.kind, pti.struct_name, is_out, tok_loc(pname));
|
pti.kind, pti.struct_name, is_out,
|
||||||
|
pti.element_type, pti.element_struct_name, pti.array_size,
|
||||||
|
tok_loc(pname));
|
||||||
if (match(p, TOK_COMMA)) continue; else break;
|
if (match(p, TOK_COMMA)) continue; else break;
|
||||||
}
|
}
|
||||||
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
|
if (!expect(p, TOK_RPAREN, error, "缺少 ')'")) return NULL;
|
||||||
|
|||||||
+7
-3
@@ -27,7 +27,9 @@ AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
|
|||||||
}
|
}
|
||||||
fields[fcount++] = ast_make_parameter(p->arena,
|
fields[fcount++] = ast_make_parameter(p->arena,
|
||||||
arena_strdup_impl(p->arena, fname->start, fname->length),
|
arena_strdup_impl(p->arena, fname->start, fname->length),
|
||||||
fti.kind, fti.struct_name, false, tok_loc(fname));
|
fti.kind, fti.struct_name, false,
|
||||||
|
fti.element_type, fti.element_struct_name, fti.array_size,
|
||||||
|
tok_loc(fname));
|
||||||
if (peek(p)->kind == TOK_COMMA) advance(p);
|
if (peek(p)->kind == TOK_COMMA) advance(p);
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
@@ -356,7 +358,9 @@ AstNode* parse_function(Parser* p, bool is_pub, ErrorInfo* error) {
|
|||||||
if (pti.kind == TYPE_ERROR) return NULL;
|
if (pti.kind == TYPE_ERROR) return NULL;
|
||||||
params[pcount++] = ast_make_parameter(p->arena,
|
params[pcount++] = ast_make_parameter(p->arena,
|
||||||
arena_strdup_impl(p->arena, pname->start, pname->length),
|
arena_strdup_impl(p->arena, pname->start, pname->length),
|
||||||
pti.kind, pti.struct_name, is_out, tok_loc(pname));
|
pti.kind, pti.struct_name, is_out,
|
||||||
|
pti.element_type, pti.element_struct_name, pti.array_size,
|
||||||
|
tok_loc(pname));
|
||||||
if (match(p, TOK_COMMA)) continue;
|
if (match(p, TOK_COMMA)) continue;
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
@@ -700,7 +704,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
|||||||
arena_strdup_impl(p.arena, fbuf, strlen(fbuf)),
|
arena_strdup_impl(p.arena, fbuf, strlen(fbuf)),
|
||||||
fn->as.function.multi_ret_types[i],
|
fn->as.function.multi_ret_types[i],
|
||||||
fn->as.function.multi_ret_snames[i],
|
fn->as.function.multi_ret_snames[i],
|
||||||
false, tok_loc(peek(&p)));
|
false, 0, NULL, 0, tok_loc(peek(&p)));
|
||||||
}
|
}
|
||||||
if (struct_count >= 64) { error->message = "结构体过多"; return NULL; }
|
if (struct_count >= 64) { error->message = "结构体过多"; return NULL; }
|
||||||
structs[struct_count++] = ast_make_struct_decl(p.arena,
|
structs[struct_count++] = ast_make_struct_decl(p.arena,
|
||||||
|
|||||||
@@ -161,6 +161,11 @@ void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* a) {
|
|||||||
AstNode* p = mono_fn->as.function.params[j];
|
AstNode* p = mono_fn->as.function.params[j];
|
||||||
Symbol* ps = scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, p->as.parameter.type);
|
Symbol* ps = scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, p->as.parameter.type);
|
||||||
if (ps && p->as.parameter.is_out) { ps->kind = SYM_VARIABLE; ps->is_mut = true; }
|
if (ps && p->as.parameter.is_out) { ps->kind = SYM_VARIABLE; ps->is_mut = true; }
|
||||||
|
if (ps && p->as.parameter.type == TYPE_ARRAY) {
|
||||||
|
ps->array_element_type = p->as.parameter.arr_elem_type;
|
||||||
|
ps->array_element_struct_name = p->as.parameter.arr_elem_struct;
|
||||||
|
ps->array_size = p->as.parameter.arr_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 分析函数体
|
// 分析函数体
|
||||||
current_return_type = mono_fn->as.function.return_type;
|
current_return_type = mono_fn->as.function.return_type;
|
||||||
@@ -202,6 +207,11 @@ void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* a) {
|
|||||||
if (sym && pt == TYPE_STRUCT && psn) {
|
if (sym && pt == TYPE_STRUCT && psn) {
|
||||||
sym->struct_type_name = psn;
|
sym->struct_type_name = psn;
|
||||||
}
|
}
|
||||||
|
if (sym && pt == TYPE_ARRAY) {
|
||||||
|
sym->array_element_type = p->as.parameter.arr_elem_type;
|
||||||
|
sym->array_element_struct_name = p->as.parameter.arr_elem_struct;
|
||||||
|
sym->array_size = p->as.parameter.arr_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 解析返回类型的别名
|
// 解析返回类型的别名
|
||||||
const char* ret_sn = node->as.function.return_struct_type_name;
|
const char* ret_sn = node->as.function.return_struct_type_name;
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// === 五子棋 5x5 — L Language 综合测试 (带简单AI) ===
|
||||||
|
fn idx(x: i64, y: i64) -> i64 { return y * 5 + x; }
|
||||||
|
|
||||||
|
fn count_dir(b: i64[25], x: i64, y: i64, dx: i64, dy: i64, color: i64) -> i64 {
|
||||||
|
var cx = x + dx; var cy = y + dy; var n = 0;
|
||||||
|
while cx >= 0 { if cx > 4 { return n; } if cy < 0 { return n; } if cy > 4 { return n; }
|
||||||
|
if b[idx(cx, cy)] != color { return n; }
|
||||||
|
n = n + 1; cx = cx + dx; cy = cy + dy; }
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn score_pos(b: i64[25], x: i64, y: i64, c: i64) -> i64 {
|
||||||
|
if b[idx(x, y)] != 0 { return -1; }
|
||||||
|
var h = count_dir(b, x, y, 1, 0, c) + count_dir(b, x, y, -1, 0, c);
|
||||||
|
var v = count_dir(b, x, y, 0, 1, c) + count_dir(b, x, y, 0, -1, c);
|
||||||
|
var d = count_dir(b, x, y, 1, 1, c) + count_dir(b, x, y, -1, -1, c);
|
||||||
|
var e = count_dir(b, x, y, 1, -1, c) + count_dir(b, x, y, -1, 1, c);
|
||||||
|
if h > 2 { return 1000; } if v > 2 { return 1000; }
|
||||||
|
if d > 2 { return 1000; } if e > 2 { return 1000; }
|
||||||
|
return h + v + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ai(b: i64[25], c: i64) -> i64 {
|
||||||
|
var bx = 2; var by = 2; var bs = -1; var x = 0;
|
||||||
|
while x < 5 { var y = 0; while y < 5 {
|
||||||
|
var s = score_pos(b, x, y, c);
|
||||||
|
if s > bs { bs = s; bx = x; by = y; }
|
||||||
|
y = y + 1; } x = x + 1; }
|
||||||
|
return by * 100 + bx;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn won(b: i64[25], x: i64, y: i64) -> bool {
|
||||||
|
var c = b[idx(x, y)]; if c == 0 { return false; }
|
||||||
|
if count_dir(b, x, y, 1, 0, c) + count_dir(b, x, y, -1, 0, c) > 2 { return true; }
|
||||||
|
if count_dir(b, x, y, 0, 1, c) + count_dir(b, x, y, 0, -1, c) > 2 { return true; }
|
||||||
|
if count_dir(b, x, y, 1, 1, c) + count_dir(b, x, y, -1, -1, c) > 2 { return true; }
|
||||||
|
if count_dir(b, x, y, 1, -1, c) + count_dir(b, x, y, -1, 1, c) > 2 { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print5(b: i64[25]) -> void {
|
||||||
|
var r = 0; while r < 5 {
|
||||||
|
var line = ""; var c = 0; while c < 5 {
|
||||||
|
var v = b[idx(c, r)];
|
||||||
|
if v == 0 { line = line + ". "; }
|
||||||
|
if v == 1 { line = line + "X "; }
|
||||||
|
if v == 2 { line = line + "O "; }
|
||||||
|
c = c + 1; } print_str(line); r = r + 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> void {
|
||||||
|
var b: i64[25] = b; var i = 0; while i < 25 { b[i] = 0; i = i + 1; }
|
||||||
|
b[idx(2, 2)] = 1; var turn = 2; var n = 1;
|
||||||
|
while n < 25 {
|
||||||
|
var mv = ai(b, turn); var y = mv / 100; var x = mv - y * 100;
|
||||||
|
b[idx(x, y)] = turn;
|
||||||
|
if turn == 1 { print_str("X: "); } else { print_str("O: "); }
|
||||||
|
print_i64(x); print_i64(y);
|
||||||
|
if won(b, x, y) { print5(b); if turn == 1 { print_str("X wins!"); } else { print_str("O wins!"); } return; }
|
||||||
|
n = n + 1; if turn == 1 { turn = 2; } else { turn = 1; }
|
||||||
|
}
|
||||||
|
print5(b); print_str("Draw");
|
||||||
|
}
|
||||||
+7
-7
@@ -129,8 +129,8 @@ void test_codegen_struct_decl() {
|
|||||||
|
|
||||||
/* 构造 AST: struct Point { x: i64, y: i64 } */
|
/* 构造 AST: struct Point { x: i64, y: i64 } */
|
||||||
AstNode* fields[2];
|
AstNode* fields[2];
|
||||||
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
||||||
AstNode* structs[] = { struct_decl };
|
AstNode* structs[] = { struct_decl };
|
||||||
|
|
||||||
@@ -185,8 +185,8 @@ void test_codegen_struct_field_access() {
|
|||||||
|
|
||||||
/* 构造 AST: struct Point { x: i64, y: i64 } */
|
/* 构造 AST: struct Point { x: i64, y: i64 } */
|
||||||
AstNode* fields[2];
|
AstNode* fields[2];
|
||||||
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
||||||
AstNode* structs[] = { struct_decl };
|
AstNode* structs[] = { struct_decl };
|
||||||
|
|
||||||
@@ -356,13 +356,13 @@ void test_codegen_method_call() {
|
|||||||
|
|
||||||
/* struct Point { x: i64, y: i64 } */
|
/* struct Point { x: i64, y: i64 } */
|
||||||
AstNode* fields[2];
|
AstNode* fields[2];
|
||||||
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[0] = ast_make_parameter(&a, "x", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, loc_at(1, 1));
|
fields[1] = ast_make_parameter(&a, "y", TYPE_I64, NULL, false, 0, NULL, 0, loc_at(1, 1));
|
||||||
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
AstNode* struct_decl = ast_make_struct_decl(&a, "Point", fields, 2, loc_at(1, 1));
|
||||||
AstNode* structs[] = { struct_decl };
|
AstNode* structs[] = { struct_decl };
|
||||||
|
|
||||||
/* fn Point$get_x(self: Point) -> i64 { return self.x; } */
|
/* fn Point$get_x(self: Point) -> i64 { return self.x; } */
|
||||||
AstNode* self_param = ast_make_parameter(&a, "self", TYPE_STRUCT, "Point", false, loc_at(1, 1));
|
AstNode* self_param = ast_make_parameter(&a, "self", TYPE_STRUCT, "Point", false, 0, NULL, 0, loc_at(1, 1));
|
||||||
AstNode* params[] = { self_param };
|
AstNode* params[] = { self_param };
|
||||||
AstNode* self_ident = ast_make_ident(&a, "self", loc_at(1, 1));
|
AstNode* self_ident = ast_make_ident(&a, "self", loc_at(1, 1));
|
||||||
self_ident->type.kind = TYPE_STRUCT;
|
self_ident->type.kind = TYPE_STRUCT;
|
||||||
|
|||||||
Reference in New Issue
Block a user