Core: Add goto
This commit is contained in:
@@ -76,9 +76,6 @@ main :: (): int
|
||||
target_color := RED
|
||||
target_color.a = 255/2
|
||||
|
||||
:some_label:
|
||||
target_color = RED
|
||||
|
||||
for !WindowShouldClose()
|
||||
WinX = GetScreenWidth()
|
||||
WinY = GetScreenHeight()
|
||||
|
||||
10
core_ast.cpp
10
core_ast.cpp
@@ -177,6 +177,13 @@ ast_return(Token *pos, Ast_Expr *expr) {
|
||||
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 *
|
||||
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);
|
||||
@@ -572,10 +579,11 @@ void next(Ast_Iter *iter) {
|
||||
case AST_BREAK:
|
||||
case AST_PASS:
|
||||
case AST_CONTINUE:
|
||||
case AST_GOTO:
|
||||
case AST_COMPILER_BREAKPOINT_STMT: {
|
||||
Ast *node = (Ast *)ast;
|
||||
} break;
|
||||
|
||||
case AST_LABEL:
|
||||
case AST_NAMESPACE:
|
||||
case AST_STRUCT:
|
||||
case AST_UNION:
|
||||
|
||||
@@ -621,6 +621,11 @@ gen_ast(Ast *ast) {
|
||||
BREAK();
|
||||
}
|
||||
|
||||
case AST_GOTO: {
|
||||
auto n = (Ast_Goto *)ast;
|
||||
gen("goto %Q;", n->label);
|
||||
} break;
|
||||
|
||||
case AST_LABEL: {
|
||||
auto n = (Ast_Label *)ast;
|
||||
if (n->enable_goto == false) gen("/* %Q */", n->name);
|
||||
|
||||
@@ -66,8 +66,9 @@ 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_goto = pctx->intern("goto"_s);
|
||||
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_sizeof = pctx->intern("sizeof"_s);
|
||||
pctx->intern_len = pctx->intern("Len"_s);
|
||||
|
||||
@@ -107,6 +107,7 @@ 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_goto;
|
||||
Intern_String intern_typeof;
|
||||
Intern_String intern_sizeof;
|
||||
Intern_String intern_len;
|
||||
|
||||
@@ -335,6 +335,7 @@ enum Ast_Kind : uint32_t {
|
||||
AST_VARGS_LAMBDA_PARAM,
|
||||
|
||||
AST_LABEL,
|
||||
AST_GOTO,
|
||||
AST_SWITCH,
|
||||
AST_SWITCH_CASE,
|
||||
AST_VAR_UNPACK,
|
||||
@@ -530,6 +531,10 @@ struct Ast_If : Ast {
|
||||
#define Ast_Pass Ast
|
||||
#define Ast_Break Ast
|
||||
|
||||
struct Ast_Goto : Ast {
|
||||
Intern_String label;
|
||||
};
|
||||
|
||||
struct Ast_For : Ast {
|
||||
Ast_Expr *init;
|
||||
Ast_Expr *cond;
|
||||
|
||||
@@ -423,6 +423,12 @@ parse_stmt_scope(Ast_Scope *scope_defined_outside = 0) {
|
||||
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
|
||||
else if (token_match(TK_Colon)) {
|
||||
Token *ident = token_expect(TK_Identifier);
|
||||
|
||||
@@ -324,6 +324,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
|
||||
|
||||
case AST_BREAK:
|
||||
case AST_PASS:
|
||||
case AST_GOTO:
|
||||
case AST_CONTINUE:
|
||||
case AST_COMPILER_BREAKPOINT_STMT: {
|
||||
Ast *src = (Ast *)ast;
|
||||
@@ -331,6 +332,7 @@ Ast *ast_copy(Ast *ast, Ast_Scope *parent_scope, Array<Poly_Replacement> *repl)
|
||||
result = dst;
|
||||
} break;
|
||||
|
||||
case AST_LABEL:
|
||||
case AST_NAMESPACE:
|
||||
case AST_STRUCT:
|
||||
case AST_UNION:
|
||||
|
||||
@@ -766,12 +766,19 @@ CORE_Static void resolve_stmt(Ast *ast, Ast_Type *ret) {
|
||||
}
|
||||
} 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_BREAK:
|
||||
CASE(PASS, Pass) {
|
||||
unused(node);
|
||||
BREAK();
|
||||
}
|
||||
case AST_PASS: {
|
||||
|
||||
} break;
|
||||
|
||||
CASE(RUNTIME_ASSERT, Builtin) {
|
||||
resolve_and_require_bool("Assert condition is not boolean", node->expr, AST_CAN_BE_NULL);
|
||||
|
||||
Reference in New Issue
Block a user