Core: Add goto

This commit is contained in:
Krzosa Karol
2023-04-22 13:14:08 +02:00
parent eff6b10cf4
commit 654d6f17e4
10 changed files with 42 additions and 9 deletions

View File

@@ -76,9 +76,6 @@ 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()

View File

@@ -177,6 +177,13 @@ ast_return(Token *pos, Ast_Expr *expr) {
return result; return result;
} }
CORE_Static Ast_Goto *
ast_goto(Token *pos, Intern_String label) {
Ast_Goto *result = ast_new(Ast_Goto, AST_GOTO, pos, AST_STMT);
result->label = label;
return result;
}
CORE_Static Ast_Label * CORE_Static Ast_Label *
ast_label(Token *pos, Intern_String name, Ast_Scope *scope, bool enable_goto) { 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); Ast_Label *result = ast_new(Ast_Label, AST_LABEL, pos, AST_STMT | AST_DECL);
@@ -572,10 +579,11 @@ void next(Ast_Iter *iter) {
case AST_BREAK: case AST_BREAK:
case AST_PASS: case AST_PASS:
case AST_CONTINUE: case AST_CONTINUE:
case AST_GOTO:
case AST_COMPILER_BREAKPOINT_STMT: { case AST_COMPILER_BREAKPOINT_STMT: {
Ast *node = (Ast *)ast;
} break; } break;
case AST_LABEL:
case AST_NAMESPACE: case AST_NAMESPACE:
case AST_STRUCT: case AST_STRUCT:
case AST_UNION: case AST_UNION:

View File

@@ -621,6 +621,11 @@ gen_ast(Ast *ast) {
BREAK(); BREAK();
} }
case AST_GOTO: {
auto n = (Ast_Goto *)ast;
gen("goto %Q;", n->label);
} break;
case AST_LABEL: { case AST_LABEL: {
auto n = (Ast_Label *)ast; auto n = (Ast_Label *)ast;
if (n->enable_goto == false) gen("/* %Q */", n->name); if (n->enable_goto == false) gen("/* %Q */", n->name);

View File

@@ -66,8 +66,9 @@ 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_goto = pctx->intern("goto"_s);
pctx->interns.first_keyword = pctx->keyword_struct.str; pctx->interns.first_keyword = pctx->keyword_struct.str;
pctx->interns.last_keyword = pctx->keyword_enum.str; pctx->interns.last_keyword = pctx->keyword_goto.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);

View File

@@ -107,6 +107,7 @@ 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_goto;
Intern_String intern_typeof; Intern_String intern_typeof;
Intern_String intern_sizeof; Intern_String intern_sizeof;
Intern_String intern_len; Intern_String intern_len;

View File

@@ -335,6 +335,7 @@ enum Ast_Kind : uint32_t {
AST_VARGS_LAMBDA_PARAM, AST_VARGS_LAMBDA_PARAM,
AST_LABEL, AST_LABEL,
AST_GOTO,
AST_SWITCH, AST_SWITCH,
AST_SWITCH_CASE, AST_SWITCH_CASE,
AST_VAR_UNPACK, AST_VAR_UNPACK,
@@ -530,6 +531,10 @@ struct Ast_If : Ast {
#define Ast_Pass Ast #define Ast_Pass Ast
#define Ast_Break Ast #define Ast_Break Ast
struct Ast_Goto : Ast {
Intern_String label;
};
struct Ast_For : Ast { struct Ast_For : Ast {
Ast_Expr *init; Ast_Expr *init;
Ast_Expr *cond; Ast_Expr *cond;

View File

@@ -423,6 +423,12 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) {
scope->stmts.add(result_if); scope->stmts.add(result_if);
} }
else if (token_match_keyword(pctx->keyword_goto)) {
Token *ident = token_expect(TK_Identifier);
Ast_Goto *result = ast_goto(token, ident->intern_val);
scope->stmts.add(result);
}
// Label // Label
else if (token_match(TK_Colon)) { else if (token_match(TK_Colon)) {
Token *ident = token_expect(TK_Identifier); Token *ident = token_expect(TK_Identifier);

View File

@@ -324,6 +324,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
case AST_BREAK: case AST_BREAK:
case AST_PASS: case AST_PASS:
case AST_GOTO:
case AST_CONTINUE: case AST_CONTINUE:
case AST_COMPILER_BREAKPOINT_STMT: { case AST_COMPILER_BREAKPOINT_STMT: {
Ast *src = (Ast *)ast; Ast *src = (Ast *)ast;
@@ -331,6 +332,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
result = dst; result = dst;
} break; } break;
case AST_LABEL:
case AST_NAMESPACE: case AST_NAMESPACE:
case AST_STRUCT: case AST_STRUCT:
case AST_UNION: case AST_UNION:

View File

@@ -766,12 +766,19 @@ CORE_Static void resolve_stmt(Ast *ast, Ast_Type *ret) {
} }
} break; } break;
case AST_GOTO: {
auto n = (Ast_Goto *)ast;
auto decl = (Ast_Label *)search_for_single_decl(n->parent_scope, n->label);
if (!decl) compiler_error(n->pos, "Goto label is unidentified");
if (decl->kind != AST_LABEL) compiler_error(n->pos, "Trying to goto identifier that is not a label");
if (decl->enable_goto == false) compiler_error(decl->pos, "Label doesn't have goto enabled, add ':' at the end");
} break;
case AST_CONTINUE: case AST_CONTINUE:
case AST_BREAK: case AST_BREAK:
CASE(PASS, Pass) { case AST_PASS: {
unused(node);
BREAK(); } break;
}
CASE(RUNTIME_ASSERT, Builtin) { CASE(RUNTIME_ASSERT, Builtin) {
resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL); resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);

View File

@@ -115,6 +115,7 @@ keywords = [
"else", "else",
"for", "for",
"enum", "enum",
"goto",
] ]
interns = [ interns = [