diff --git a/base.cpp b/base.cpp index c7a8f3e..742a567 100644 --- a/base.cpp +++ b/base.cpp @@ -289,14 +289,13 @@ hash_string(String string) { return hash; } -CORE_Static U64 +force_inline U64 hash_u64(U64 x) { - x *= 0xff51afd7ed558ccd; - x ^= x >> 32; - return x; + U64 result = hash_string({(U8 *)&x, sizeof(x)}); + return result; } -CORE_Static U64 +force_inline U64 hash_ptr(const void *ptr) { return hash_u64((uintptr_t)ptr); } @@ -314,14 +313,14 @@ hash_mix(U64 x, U64 y) { return x; } -CORE_Static U64 +force_inline U64 is_pow2(U64 x) { assert(x != 0); B32 result = (x & (x - 1llu)) == 0; return result; } -CORE_Static U64 +force_inline U64 wrap_around_pow2(U64 x, U64 power_of_2) { assert(is_pow2(power_of_2)); U64 r = (((x) & ((power_of_2)-1llu))); diff --git a/build/rtsgame/main.core b/build/rtsgame/main.core index d48b50b..4f96994 100644 --- a/build/rtsgame/main.core +++ b/build/rtsgame/main.core @@ -76,6 +76,9 @@ main :: (): int target_color := RED target_color.a = 255/2 + :some_label: + target_color = RED + for !WindowShouldClose() WinX = GetScreenWidth() WinY = GetScreenHeight() diff --git a/core_ast.cpp b/core_ast.cpp index b6b1c18..020472e 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -177,6 +177,15 @@ ast_return(Token *pos, Ast_Expr *expr) { return result; } +CORE_Static Ast_Label * +ast_label(Token *pos, Intern_String name, Ast_Scope *scope, bool enable_goto) { + Ast_Label *result = ast_new(Ast_Label, AST_LABEL, pos, AST_STMT | AST_DECL); + result->enable_goto = enable_goto; + result->name = name; + result->scope = scope; + return result; +} + CORE_Static Ast_If_Node * ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope) { AST_NEW(If_Node, IF_NODE, pos, AST_STMT); diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index d9b6729..ce23236 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -621,95 +621,95 @@ gen_ast(Ast *ast) { BREAK(); } - CASE(CONTINUE, Pass) { - unused(node); + case AST_LABEL: { + auto n = (Ast_Label *)ast; + if (n->enable_goto == false) gen("/* %Q */", n->name); + if (n->enable_goto == true) gen("%Q:", n->name); + gen_stmt_scope(n->scope); + } break; + + case AST_CONTINUE: { gen("continue;"); - BREAK(); - } - CASE(BREAK, Break) { - unused(node); + } break; + + case AST_BREAK: { gen("break;"); - BREAK(); - } + } break; - CASE(COMPILER_BREAKPOINT_STMT, Break) { - unused(node); + case AST_COMPILER_BREAKPOINT_STMT: { __debugbreak(); - BREAK(); - } + } break; - CASE(PASS, Pass) { - unused(node); - gen("//pass"); - BREAK(); - } + case AST_PASS: { + gen("// pass"); + } break; - CASE(BINARY, Binary) { - gen_expr(node); - gen(";"); - BREAK(); - } + CASE(BINARY, Binary) { + gen_expr(node); + gen(";"); + BREAK(); + } - CASE(FOR, For) { - // Array iter - if (node->is_array_traversal) { - gen("for(int64_t _i%d = 0; _i%d < ", node->pos->line, node->pos->line); - if (is_array(node->cond->resolved_type)) { - gen("BufferSize("); - gen_expr(node->cond); - gen(")"); - } - else { - assert(is_slice(node->cond->resolved_type)); - gen_expr(node->cond); - gen(".len"); - } + CASE(FOR, For) { + // Array iter + if (node->is_array_traversal) { + gen("for(int64_t _i%d = 0; _i%d < ", node->pos->line, node->pos->line); + if (is_array(node->cond->resolved_type)) { + gen("BufferSize("); + gen_expr(node->cond); + gen(")"); + } + else { + assert(is_slice(node->cond->resolved_type)); + gen_expr(node->cond); + gen(".len"); + } - gen("; _i%d+=1)", node->pos->line); - gen("{"); - global_indent++; - genln(""); - gen_simple_decl(node->array_traversal_var->type, node->array_traversal_var->name); - gen(" = "); - gen_expr(node->cond); - if (node->is_also_slice_traversal) gen(".data"); - gen(" + _i%d;", node->pos->line); - For(node->scope->stmts) { - gen_line(it); + gen("; _i%d+=1)", node->pos->line); + gen("{"); + global_indent++; genln(""); - gen_ast(it); + gen_simple_decl(node->array_traversal_var->type, node->array_traversal_var->name); + gen(" = "); + gen_expr(node->cond); + if (node->is_also_slice_traversal) gen(".data"); + gen(" + _i%d;", node->pos->line); + For(node->scope->stmts) { + gen_line(it); + genln(""); + gen_ast(it); + } + global_indent--; + gen_last_line(); + genln("}"); } - global_indent--; - gen_last_line(); - genln("}"); + + // Normal for loop + else { + gen("for("); + if (node->init) gen_expr(node->init); + gen(";"); + if (node->cond) gen_expr(node->cond); + gen(";"); + if (node->iter) gen_expr(node->iter); + gen(")"); + gen_stmt_scope(node->scope); + } + + BREAK(); } - // Normal for loop - else { - gen("for("); - if (node->init) gen_expr(node->init); - gen(";"); - if (node->cond) gen_expr(node->cond); - gen(";"); - if (node->iter) gen_expr(node->iter); - gen(")"); - gen_stmt_scope(node->scope); + CASE(LAMBDA, Decl) { + gen_line(node); + genln(""); + + if (is_flag_set(node->expr->flags, AST_FOREIGN)) { + gen("/*foreign*/"); + } + gen_lambda(node->unique_name, node->lambda); + BREAK(); } - BREAK(); - } - - CASE(LAMBDA, Decl) { - gen_line(node); - genln(""); - - if (is_flag_set(node->expr->flags, AST_FOREIGN)) { - gen("/*foreign*/"); - } - gen_lambda(node->unique_name, node->lambda); - BREAK(); - } - case AST_UNION: CASE(STRUCT, Decl) { gen("%s ", node->kind == AST_STRUCT ? "struct" : "union"); diff --git a/core_compiler.cpp b/core_compiler.cpp index 082ddfc..a336102 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -66,9 +66,8 @@ for i in meta.token_simple_expr: pctx->keyword_else = pctx->intern("else"_s); pctx->keyword_for = pctx->intern("for"_s); pctx->keyword_enum = pctx->intern("enum"_s); - pctx->keyword___compilerbreakpoint = pctx->intern("__CompilerBreakpoint"_s); pctx->interns.first_keyword = pctx->keyword_struct.str; - pctx->interns.last_keyword = pctx->keyword___compilerbreakpoint.str; + pctx->interns.last_keyword = pctx->keyword_enum.str; pctx->intern_typeof = pctx->intern("typeof"_s); pctx->intern_sizeof = pctx->intern("sizeof"_s); pctx->intern_len = pctx->intern("Len"_s); diff --git a/core_compiler.h b/core_compiler.h index 44bf617..8cc6d67 100644 --- a/core_compiler.h +++ b/core_compiler.h @@ -107,7 +107,6 @@ for i in meta.interns: print(f'Intern_String intern_{i.lower()};') Intern_String keyword_else; Intern_String keyword_for; Intern_String keyword_enum; - Intern_String keyword___compilerbreakpoint; Intern_String intern_typeof; Intern_String intern_sizeof; Intern_String intern_len; diff --git a/core_compiler_interface.hpp b/core_compiler_interface.hpp index a6d9aaf..bc7d8ec 100644 --- a/core_compiler_interface.hpp +++ b/core_compiler_interface.hpp @@ -334,6 +334,7 @@ enum Ast_Kind : uint32_t { AST_TYPE_OF, AST_VARGS_LAMBDA_PARAM, + AST_LABEL, AST_SWITCH, AST_SWITCH_CASE, AST_VAR_UNPACK, @@ -404,17 +405,6 @@ struct Ast_Expr : Ast { }; }; -/* Typespecs -*int - (AST_UNARY=TK_Pointer Ast_Unary) == TYPE_POINTER -int - (AST_IDENT Ast_Atom) == TYPE_INT .. -[] - (Ast_Array AST_ARRAY) == TYPE_SLICE -[3] - (Ast_Array AST_ARRAY) == TYPE_ARRAY -Array(int) - (Ast_Call AST_CALL) == TYPE_STRUCT, TYPE_UNION - - - -*/ - struct Ast_Atom : Ast_Expr { // We have a field type here // it has a different purpose from the @@ -501,10 +491,25 @@ struct Ast_Builtin : Ast_Expr { // Problem: We are parsing out of order, in the middle of parsing a function // we can jump down a different function, we cant therfore use global map. +// Because it would have symbols from previous function we were in middle of resolving. +// // On top of that in the future we want a way to inject scopes, for convenience. // Each scope needs to have it's checked locals list. To lookup syms we need to // look into global scope and to the locals list. // +// +// This seems slow though, would be nice to have a simpler scheme that's more flat. +// Would be nice to just reuse single map while resolving that would keep track of which +// function we are resolving. +// +// Also would be nice to have a more flat module scheme. The Ion approach seemed +// very straight forward when I looked at it. It used a single locals list with +// an index that signified from where we should consider declarations. Not really +// sure how the packages worked though. +// +// The idea that you have a flat list of packages, each package has a flat list of declarations. +// Seems nice. +// struct Ast_Return : Ast { Ast_Type *resolved_type; @@ -521,6 +526,7 @@ struct Ast_If : Ast { Array ifs; }; +// @todo: Ast_Simple_Stmt #define Ast_Pass Ast #define Ast_Break Ast @@ -615,6 +621,7 @@ struct Ast_Decl : Ast { Intern_String name; Intern_String unique_name; // For code generation, currently only present on lambdas + // @todo: Move this to Ast_Operator_Overload uint64_t operator_overload_arguments_hash; Ast_Operator_Info *overload_op_info; @@ -651,6 +658,10 @@ meta.inline_value_fields() /*END*/ }; +struct Ast_Label : Ast_Decl { + bool enable_goto; +}; + enum Core_Message_Kind { CORE_ERROR, CORE_WARNING, diff --git a/core_parsing.cpp b/core_parsing.cpp index c0c6e83..8d4a128 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -293,7 +293,7 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) { scope->stmts.add(ast_continue(token)); } - else if (token_match_keyword(pctx->keyword___compilerbreakpoint)) { + else if (token_match_keyword(pctx->intern_compiler_breakpoint)) { scope->stmts.add(ast_compiler_breakpoint(token)); } @@ -423,6 +423,21 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) { scope->stmts.add(result_if); } + // Label + else if (token_match(TK_Colon)) { + Token *ident = token_expect(TK_Identifier); + Token *enable_goto_token = token_match(TK_Colon); + bool enable_goto = enable_goto_token ? 1 : 0; + Token *breakpoint = token_match_pound(pctx->intern_compiler_breakpoint); + + Ast_Scope *s = 0; + if (token_is(OPEN_SCOPE)) s = parse_stmt_scope(); + + Ast_Label *result = ast_label(token, ident->intern_val, s, enable_goto); + if (breakpoint) set_flag(result->flags, AST_COMPILER_BREAKPOINT); + scope->stmts.add(result); + } + // Var unpack else if (token_is(TK_Identifier) && token_is(TK_Comma, 1)) { Array decls = {scratch.arena}; diff --git a/core_typechecking.cpp b/core_typechecking.cpp index b6c678d..9519242 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -758,6 +758,14 @@ CORE_Static void resolve_stmt(Ast *ast, Ast_Type *ret) { __debugbreak(); } break; + case AST_LABEL: { + auto n = (Ast_Label *)ast; + insert_into_scope(n->parent_scope, n); + For(n->scope->stmts) { + resolve_stmt(it, ret); + } + } break; + case AST_CONTINUE: case AST_BREAK: CASE(PASS, Pass) { diff --git a/meta.py b/meta.py index b9de3f0..9ee318f 100644 --- a/meta.py +++ b/meta.py @@ -115,7 +115,6 @@ keywords = [ "else", "for", "enum", - "__CompilerBreakpoint", # @language_todo: maybe make a #compiler_breakpoint instead that you can attach to anything ] interns = [