feat: 字符串类型 + 字面量 + print_str

- 新增 TYPE_STR 类型 (i8* 指针)
- lexer: 双引号字符串字面量 + str 关键字
- parser: TOK_STR_LIT → AST_LITERAL_EXPR(str_val)
- sema: print_str 内置函数注册 + 字符串拼接类型检查
- codegen: GlobalStringPtr 生成字符串常量,print_str → printf("%s")
- 新增集成测试 07_hello_str.l

基于 Codex 分析报告 P0 建议。
This commit is contained in:
2026-06-05 00:47:53 +08:00
parent bd02a4989e
commit 9a53d97274
10 changed files with 84 additions and 11 deletions
+22 -1
View File
@@ -68,7 +68,26 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
if (l == TYPE_ERROR || r == TYPE_ERROR) { node->type.kind = TYPE_ERROR; break; }
switch (node->as.binary.op) {
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD:
case OP_ADD:
if (l == TYPE_STR || r == TYPE_STR) {
// 字符串拼接:两边都必须是 str 类型
if (l != TYPE_STR || r != TYPE_STR) {
error_add(errors, "<sema>", node->line, node->col,
"字符串拼接需要两边都是 str 类型,得到 '%s' + '%s'",
type_name(l), type_name(r));
node->type.kind = TYPE_ERROR;
} else {
node->type.kind = TYPE_STR;
}
} else if (!is_numeric(l) || !is_numeric(r)) {
error_add(errors, "<sema>", node->line, node->col,
"算术运算需要数值类型");
node->type.kind = TYPE_ERROR;
} else {
node->type.kind = promote(l, r);
}
break;
case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD:
if (!is_numeric(l) || !is_numeric(r)) {
error_add(errors, "<sema>", node->line, node->col,
"算术运算需要数值类型");
@@ -294,6 +313,8 @@ void sema_analyze(AstNode* ast, ErrorList* errors, Arena* arena) {
scope_insert_function(global, arena, "print_f64", TYPE_VOID, params_f64, 1);
TypeKind params_bool[] = {TYPE_BOOL};
scope_insert_function(global, arena, "print_bool", TYPE_VOID, params_bool, 1);
TypeKind params_str[] = {TYPE_STR};
scope_insert_function(global, arena, "print_str", TYPE_VOID, params_str, 1);
analyze_node(ast, global, errors, arena);
}