From 946e4082ccc3a7e528386e7bcf9bf199d136db73 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 14 Jun 2022 12:00:48 +0200 Subject: [PATCH] Working on slices, builtin stuff feels wanky, rewrite gen_simple_decl to generate string --- ast.cpp | 3 +- ccodegen.cpp | 177 +++++++++++++++++++++++++++++++++-------------- compiler.h | 17 ++--- typechecking.cpp | 23 +++++- typechecking.h | 3 +- 5 files changed, 159 insertions(+), 64 deletions(-) diff --git a/ast.cpp b/ast.cpp index 00d154e..74a4bb0 100644 --- a/ast.cpp +++ b/ast.cpp @@ -65,7 +65,8 @@ struct Ast{ }; struct Ast_Type; -struct Ast_Expr:Ast{ }; +struct Ast_Expr:Ast{ +}; #define VALUE_FIELDS \ Ast_Type *type; \ diff --git a/ccodegen.cpp b/ccodegen.cpp index 922fa73..3690e71 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -3,9 +3,10 @@ #define genln(...) do{gen("\n"); gen_indent(); gen(__VA_ARGS__); }while(0) global S32 global_indent; global S32 is_inside_struct; +global B32 should_gen_scope_name = false; function void gen_ast(Ast *ast); -function bool gen_expr(Ast_Expr *ast); +function bool gen_expr(Ast_Expr *ast, Ast_Type *type_of_var = 0); function void gen_indent(){ @@ -18,10 +19,20 @@ gen_line(Ast *node){ genln("#line %d", node->pos->line+1); } +function String +string_scope_name(Allocator *a, Ast_Scope *scope){ + String string = {}; + if(!should_gen_scope_name) return string; + if(scope->parent_scope) string = string_scope_name(a, scope->parent_scope); + if(scope->name.str) string_fmt(a, "%Q%s_", string, scope->name.str); + return string; +} + function void gen_scope_name(Ast_Scope *scope){ - if(scope->parent_scope) gen_scope_name(scope->parent_scope); - if(scope->name.str) gen("%s_", scope->name.str); + Scratch scratch; + String string = string_scope_name(scratch, scope); + gen("%.*s", (int)string.len, string.str); } // @todo: Gen complicated decl @@ -33,62 +44,91 @@ gen_scope_name(Ast_Scope *scope){ // 3 Going backwards add arrays and pointers in parens // 4 Add type name on the left side -function void -gen_simple_decl_prefix(Ast_Type *ast, bool scope_names){ +function String +string_simple_decl_prefix(Allocator *a, Ast_Type *ast, bool scope_names){ switch(ast->kind){ - case TYPE_POINTER: gen_simple_decl_prefix(ast->base, scope_names); gen("*"); break; - case TYPE_ARRAY: gen_simple_decl_prefix(ast->base, scope_names); break; - case TYPE_LAMBDA:break; - case TYPE_ENUM:{ - gen_simple_decl_prefix(ast->base, scope_names); break; + case TYPE_POINTER:{ + String string = string_simple_decl_prefix(a, ast->base, scope_names); + string = string_fmt(a, "%Q*", string); + return string; + }break; + case TYPE_LAMBDA: return {}; break; + case TYPE_ENUM: + case TYPE_ARRAY: { + return string_simple_decl_prefix(a, ast->base, scope_names); + }break; + case TYPE_SLICE:{ + String string = string_simple_decl_prefix(a, ast->base, true); + string = string_fmt(a, "SliceOf%Q", string); + return string; }break; case TYPE_STRUCT: { auto constant = (Ast_Decl *)ast->ast; auto name = constant->name; - if(scope_names) gen_scope_name(constant->parent_scope); - gen("%s ", name.str); + String string = string_fmt(a, "%Q ", name); + String sc = {}; + if(scope_names) sc = string_scope_name(a, constant->parent_scope); + return string_fmt(a, "%Q%Q", sc, string); }break; default: { - gen("%s ", name(ast)); + String string = string_fmt(a, "%s ", name(ast)); + return string; } } + return {}; } -function void -gen_simple_decl_postfix(Ast_Type *ast, bool scope_names){ +function String +string_simple_decl_postfix(Allocator *a, Ast_Type *ast, bool scope_names){ switch(ast->kind){ - case TYPE_POINTER: gen_simple_decl_postfix(ast->base, scope_names); break; - case TYPE_ARRAY: - gen("["); - if(ast->arr.size != ARRAY_SIZE_SLICE) - gen("%d", (int)ast->arr.size); - gen("]"); - gen_simple_decl_postfix(ast->arr.base, scope_names); break; + case TYPE_POINTER: + return string_simple_decl_postfix(a, ast->base, scope_names); + break; + case TYPE_ARRAY:{ + String result = string_simple_decl_postfix(a, ast->arr.base, scope_names); + String string = string_fmt(a, "[%d]%Q", ast->arr.size, result); + return string; + }break; case TYPE_LAMBDA:break; - case TYPE_ENUM: case TYPE_STRUCT:break; - default: name(ast); + case TYPE_SLICE: case TYPE_ENUM: case TYPE_STRUCT:break; + default:break; + // default: return string_from_cstring((char *)name(ast)); + } + return {}; +} + +function String +string_simple_decl(Allocator *a, Ast_Type *ast, Intern_String name = {}, Ast_Scope *scope = 0, bool scope_names = true){ + if(ast->kind == TYPE_LAMBDA) { + String prefix = string_simple_decl_prefix(a, ast->func.ret, scope_names); + String string = string_fmt(a, "%Q(*%Q)(", prefix, name); + For(ast->func.args){ + String prefix_arg = string_simple_decl_prefix(a, it, scope_names); + string = string_fmt(a, "%Q%Q", string, prefix_arg); + if(&it != ast->func.args.end() - 1) + string = string_fmt(a, "%Q, ", string); + } + string = string_fmt(a, "%Q)", string); + return string; + } + else{ + String string = string_simple_decl_prefix(a, ast, scope_names); + if(name.len) { + if(scope && scope_names) + string = string_fmt(a, "%Q%Q", string, string_scope_name(a, scope)); + string = string_fmt(a, "%Q%Q", string, name); + } + String postfix = string_simple_decl_postfix(a, ast, scope_names); + string = string_fmt(a, "%Q%Q", string, postfix); + return string; } } function void gen_simple_decl(Ast_Type *ast, Intern_String name = {}, Ast_Scope *scope = 0, bool scope_names = true){ - if(ast->kind == TYPE_LAMBDA) { - gen_simple_decl_prefix(ast->func.ret, scope_names); - gen("(*%s)(", name.str); - For(ast->func.args){ - gen_simple_decl_prefix(it, scope_names); - if(&it != ast->func.args.end() - 1) gen(", "); - } - gen(")"); - } - else{ - gen_simple_decl_prefix(ast, scope_names); - if(name.len) { - if(scope && scope_names) gen_scope_name(scope); - gen("%s", name.str); - } - gen_simple_decl_postfix(ast, scope_names); - } + Scratch scratch; + String string = string_simple_decl(scratch, ast, name, scope, scope_names); + gen("%.*s", (int)string.len, string.str); } function B32 @@ -143,7 +183,7 @@ gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){ if(decl->expr){ gen(" = "); - gen_expr(decl->expr); + gen_expr(decl->expr, decl->type); } else { // Default zero if(is_numeric(decl->type)){ gen(" = 0"); @@ -154,7 +194,7 @@ gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){ } function void -gen_lambda(Intern_String name, Ast_Lambda *lambda){ +gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){ bool is_foreign = is_flag_set(lambda->flags, AST_FOREIGN); if(name == pctx->intern("main"_s)){ is_foreign = true; @@ -163,18 +203,19 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda){ gen("("); For(lambda->args){ gen_var(it, DONT_EMIT_VALUE, true); - if(&it != (lambda->args.end() - 1)) gen(", "); + if(&it != (lambda->args.end() - 1)) + gen(", "); } gen(")"); - if(lambda->scope){ + if(generate_block && lambda->scope){ gen_stmt_scope(lambda->scope); } else gen(";"); } function bool -gen_expr(Ast_Expr *ast){ +gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ switch(ast->kind){ CASE(IDENT, Atom){ if(node->resolved_decl->kind == AST_MODULE_NAMESPACE || node->resolved_decl->kind == AST_FILE_NAMESPACE) @@ -184,8 +225,14 @@ gen_expr(Ast_Expr *ast){ if(is_flag_set(node->resolved_decl->lambda->flags, AST_FOREIGN)) print_scope = false; } - if(print_scope) gen_scope_name(node->resolved_decl->parent_scope); - gen("%s", node->intern_val.str); + if(type_of_var && is_slice(type_of_var) && is_array(node->resolved_decl->type)){ + gen("{%d, ", (int)node->resolved_decl->type->arr.size); + if(print_scope) gen_scope_name(node->resolved_decl->parent_scope); + gen("%s}", node->intern_val.str); + } else { + if(print_scope) gen_scope_name(node->resolved_decl->parent_scope); + gen("%s", node->intern_val.str); + } BREAK(); } @@ -256,6 +303,18 @@ gen_expr(Ast_Expr *ast){ } CASE(CALL, Call){ + if(node->name->kind == AST_IDENT){ + auto ident = (Ast_Atom *)node->name; + if(ident->intern_val == pctx->intern("len"_s)){ + if(is_slice(ident->type)){ + Ast_Call_Item *arg = node->exprs[0]; + gen_expr(arg->item); + gen(".len"); + return true; + } else invalid_codepath; + } + } + gen_expr(node->name); gen("("); For(node->exprs){ @@ -359,7 +418,7 @@ gen_ast(Ast *ast){ } CASE(STRUCT, Decl){ - gen("typedef struct "); + gen("struct "); gen_scope_name(node->parent_scope); gen("%s{", node->name.str); global_indent++; @@ -371,15 +430,13 @@ gen_ast(Ast *ast){ is_inside_struct--; global_indent--; - genln("}"); - gen_scope_name(node->parent_scope); - gen("%s;", node->name.str); + genln("};"); BREAK(); } CASE(TYPE, Decl){ gen("// Type %s = ", node->name.str); - gen_expr(node->expr); + gen_simple_decl(node->type_val); BREAK(); } @@ -613,6 +670,20 @@ typedef struct String{ )=="); #endif + For(pctx->ordered_decls){ + if(it->kind == AST_STRUCT){ + if(it->type && it->type->kind == TYPE_TYPE && is_slice(it->type_val)){ + genln("typedef struct struct "); + gen_simple_decl(it->type_val); + gen(";"); + } else{ + genln("typedef struct struct %s;", it->name.str); + } + } else if(it->kind == AST_LAMBDA){ + genln(""); + gen_lambda(it->name, it->lambda, false); + } + } For(pctx->ordered_decls){ genln(""); diff --git a/compiler.h b/compiler.h index 03d2dc3..df0d02b 100644 --- a/compiler.h +++ b/compiler.h @@ -3,6 +3,7 @@ struct Ast_Decl; struct Ast_File_Namespace; struct Ast_File; struct Ast_Module; +struct Ast_Type; function Ast_Module *ast_module(Intern_String filename); function void insert_builtin_types_into_scope(Ast_Scope *p); @@ -221,14 +222,14 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ function void parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator){ - pctx = ctx; - ctx->perm = perm_allocator; - ctx->heap = heap_allocator; - ctx->gen = {ctx->perm}; - ctx->ordered_decls = {ctx->heap}; - ctx->type_map = {ctx->heap}; - ctx->modules = {ctx->heap}; - bigint_allocator = ctx->perm; + pctx = ctx; + ctx->perm = perm_allocator; + ctx->heap = heap_allocator; + ctx->gen = {ctx->perm}; + ctx->ordered_decls = {ctx->heap}; + ctx->type_map = {ctx->heap}; + ctx->modules = {ctx->heap}; + bigint_allocator = ctx->perm; lex_init(ctx->perm, ctx->heap, ctx); diff --git a/typechecking.cpp b/typechecking.cpp index 2ca04ca..3440902 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -707,7 +707,24 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ if(node->expr){ node->type = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val)); } else{ - node->type = type_slice(type.type_val); + node->type = type_slice(type.type_val, node); + { // @c_backend + Ast_Scope *scope = ast_decl_scope(0, pctx->heap, (Ast_File *)node->parent_scope->file); + + Ast_Decl *len_var = ast_var(0, 0, pctx->intern("len"_s), 0); + len_var->type = type_s64; + scope->decls.add(len_var); + + Ast_Decl *pointer_var = ast_var(0, 0, pctx->intern("data"_s), 0); + pointer_var->type = type.type_val; + scope->decls.add(pointer_var); + + Ast_Decl *struct_decl = ast_struct(0, scope); + struct_decl->name = pctx->intern("SliceOf"_s); + struct_decl->type = type_type; + struct_decl->type_val = node->type; + pctx->ordered_decls.add(struct_decl); + } } @@ -847,10 +864,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ Ast_Call_Item *arg = node->exprs[0]; if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected"); Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL); + ident->type = op.type; + if(is_array(op.type)){ Value val = value_int(op.type->arr.size); rewrite_into_const(node, Ast_Call, val); return operand_const_rvalue(val); + } else if(is_slice(op.type)){ + return operand_rvalue(type_s64); } else compiler_error(node->pos, "Invalid argument"); } } diff --git a/typechecking.h b/typechecking.h index ba91589..a190732 100644 --- a/typechecking.h +++ b/typechecking.h @@ -134,7 +134,7 @@ type_pointer(Ast_Type *base){ } function Ast_Type * -type_slice(Ast_Type *base){ +type_slice(Ast_Type *base, Ast *ast){ U64 hash_base = hash_ptr(base); U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE)); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); @@ -148,6 +148,7 @@ type_slice(Ast_Type *base){ result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice)); result->arr.base = base; result->arr.slice_hash = hash; + result->ast = ast; return result; }