Core: Add Ast_Label

This commit is contained in:
Krzosa Karol
2023-04-22 12:38:48 +02:00
parent d244608571
commit eff6b10cf4
10 changed files with 140 additions and 98 deletions

View File

@@ -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)));

View File

@@ -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()

View File

@@ -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);

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<Ast_If_Node *> 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,

View File

@@ -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<Ast_Decl *> decls = {scratch.arena};

View File

@@ -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) {

View File

@@ -115,7 +115,6 @@ keywords = [
"else",
"for",
"enum",
"__CompilerBreakpoint", # @language_todo: maybe make a #compiler_breakpoint instead that you can attach to anything
]
interns = [