From 277404fe956bbf0395b4e93bddf427451e13c508 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 31 Mar 2023 17:38:32 +0200 Subject: [PATCH] Iterator + start to add core to core codegen --- base_data_structures.cpp | 2 +- core_ast.cpp | 2 + core_codegen_c_language.cpp | 132 ++++++++++++++++++++++++++++++++---- core_compiler_interface.hpp | 8 ++- core_parsing.cpp | 24 +++++-- core_polymorph.cpp | 91 ++++++++++++++----------- 6 files changed, 198 insertions(+), 61 deletions(-) diff --git a/base_data_structures.cpp b/base_data_structures.cpp index 2457011..bd53b41 100644 --- a/base_data_structures.cpp +++ b/base_data_structures.cpp @@ -39,7 +39,7 @@ struct Array { } void dealloc() { - deallocate(allocator, data); + if (data) deallocate(allocator, data); } S64 get_index(T *item) { diff --git a/core_ast.cpp b/core_ast.cpp index 907ff7c..ac4acfc 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -240,6 +240,7 @@ ast_enum(Token *pos, Ast_Expr *typespec, Ast_Scope *scope) { AST_NEW(Decl, ENUM, pos, AST_DECL); result->scope = scope; result->typespec = typespec; + if (typespec) set_flag(typespec->flags, AST_TYPESPEC); return result; } @@ -248,6 +249,7 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr) { AST_NEW(Decl, VAR, pos, AST_DECL); result->name = name; result->typespec = typespec; + if (typespec) set_flag(typespec->flags, AST_TYPESPEC); result->expr = expr; return result; } diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index ac382cf..ae3cb47 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -83,8 +83,9 @@ get_ctype_name_for_type(Ast_Type *type) { case TYPE_INCOMPLETE: { // This happens in case where we have a procedure in an away module. + // Meaning that it's not resolved fully on purpose (treeshaking). // And that procedure takes a pointer from a struct that is never - // use elsewhere. In that case this seems fine. + // used elsewhere. In that case this seems fine. return "void"; } invalid_default_case; @@ -824,37 +825,144 @@ gen_ast(Ast *ast) { } } +CORE_Static String +core_type_to_string(Ast_Type *type) { + switch (type->kind) { + case TYPE_NONE: return ""_s; break; + case TYPE_S64: return "S64"_s; break; + case TYPE_S32: return "S32"_s; break; + case TYPE_S16: return "S16"_s; break; + case TYPE_S8: return "S8"_s; break; + case TYPE_INT: return "int"_s; break; + case TYPE_CHAR: return "char"_s; break; + case TYPE_U64: return "U64"_s; break; + case TYPE_U32: return "U32"_s; break; + case TYPE_U16: return "U16"_s; break; + case TYPE_U8: return "U8"_s; break; + case TYPE_F32: return "F32"_s; break; + case TYPE_F64: return "F64"_s; break; + case TYPE_BOOL: return "Bool"_s; break; + case TYPE_STRING: return "String"_s; break; + case TYPE_VOID: return "void"_s; break; + case TYPE_POINTER: { + String base = core_type_to_string(type->base); + return pctx->fmt("*%Q", base); + } break; + + case TYPE_LAMBDA: { + String_Builder *b = &pctx->helper_builder; + b->addf("("); + Array &args = type->func.args; + For(args) { + String t = core_type_to_string(it); + b->addf("%Q", t); + if (!args.is_last(&it)) b->addf(", "); + } + b->addf(")"); + if (type->func.ret) { + String t = core_type_to_string(type->func.ret); + b->addf("%Q", t); + } + String result = string_flatten(pctx->perm, b); + return result; + } break; + + case TYPE_STRUCT: + case TYPE_UNION: + case TYPE_ENUM: { + // @fixme: we probably want a string on Ast_Type + // so that we don't have to reach into Ast_Decl + // for Structs Enums etc. + Ast_Decl *decl = (Ast_Decl *)type->ast; + return decl->name.s; + } break; + + case TYPE_ARRAY: { + String base = core_type_to_string(type->base); + return pctx->fmt("[%u]%Q", type->arr.size, base); + } break; + + case TYPE_SLICE: { + String base = core_type_to_string(type->base); + return pctx->fmt("[]%Q", base); + } break; + case TYPE_TUPLE: { + invalid_codepath; + } break; + + case TYPE_TYPE: return "Type"_s; break; + case TYPE_UNTYPED_BOOL: return "UntypedBool"_s; break; + case TYPE_UNTYPED_INT: return "UntypedInt"_s; break; + case TYPE_UNTYPED_FLOAT: return "UntypedFloat"_s; break; + case TYPE_UNTYPED_STRING: return "UntypedString"_s; break; + + case TYPE_COMPLETING: invalid_codepath; break; + case TYPE_INCOMPLETE: invalid_codepath; break; + case TYPE_POLYMORPH: + invalid_codepath; + break; + + invalid_default_case; + } + invalid_return; +} + CORE_Static String compile_to_c_code() { pctx->time.code_generation = os_time(); + int di = 0; For(pctx->ordered_decls) { for (Ast_Iter iter = iterate_depth_first(pctx->heap, it); iter.ast; next(&iter)) { Ast_Decl *decl = (Ast_Decl *)iter.ast; + Ast *ast = iter.ast; + Ast_Atom *atom = (Ast_Atom *)iter.ast; + switch (iter.kind) { case AST_STRUCT: { - genln("(struct %s", decl->name.str); + genln("%Q :: struct", decl->name); global_indent += 1; } break; - case AST_STRUCT + 128: { + case AST_STRUCT + AST_NODE_END: { + global_indent -= 1; + } break; + case AST_LAMBDA: { + Ast_Lambda *lambda = decl->lambda; + genln("%Q :: (", decl->name); + For(lambda->args) { + gen("%Q: %Q, ", it->name, core_type_to_string(it->type)); + } + gen(")"); + + // @cleanup @refactor: return value shouldn't be a array of expressions. + // It should be a single expression. So probably need a special type + // for that. + if (lambda->args.len) { + gen(": "); + For(lambda->args) { + gen("%Q ", core_type_to_string(it->type)); + } + } + + iter.skip_children = true; + iter.stack.add(decl); + if (lambda->scope) iter.stack.add(lambda->scope); + global_indent += 1; + } break; + case AST_LAMBDA + AST_NODE_END: { global_indent -= 1; - genln(")"); } break; case AST_VAR: { - genln("(var %s: ", decl->name.str); - auto typespec = (Ast_Atom *)decl->typespec; - Ast_Decl *type = typespec->resolved_decl; - assert(typespec); - gen("%s", type->name.str); + genln("%Q: %Q", decl->name, core_type_to_string(decl->type)); } break; - case AST_VAR + 128: { - gen(")"); + case AST_VAR + AST_NODE_END: { } break; } } String str = string_flatten(pctx->perm, &pctx->gen); - printf("%s", str.str); + printf("%s\n", str.str); pctx->gen.reset(); + di += 1; } prefixed_string_type = string_fmt(pctx->perm, "%QString", pctx->symbol_prefix); diff --git a/core_compiler_interface.hpp b/core_compiler_interface.hpp index c77f420..29ce74c 100644 --- a/core_compiler_interface.hpp +++ b/core_compiler_interface.hpp @@ -361,6 +361,8 @@ enum { AST_IDENT_POLYMORPH = 1 << 15, AST_TYPE_POLYMORPH = 1 << 16, AST_POLYMORPH = AST_IDENT_POLYMORPH | AST_TYPE_POLYMORPH, + + AST_TYPESPEC = 1 << 17, }; struct Ast { @@ -505,11 +507,11 @@ struct Ast_For : Ast { bool is_also_slice_traversal; }; -// @cleanup @refactor: return value shouldn't be a array of expressions. -// It should be a single expression. So probably need a special type -// for that. struct Ast_Lambda : Ast_Expr { Array args; + // @cleanup @refactor: return value shouldn't be a array of expressions. + // It should be a single expression. So probably need a special type + // for that. Array ret; Ast_Scope *scope; }; diff --git a/core_parsing.cpp b/core_parsing.cpp index 52305ec..f1f0c82 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -266,7 +266,9 @@ parse_expr_call(Ast_Expr *left, Token_Kind close_kind) { CORE_Static Ast_Expr * parse_optional_type() { Ast_Expr *result = 0; - if (token_match(TK_Colon)) result = parse_expr(); + if (token_match(TK_Colon)) { + result = parse_expr(); + } return result; } @@ -418,6 +420,8 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) { Ast_If *result_if = ast_if(token, if_nodes); scope->stmts.add(result_if); } + + // Var unpack else if (token_is(TK_Identifier) && token_is(TK_Comma, 1)) { Array decls = {scratch.arena}; do { @@ -431,6 +435,8 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) { Ast_Var_Unpack *vars = ast_var_unpack(token, decls, expr); scope->stmts.add(vars); } + + // Declaration or init stmt else { Ast *result = parse_decl(false); if (result && result->kind != AST_VAR && result->kind != AST_CONST) { @@ -470,6 +476,7 @@ parse_parameter_list(Arena *arena) { Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL); param->name = name->intern_val; param->typespec = parse_expr(); + set_flag(param->typespec->flags, AST_TYPESPEC); propagate_polymorphic(param, param->typespec); propagate_polymorphic(param, name); @@ -499,6 +506,7 @@ parse_lambda(Token *token) { if (token_match(TK_Colon)) { do { Ast_Expr *typespec = parse_expr(); + set_flag(typespec->flags, AST_TYPESPEC); ret.add(typespec); } while (token_match(TK_Comma)); } @@ -595,7 +603,7 @@ parse_expr(S64 min_bp) { Token *token = token_next(); Binding_Power prefix_bp = binding_power(Binding_Prefix, token->kind); - // @note: parse prefix expression + // parse prefix expression switch (token->kind) { case TK_StringLit: left = ast_str(token, token->intern_val); break; case TK_Identifier: left = ast_ident(token, token->intern_val); break; @@ -611,14 +619,14 @@ parse_expr(S64 min_bp) { case TK_Decrement: left = ast_expr_unary(token, TK_Decrement, parse_expr(prefix_bp.right)); break; case TK_Dereference: left = ast_expr_unary(token, TK_Dereference, parse_expr(prefix_bp.right)); break; - // Pointer typespec + // Pointer -> *int, Deref -> *var case TK_Pointer: { left = ast_expr_unary(token, TK_Pointer, parse_expr(prefix_bp.right)); auto unary = (Ast_Unary *)left; propagate_polymorphic(unary, unary->expr); } break; - // Array typespec + // Array subscript -> [32]int case TK_OpenBracket: { Ast_Expr *expr = 0; if (!token_is(TK_CloseBracket)) @@ -669,7 +677,7 @@ parse_expr(S64 min_bp) { Binding_Power postfix_bp = binding_power(Binding_Postfix, token->kind); Binding_Power infix_bp = binding_power(Binding_Infix, token->kind); - // @note: parse postfix expression + // parse postfix expression if (postfix_bp.left > min_bp) { token_next(); switch (token->kind) { @@ -694,7 +702,7 @@ parse_expr(S64 min_bp) { } } - // @note: parse infix expression + // parse infix expression else if (infix_bp.left > min_bp) { token = token_next(); Ast_Expr *right = parse_expr(infix_bp.right); @@ -734,6 +742,8 @@ parse_struct(Token *pos, Ast_Kind kind) { token_expect(TK_Colon); Ast_Expr *typespec = parse_expr(); + set_flag(typespec->flags, AST_TYPESPEC); + Ast_Decl *decl = ast_var(token, typespec, token->intern_val, 0); set_flag(decl->flags, AST_AGGREGATE_CHILD); add(pctx->perm, &scope->decls, decl); @@ -953,8 +963,10 @@ parse_decl(B32 is_global) { result->kind = AST_LAMBDA; result->flags = set_flag(result->flags, AST_OPERATOR_OVERLOAD); } + else if (token_match(TK_Identifier, TK_Colon)) { Ast_Expr *typespec = parse_expr(); + set_flag(typespec->flags, AST_TYPESPEC); Ast_Expr *expr = parse_assign_expr(); if (token_match_pound(pctx->intern_foreign)) set_flag(flags, AST_FOREIGN); diff --git a/core_polymorph.cpp b/core_polymorph.cpp index d5090cd..e21f23b 100644 --- a/core_polymorph.cpp +++ b/core_polymorph.cpp @@ -4,64 +4,42 @@ Ast_Decl *get_or_instantiate_polymorph_type(Ast_Decl *poly, Arraykind) { - case AST_CALL: { - - } break; - case AST_CALL_END: { - - } break; - } -} -*/ +const unsigned AST_NODE_END = 128; struct Ast_Iter { Array stack; Ast *ast; Ast_Kind kind; + bool skip_children; uint32_t visit_id; uint32_t di; }; uint32_t Ast_Iter_VisitIDGen; Ast_Iter iterate_depth_first(Allocator *a, Ast *ast) { + assert(ast); Ast_Iter result = {}; result.stack = {a}; - result.stack.add(ast); + result.ast = ast; + result.kind = ast->kind; result.visit_id = ++Ast_Iter_VisitIDGen; - void next(Ast_Iter * iter); - next(&result); return result; } void next(Ast_Iter *iter) { - if (iter->stack.len <= 0) { - iter->ast = 0; - iter->kind = AST_NONE; - iter->stack.dealloc(); - return; - } - - Ast *ast = iter->stack.pop(); - assert(ast != 0); - iter->di += 1; - iter->ast = ast; - iter->kind = ast->kind; - if (ast->visit_id == iter->visit_id) { - iter->kind = (Ast_Kind)((unsigned)iter->kind + 128); - } + Ast *ast = iter->ast; ast->visit_id = iter->visit_id; + if (iter->skip_children) { + iter->skip_children = false; + goto end_of_switch; + } + switch (iter->kind) { case AST_SCOPE: { Ast_Scope *node = (Ast_Scope *)ast; iter->stack.add(node); For(node->stmts) iter->stack.add(it); - For(node->decls) iter->stack.add(it); } break; case AST_MODULE: invalid_codepath; break; @@ -77,12 +55,15 @@ void next(Ast_Iter *iter) { iter->stack.add(node); iter->stack.add(node->index); iter->stack.add(node->expr); + assert(node->index); + assert(node->expr); } break; case AST_UNARY: { Ast_Unary *node = (Ast_Unary *)ast; iter->stack.add(node); iter->stack.add(node->expr); + assert(node->expr); } break; case AST_BINARY: { @@ -90,14 +71,23 @@ void next(Ast_Iter *iter) { iter->stack.add(node); iter->stack.add(node->right); iter->stack.add(node->left); + assert(node->right); + assert(node->left); } break; case AST_CALL_ITEM: { Ast_Call_Item *node = (Ast_Call_Item *)ast; iter->stack.add(node); iter->stack.add(node->item); - if (node->call_flags & CALL_INDEX) iter->stack.add(node->index); - else if (node->call_flags & CALL_NAME) iter->stack.add(node->name); + assert(node->item); + if (node->call_flags & CALL_INDEX) { + iter->stack.add(node->index); + assert(node->index); + } + else if (node->call_flags & CALL_NAME) { + iter->stack.add(node->name); + assert(node->name); + } } break; case AST_COMPOUND: @@ -105,7 +95,7 @@ void next(Ast_Iter *iter) { Ast_Call *node = (Ast_Call *)ast; iter->stack.add(node); For(node->exprs) iter->stack.add(it); - iter->stack.add(node->name); + if (node->name) iter->stack.add(node->name); } break; case AST_TYPE_OF: @@ -117,20 +107,23 @@ void next(Ast_Iter *iter) { Ast_Builtin *node = (Ast_Builtin *)ast; iter->stack.add(node); iter->stack.add(node->expr); + assert(node->expr); } break; case AST_SWITCH: { Ast_Switch *node = (Ast_Switch *)ast; iter->stack.add(node); - iter->stack.add(node->default_scope); + if (node->default_scope) iter->stack.add(node->default_scope); For(node->cases) iter->stack.add(it); iter->stack.add(node->value); + assert(node->value); } break; case AST_SWITCH_CASE: { Ast_Switch_Case *node = (Ast_Switch_Case *)ast; iter->stack.add(node); iter->stack.add(node->scope); + assert(node->scope); For(node->labels) iter->stack.add(it); } break; @@ -138,6 +131,7 @@ void next(Ast_Iter *iter) { Ast_Var_Unpack *node = (Ast_Var_Unpack *)ast; iter->stack.add(node); iter->stack.add(node->expr); + assert(node->expr); For(node->vars) iter->stack.add(it); } break; @@ -168,13 +162,14 @@ void next(Ast_Iter *iter) { case AST_ARRAY: { Ast_Array *node = (Ast_Array *)ast; iter->stack.add(node); - iter->stack.add(node->expr); + if (node->expr) iter->stack.add(node->expr); } break; case AST_FOR: { Ast_For *node = (Ast_For *)ast; iter->stack.add(node); iter->stack.add(node->scope); + assert(node->scope); if (node->iter) iter->stack.add(node->iter); if (node->cond) iter->stack.add(node->cond); if (node->init) iter->stack.add(node->init); @@ -190,7 +185,8 @@ void next(Ast_Iter *iter) { Ast_If_Node *node = (Ast_If_Node *)ast; iter->stack.add(node); iter->stack.add(node->scope); - iter->stack.add(node->expr); + assert(node->scope); + if (node->expr) iter->stack.add(node->expr); if (node->init) iter->stack.add(node->init); } break; @@ -204,10 +200,27 @@ void next(Ast_Iter *iter) { Ast_Lambda *node = (Ast_Lambda *)ast; iter->stack.add(node); iter->stack.add(node->scope); + assert(node->scope); For(node->ret) iter->stack.add(it); For(node->args) iter->stack.add(it); } break; } +end_of_switch: + + if (iter->stack.len <= 0) { + iter->ast = 0; + iter->kind = AST_NONE; + iter->stack.dealloc(); + return; + } + + iter->ast = iter->stack.pop(); + assert(iter->ast != 0); + iter->di += 1; + iter->kind = iter->ast->kind; + if (iter->ast->visit_id == iter->visit_id) { + iter->kind = (Ast_Kind)((unsigned)iter->kind + AST_NODE_END); + } } // We are not copying module and file Ast's