mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 06:38:47 +00:00
Demaybe operator ?
This commit is contained in:
+2
-1
@@ -1,8 +1,9 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
maybe_print :: proc(x: ?int) {
|
maybe_print :: proc(x: ?int) {
|
||||||
if v, ok := maybe_value(x); ok {
|
if v, ok := x?; ok {
|
||||||
fmt.println(v)
|
fmt.println(v)
|
||||||
} else {
|
} else {
|
||||||
fmt.println("nowt")
|
fmt.println("nowt")
|
||||||
|
|||||||
@@ -327,6 +327,3 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+12
-7
@@ -168,8 +168,6 @@ enum BuiltinProcId {
|
|||||||
|
|
||||||
BuiltinProc_enum_to_string,
|
BuiltinProc_enum_to_string,
|
||||||
|
|
||||||
BuiltinProc_maybe_value,
|
|
||||||
|
|
||||||
BuiltinProc_Count,
|
BuiltinProc_Count,
|
||||||
};
|
};
|
||||||
struct BuiltinProc {
|
struct BuiltinProc {
|
||||||
@@ -213,9 +211,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
{STR_LIT("abs"), 1, false, Expr_Expr},
|
{STR_LIT("abs"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("maybe_value"), 1, false, Expr_Expr},
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheckerContext {
|
struct CheckerContext {
|
||||||
@@ -874,8 +869,6 @@ Map<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start)
|
|||||||
Map<Entity *> map = {}; // Key: Entity *
|
Map<Entity *> map = {}; // Key: Entity *
|
||||||
map_init(&map, gb_heap_allocator());
|
map_init(&map, gb_heap_allocator());
|
||||||
|
|
||||||
add_dependency_to_map(&map, info, start);
|
|
||||||
|
|
||||||
gb_for_array(i, info->entities.entries) {
|
gb_for_array(i, info->entities.entries) {
|
||||||
auto *entry = &info->entities.entries[i];
|
auto *entry = &info->entities.entries[i];
|
||||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||||
@@ -885,6 +878,8 @@ Map<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_dependency_to_map(&map, info, start);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,6 +1195,16 @@ void check_parsed_files(Checker *c) {
|
|||||||
add_curr_ast_file(c, d->scope->file);
|
add_curr_ast_file(c, d->scope->file);
|
||||||
|
|
||||||
if (d->scope == e->scope) {
|
if (d->scope == e->scope) {
|
||||||
|
if (kind != Entity_Procedure && e->token.string == "main") {
|
||||||
|
if (e->scope->is_init) {
|
||||||
|
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (e->scope->is_global && e->token.string == "main") {
|
||||||
|
error(e->token, "`main` is reserved as the entry point procedure in the initial scope");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Scope *prev_scope = c->context.scope;
|
Scope *prev_scope = c->context.scope;
|
||||||
c->context.scope = d->scope;
|
c->context.scope = d->scope;
|
||||||
check_entity_decl(c, e, d, NULL);
|
check_entity_decl(c, e, d, NULL);
|
||||||
|
|||||||
+37
-25
@@ -3028,31 +3028,6 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
operand->type = t_string;
|
operand->type = t_string;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_maybe_value: {
|
|
||||||
Type *type = operand->type;
|
|
||||||
if (!is_type_maybe(type)) {
|
|
||||||
gbString type_str = type_to_string(operand->type);
|
|
||||||
defer (gb_string_free(type_str));
|
|
||||||
error(ast_node_token(call),
|
|
||||||
"Expected a maybe to `maybe_value`, got `%s`",
|
|
||||||
type_str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
operand->mode = Addressing_Value;
|
|
||||||
|
|
||||||
Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
|
|
||||||
Type *elem = base_type(type)->Maybe.elem;
|
|
||||||
Token t = make_token_ident(make_string(""));
|
|
||||||
variables[0] = make_entity_param(c->allocator, NULL, t, elem, false);
|
|
||||||
variables[1] = make_entity_param(c->allocator, NULL, t, t_bool, false);
|
|
||||||
|
|
||||||
Type *tuple = make_type_tuple(c->allocator);
|
|
||||||
tuple->Tuple.variables = variables;
|
|
||||||
tuple->Tuple.variable_count = 2;
|
|
||||||
operand->type = tuple;
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -3270,6 +3245,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
o->type = t_invalid;
|
o->type = t_invalid;
|
||||||
|
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
|
default:
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
|
|
||||||
case_ast_node(be, BadExpr, node)
|
case_ast_node(be, BadExpr, node)
|
||||||
goto error;
|
goto error;
|
||||||
case_end;
|
case_end;
|
||||||
@@ -3731,6 +3710,34 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(de, DemaybeExpr, node);
|
||||||
|
check_expr_or_type(c, o, de->expr);
|
||||||
|
if (o->mode == Addressing_Invalid) {
|
||||||
|
goto error;
|
||||||
|
} else {
|
||||||
|
Type *t = base_type(o->type);
|
||||||
|
if (t->kind == Type_Maybe) {
|
||||||
|
Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
|
||||||
|
Type *elem = t->Maybe.elem;
|
||||||
|
Token tok = make_token_ident(make_string(""));
|
||||||
|
variables[0] = make_entity_param(c->allocator, NULL, tok, elem, false);
|
||||||
|
variables[1] = make_entity_param(c->allocator, NULL, tok, t_bool, false);
|
||||||
|
|
||||||
|
Type *tuple = make_type_tuple(c->allocator);
|
||||||
|
tuple->Tuple.variables = variables;
|
||||||
|
tuple->Tuple.variable_count = 2;
|
||||||
|
|
||||||
|
o->type = tuple;
|
||||||
|
o->mode = Addressing_Variable;
|
||||||
|
} else {
|
||||||
|
gbString str = expr_to_string(o->expr);
|
||||||
|
error(ast_node_token(o->expr), "Cannot demaybe `%s`", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
|
|
||||||
case AstNode_ProcType:
|
case AstNode_ProcType:
|
||||||
case AstNode_PointerType:
|
case AstNode_PointerType:
|
||||||
case AstNode_MaybeType:
|
case AstNode_MaybeType:
|
||||||
@@ -3910,6 +3917,11 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = gb_string_appendc(str, "^");
|
str = gb_string_appendc(str, "^");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(de, DemaybeExpr, node);
|
||||||
|
str = write_expr_to_string(str, de->expr);
|
||||||
|
str = gb_string_appendc(str, "?");
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(be, BinaryExpr, node);
|
case_ast_node(be, BinaryExpr, node);
|
||||||
str = write_expr_to_string(str, be->left);
|
str = write_expr_to_string(str, be->left);
|
||||||
str = gb_string_appendc(str, " ");
|
str = gb_string_appendc(str, " ");
|
||||||
|
|||||||
@@ -121,12 +121,9 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry_point != NULL) {
|
if (map_get(&min_dep_map, hash_pointer(e)) == NULL) {
|
||||||
auto found = map_get(&min_dep_map, hash_pointer(e));
|
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||||
if (found == NULL) {
|
continue;
|
||||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scope->is_global && !scope->is_init) {
|
if (!scope->is_global && !scope->is_init) {
|
||||||
|
|||||||
+23
-18
@@ -2689,24 +2689,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
args[1] = ssa_emit_conv(proc, x, t_i64);
|
args[1] = ssa_emit_conv(proc, x, t_i64);
|
||||||
return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
|
return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_maybe_value: {
|
|
||||||
ssa_emit_comment(proc, make_string("maybe_value"));
|
|
||||||
ssaValue *maybe = ssa_build_expr(proc, ce->args[0]);
|
|
||||||
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
|
||||||
GB_ASSERT(is_type_tuple(t));
|
|
||||||
|
|
||||||
Type *elem = ssa_type(maybe);
|
|
||||||
GB_ASSERT(is_type_maybe(elem));
|
|
||||||
elem = base_type(elem)->Maybe.elem;
|
|
||||||
|
|
||||||
ssaValue *result = ssa_add_local_generated(proc, t);
|
|
||||||
ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, elem));
|
|
||||||
ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32, make_type_pointer(proc->module->allocator, t_bool));
|
|
||||||
ssa_emit_store(proc, gep0, ssa_emit_struct_ev(proc, maybe, 0, elem));
|
|
||||||
ssa_emit_store(proc, gep1, ssa_emit_struct_ev(proc, maybe, 1, t_bool));
|
|
||||||
return ssa_emit_load(proc, result);
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2803,6 +2785,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
return ssa_emit_call(proc, value, args, arg_count);
|
return ssa_emit_call(proc, value, args, arg_count);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(de, DemaybeExpr, expr);
|
||||||
|
return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr);
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(se, SliceExpr, expr);
|
case_ast_node(se, SliceExpr, expr);
|
||||||
return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr);
|
return ssa_emit_load(proc, ssa_build_addr(proc, expr).addr);
|
||||||
case_end;
|
case_end;
|
||||||
@@ -3191,6 +3177,25 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
return ssa_make_addr(gep, expr);
|
return ssa_make_addr(gep, expr);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(de, DemaybeExpr, expr);
|
||||||
|
ssa_emit_comment(proc, make_string("DemaybeExpr"));
|
||||||
|
ssaValue *maybe = ssa_build_expr(proc, de->expr);
|
||||||
|
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
||||||
|
GB_ASSERT(is_type_tuple(t));
|
||||||
|
|
||||||
|
Type *elem = ssa_type(maybe);
|
||||||
|
GB_ASSERT(is_type_maybe(elem));
|
||||||
|
elem = base_type(elem)->Maybe.elem;
|
||||||
|
|
||||||
|
ssaValue *result = ssa_add_local_generated(proc, t);
|
||||||
|
ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, elem));
|
||||||
|
ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32, make_type_pointer(proc->module->allocator, t_bool));
|
||||||
|
ssa_emit_store(proc, gep0, ssa_emit_struct_ev(proc, maybe, 0, elem));
|
||||||
|
ssa_emit_store(proc, gep1, ssa_emit_struct_ev(proc, maybe, 1, t_bool));
|
||||||
|
|
||||||
|
return ssa_make_addr(result, expr);
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ce, CallExpr, expr);
|
case_ast_node(ce, CallExpr, expr);
|
||||||
ssaValue *e = ssa_build_expr(proc, expr);
|
ssaValue *e = ssa_build_expr(proc, expr);
|
||||||
ssaValue *v = ssa_add_local_generated(proc, ssa_type(e));
|
ssaValue *v = ssa_add_local_generated(proc, ssa_type(e));
|
||||||
|
|||||||
+30
-10
@@ -129,6 +129,7 @@ AST_NODE_KIND(_ExprBegin, "", struct{}) \
|
|||||||
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
|
AST_NODE_KIND(SelectorExpr, "selector expression", struct { Token token; AstNode *expr, *selector; }) \
|
||||||
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
|
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
|
||||||
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
|
||||||
|
AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \
|
||||||
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
AST_NODE_KIND(CallExpr, "call expression", struct { \
|
||||||
AstNode *proc; \
|
AstNode *proc; \
|
||||||
AstNodeArray args; \
|
AstNodeArray args; \
|
||||||
@@ -398,6 +399,8 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->FieldValue.eq;
|
return node->FieldValue.eq;
|
||||||
case AstNode_DerefExpr:
|
case AstNode_DerefExpr:
|
||||||
return node->DerefExpr.op;
|
return node->DerefExpr.op;
|
||||||
|
case AstNode_DemaybeExpr:
|
||||||
|
return node->DemaybeExpr.op;
|
||||||
case AstNode_BadStmt:
|
case AstNode_BadStmt:
|
||||||
return node->BadStmt.begin;
|
return node->BadStmt.begin;
|
||||||
case AstNode_EmptyStmt:
|
case AstNode_EmptyStmt:
|
||||||
@@ -597,6 +600,13 @@ AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNode *make_demaybe_expr(AstFile *f, AstNode *expr, Token op) {
|
||||||
|
AstNode *result = make_node(f, AstNode_DemaybeExpr);
|
||||||
|
result->DemaybeExpr.expr = expr;
|
||||||
|
result->DemaybeExpr.op = op;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
|
AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
|
||||||
AstNode *result = make_node(f, AstNode_BasicLit);
|
AstNode *result = make_node(f, AstNode_BasicLit);
|
||||||
@@ -1453,7 +1463,8 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) {
|
|||||||
next_token(f);
|
next_token(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_array_append(args, parse_expr(f, false));
|
AstNode *arg = parse_expr(f, false);
|
||||||
|
gb_array_append(args, arg);
|
||||||
|
|
||||||
if (f->curr_token.kind != Token_Comma) {
|
if (f->curr_token.kind != Token_Comma) {
|
||||||
if (f->curr_token.kind == Token_CloseParen)
|
if (f->curr_token.kind == Token_CloseParen)
|
||||||
@@ -1564,6 +1575,10 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
|
|||||||
operand = make_deref_expr(f, operand, expect_token(f, Token_Pointer));
|
operand = make_deref_expr(f, operand, expect_token(f, Token_Pointer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Token_Maybe: // Demaybe
|
||||||
|
operand = make_demaybe_expr(f, operand, expect_token(f, Token_Maybe));
|
||||||
|
break;
|
||||||
|
|
||||||
case Token_OpenBrace: {
|
case Token_OpenBrace: {
|
||||||
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
if (!lhs && is_literal_type(operand) && f->expr_level >= 0) {
|
||||||
if (f->curr_token.pos.line == f->prev_token.pos.line) {
|
if (f->curr_token.pos.line == f->prev_token.pos.line) {
|
||||||
@@ -2715,12 +2730,12 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
f->is_global_scope = true;
|
f->is_global_scope = true;
|
||||||
return make_empty_stmt(f, f->curr_token);
|
return make_empty_stmt(f, f->curr_token);
|
||||||
}
|
}
|
||||||
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope.");
|
syntax_error(token, "You cannot use #shared_global_scope within a procedure. This must be done at the file scope");
|
||||||
return make_bad_decl(f, token, f->curr_token);
|
return make_bad_decl(f, token, f->curr_token);
|
||||||
} else if (tag == "import") {
|
} else if (tag == "import") {
|
||||||
// TODO(bill): better error messages
|
// TODO(bill): better error messages
|
||||||
Token import_name = {};
|
Token import_name = {};
|
||||||
Token file_path = expect_token(f, Token_String);
|
Token file_path = expect_token_after(f, Token_String, "#import");
|
||||||
if (allow_token(f, Token_as)) {
|
if (allow_token(f, Token_as)) {
|
||||||
// NOTE(bill): Custom import name
|
// NOTE(bill): Custom import name
|
||||||
if (f->curr_token.kind == Token_Period) {
|
if (f->curr_token.kind == Token_Period) {
|
||||||
@@ -2728,14 +2743,19 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
import_name.kind = Token_Identifier;
|
import_name.kind = Token_Identifier;
|
||||||
next_token(f);
|
next_token(f);
|
||||||
} else {
|
} else {
|
||||||
import_name = expect_token(f, Token_Identifier);
|
import_name = expect_token_after(f, Token_Identifier, "`as` for import declaration");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (import_name.string == "_") {
|
||||||
|
syntax_error(token, "Illegal import name: `_`");
|
||||||
|
return make_bad_decl(f, token, f->curr_token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name, false);
|
return make_import_decl(f, s->TagStmt.token, file_path, import_name, false);
|
||||||
}
|
}
|
||||||
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope.");
|
syntax_error(token, "You cannot use #import within a procedure. This must be done at the file scope");
|
||||||
return make_bad_decl(f, token, file_path);
|
return make_bad_decl(f, token, file_path);
|
||||||
} else if (tag == "load") {
|
} else if (tag == "load") {
|
||||||
// TODO(bill): better error messages
|
// TODO(bill): better error messages
|
||||||
@@ -2746,14 +2766,14 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
|
return make_import_decl(f, s->TagStmt.token, file_path, import_name, true);
|
||||||
}
|
}
|
||||||
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope.");
|
syntax_error(token, "You cannot use #load within a procedure. This must be done at the file scope");
|
||||||
return make_bad_decl(f, token, file_path);
|
return make_bad_decl(f, token, file_path);
|
||||||
} else if (tag == "foreign_system_library") {
|
} else if (tag == "foreign_system_library") {
|
||||||
Token file_path = expect_token(f, Token_String);
|
Token file_path = expect_token(f, Token_String);
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
return make_foreign_system_library(f, s->TagStmt.token, file_path);
|
return make_foreign_system_library(f, s->TagStmt.token, file_path);
|
||||||
}
|
}
|
||||||
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope.");
|
syntax_error(token, "You cannot use #foreign_system_library within a procedure. This must be done at the file scope");
|
||||||
return make_bad_decl(f, token, file_path);
|
return make_bad_decl(f, token, file_path);
|
||||||
} else if (tag == "thread_local") {
|
} else if (tag == "thread_local") {
|
||||||
AstNode *var_decl = parse_simple_stmt(f);
|
AstNode *var_decl = parse_simple_stmt(f);
|
||||||
@@ -2762,7 +2782,7 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
return make_bad_decl(f, token, ast_node_token(var_decl));
|
return make_bad_decl(f, token, ast_node_token(var_decl));
|
||||||
}
|
}
|
||||||
if (f->curr_proc != NULL) {
|
if (f->curr_proc != NULL) {
|
||||||
syntax_error(token, "#thread_local is only allowed at the file scope.");
|
syntax_error(token, "#thread_local is only allowed at the file scope");
|
||||||
return make_bad_decl(f, token, ast_node_token(var_decl));
|
return make_bad_decl(f, token, ast_node_token(var_decl));
|
||||||
}
|
}
|
||||||
var_decl->VarDecl.tags |= VarDeclTag_thread_local;
|
var_decl->VarDecl.tags |= VarDeclTag_thread_local;
|
||||||
@@ -2783,12 +2803,12 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
s->TagStmt.stmt = parse_stmt(f); // TODO(bill): Find out why this doesn't work as an argument
|
||||||
return s;
|
return s;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Token_OpenBrace: return parse_block_stmt(f);
|
case Token_OpenBrace:
|
||||||
|
return parse_block_stmt(f);
|
||||||
|
|
||||||
case Token_Semicolon:
|
case Token_Semicolon:
|
||||||
s = make_empty_stmt(f, token);
|
s = make_empty_stmt(f, token);
|
||||||
|
|||||||
Reference in New Issue
Block a user