Core: Add Ast_Label
This commit is contained in:
13
base.cpp
13
base.cpp
@@ -289,14 +289,13 @@ hash_string(String string) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static U64
|
force_inline U64
|
||||||
hash_u64(U64 x) {
|
hash_u64(U64 x) {
|
||||||
x *= 0xff51afd7ed558ccd;
|
U64 result = hash_string({(U8 *)&x, sizeof(x)});
|
||||||
x ^= x >> 32;
|
return result;
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static U64
|
force_inline U64
|
||||||
hash_ptr(const void *ptr) {
|
hash_ptr(const void *ptr) {
|
||||||
return hash_u64((uintptr_t)ptr);
|
return hash_u64((uintptr_t)ptr);
|
||||||
}
|
}
|
||||||
@@ -314,14 +313,14 @@ hash_mix(U64 x, U64 y) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static U64
|
force_inline U64
|
||||||
is_pow2(U64 x) {
|
is_pow2(U64 x) {
|
||||||
assert(x != 0);
|
assert(x != 0);
|
||||||
B32 result = (x & (x - 1llu)) == 0;
|
B32 result = (x & (x - 1llu)) == 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CORE_Static U64
|
force_inline U64
|
||||||
wrap_around_pow2(U64 x, U64 power_of_2) {
|
wrap_around_pow2(U64 x, U64 power_of_2) {
|
||||||
assert(is_pow2(power_of_2));
|
assert(is_pow2(power_of_2));
|
||||||
U64 r = (((x) & ((power_of_2)-1llu)));
|
U64 r = (((x) & ((power_of_2)-1llu)));
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ main :: (): int
|
|||||||
target_color := RED
|
target_color := RED
|
||||||
target_color.a = 255/2
|
target_color.a = 255/2
|
||||||
|
|
||||||
|
:some_label:
|
||||||
|
target_color = RED
|
||||||
|
|
||||||
for !WindowShouldClose()
|
for !WindowShouldClose()
|
||||||
WinX = GetScreenWidth()
|
WinX = GetScreenWidth()
|
||||||
WinY = GetScreenHeight()
|
WinY = GetScreenHeight()
|
||||||
|
|||||||
@@ -177,6 +177,15 @@ ast_return(Token *pos, Ast_Expr *expr) {
|
|||||||
return result;
|
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 *
|
CORE_Static Ast_If_Node *
|
||||||
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope) {
|
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope) {
|
||||||
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
||||||
|
|||||||
@@ -621,28 +621,28 @@ gen_ast(Ast *ast) {
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(CONTINUE, Pass) {
|
case AST_LABEL: {
|
||||||
unused(node);
|
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;");
|
gen("continue;");
|
||||||
BREAK();
|
} break;
|
||||||
}
|
|
||||||
CASE(BREAK, Break) {
|
case AST_BREAK: {
|
||||||
unused(node);
|
|
||||||
gen("break;");
|
gen("break;");
|
||||||
BREAK();
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
CASE(COMPILER_BREAKPOINT_STMT, Break) {
|
case AST_COMPILER_BREAKPOINT_STMT: {
|
||||||
unused(node);
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
BREAK();
|
} break;
|
||||||
}
|
|
||||||
|
|
||||||
CASE(PASS, Pass) {
|
case AST_PASS: {
|
||||||
unused(node);
|
gen("// pass");
|
||||||
gen("//pass");
|
} break;
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(BINARY, Binary) {
|
CASE(BINARY, Binary) {
|
||||||
gen_expr(node);
|
gen_expr(node);
|
||||||
|
|||||||
@@ -66,9 +66,8 @@ for i in meta.token_simple_expr:
|
|||||||
pctx->keyword_else = pctx->intern("else"_s);
|
pctx->keyword_else = pctx->intern("else"_s);
|
||||||
pctx->keyword_for = pctx->intern("for"_s);
|
pctx->keyword_for = pctx->intern("for"_s);
|
||||||
pctx->keyword_enum = pctx->intern("enum"_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.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_typeof = pctx->intern("typeof"_s);
|
||||||
pctx->intern_sizeof = pctx->intern("sizeof"_s);
|
pctx->intern_sizeof = pctx->intern("sizeof"_s);
|
||||||
pctx->intern_len = pctx->intern("Len"_s);
|
pctx->intern_len = pctx->intern("Len"_s);
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ for i in meta.interns: print(f'Intern_String intern_{i.lower()};')
|
|||||||
Intern_String keyword_else;
|
Intern_String keyword_else;
|
||||||
Intern_String keyword_for;
|
Intern_String keyword_for;
|
||||||
Intern_String keyword_enum;
|
Intern_String keyword_enum;
|
||||||
Intern_String keyword___compilerbreakpoint;
|
|
||||||
Intern_String intern_typeof;
|
Intern_String intern_typeof;
|
||||||
Intern_String intern_sizeof;
|
Intern_String intern_sizeof;
|
||||||
Intern_String intern_len;
|
Intern_String intern_len;
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ enum Ast_Kind : uint32_t {
|
|||||||
AST_TYPE_OF,
|
AST_TYPE_OF,
|
||||||
AST_VARGS_LAMBDA_PARAM,
|
AST_VARGS_LAMBDA_PARAM,
|
||||||
|
|
||||||
|
AST_LABEL,
|
||||||
AST_SWITCH,
|
AST_SWITCH,
|
||||||
AST_SWITCH_CASE,
|
AST_SWITCH_CASE,
|
||||||
AST_VAR_UNPACK,
|
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 {
|
struct Ast_Atom : Ast_Expr {
|
||||||
// We have a field type here
|
// We have a field type here
|
||||||
// it has a different purpose from the
|
// 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
|
// 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.
|
// 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.
|
// 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
|
// 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.
|
// 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 {
|
struct Ast_Return : Ast {
|
||||||
Ast_Type *resolved_type;
|
Ast_Type *resolved_type;
|
||||||
@@ -521,6 +526,7 @@ struct Ast_If : Ast {
|
|||||||
Array<Ast_If_Node *> ifs;
|
Array<Ast_If_Node *> ifs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// @todo: Ast_Simple_Stmt
|
||||||
#define Ast_Pass Ast
|
#define Ast_Pass Ast
|
||||||
#define Ast_Break Ast
|
#define Ast_Break Ast
|
||||||
|
|
||||||
@@ -615,6 +621,7 @@ struct Ast_Decl : Ast {
|
|||||||
Intern_String name;
|
Intern_String name;
|
||||||
Intern_String unique_name; // For code generation, currently only present on lambdas
|
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;
|
uint64_t operator_overload_arguments_hash;
|
||||||
Ast_Operator_Info *overload_op_info;
|
Ast_Operator_Info *overload_op_info;
|
||||||
|
|
||||||
@@ -651,6 +658,10 @@ meta.inline_value_fields()
|
|||||||
/*END*/
|
/*END*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ast_Label : Ast_Decl {
|
||||||
|
bool enable_goto;
|
||||||
|
};
|
||||||
|
|
||||||
enum Core_Message_Kind {
|
enum Core_Message_Kind {
|
||||||
CORE_ERROR,
|
CORE_ERROR,
|
||||||
CORE_WARNING,
|
CORE_WARNING,
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) {
|
|||||||
scope->stmts.add(ast_continue(token));
|
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));
|
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);
|
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
|
// Var unpack
|
||||||
else if (token_is(TK_Identifier) && token_is(TK_Comma, 1)) {
|
else if (token_is(TK_Identifier) && token_is(TK_Comma, 1)) {
|
||||||
Array<Ast_Decl *> decls = {scratch.arena};
|
Array<Ast_Decl *> decls = {scratch.arena};
|
||||||
|
|||||||
@@ -758,6 +758,14 @@ CORE_Static void resolve_stmt(Ast *ast, Ast_Type *ret) {
|
|||||||
__debugbreak();
|
__debugbreak();
|
||||||
} break;
|
} 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_CONTINUE:
|
||||||
case AST_BREAK:
|
case AST_BREAK:
|
||||||
CASE(PASS, Pass) {
|
CASE(PASS, Pass) {
|
||||||
|
|||||||
Reference in New Issue
Block a user