Core: Add goto
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
10
core_ast.cpp
10
core_ast.cpp
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user