mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-06 10:44:06 +00:00
Replace context <- c {} with context = c;. context assignments are scope based
This commit is contained in:
@@ -211,12 +211,11 @@ context_from_allocator :: proc(a: Allocator) -> runtime.Context {
|
||||
|
||||
destroy_arena :: proc(using a: ^Arena) {
|
||||
if backing.procedure != nil {
|
||||
context <- context_from_allocator(backing) {
|
||||
if memory != nil {
|
||||
free(&memory[0]);
|
||||
}
|
||||
memory = nil;
|
||||
context = context_from_allocator(backing);
|
||||
if memory != nil {
|
||||
free(&memory[0]);
|
||||
}
|
||||
memory = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,13 +29,9 @@ create :: proc(procedure: Thread_Proc) -> ^Thread {
|
||||
if t.use_init_context {
|
||||
c = t.init_context;
|
||||
}
|
||||
context = c;
|
||||
|
||||
exit := 0;
|
||||
context <- c {
|
||||
exit = t.procedure(t);
|
||||
}
|
||||
|
||||
return i32(exit);
|
||||
return i32(t.procedure(t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -364,26 +364,24 @@ parametric_polymorphism :: proc() {
|
||||
allocate :: proc(table: ^$T/Table, capacity: int) {
|
||||
c := context;
|
||||
if table.allocator.procedure != nil do c.allocator = table.allocator;
|
||||
context = c;
|
||||
|
||||
context <- c {
|
||||
table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
|
||||
}
|
||||
table.slots = make_slice(type_of(table.slots), max(capacity, TABLE_SIZE_MIN));
|
||||
}
|
||||
|
||||
expand :: proc(table: ^$T/Table) {
|
||||
c := context;
|
||||
if table.allocator.procedure != nil do c.allocator = table.allocator;
|
||||
context = c;
|
||||
|
||||
context <- c {
|
||||
old_slots := table.slots;
|
||||
defer delete(old_slots);
|
||||
old_slots := table.slots;
|
||||
defer delete(old_slots);
|
||||
|
||||
cap := max(2*len(table.slots), TABLE_SIZE_MIN);
|
||||
allocate(table, cap);
|
||||
cap := max(2*len(table.slots), TABLE_SIZE_MIN);
|
||||
allocate(table, cap);
|
||||
|
||||
for s in old_slots do if s.occupied {
|
||||
put(table, s.key, s.value);
|
||||
}
|
||||
for s in old_slots do if s.occupied {
|
||||
put(table, s.key, s.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,15 @@ template <typename T> void array_resize (Array<T> *array, isize count)
|
||||
template <typename T> void array_set_capacity (Array<T> *array, isize capacity);
|
||||
template <typename T> Array<T> array_slice (Array<T> const &array, isize lo, isize hi);
|
||||
|
||||
template <typename T>
|
||||
T *array_end_ptr(Array<T> *array) {
|
||||
if (array->count > 0) {
|
||||
return &array->data[array->count-1];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
gb_inline void array_init(Array<T> *array, gbAllocator const &a) {
|
||||
isize cap = ARRAY_GROW_FORMULA(0);
|
||||
|
||||
@@ -578,7 +578,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
|
||||
|
||||
if (is_type_any(dst)) {
|
||||
if (!is_type_polymorphic(src)) {
|
||||
if (operand->mode == Addressing_Immutable && operand->type == t_context) {
|
||||
if (operand->mode == Addressing_Context && operand->type == t_context) {
|
||||
return -1;
|
||||
} else {
|
||||
// NOTE(bill): Anything can cast to 'Any'
|
||||
@@ -2040,6 +2040,17 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x->mode == Addressing_Builtin) {
|
||||
x->mode = Addressing_Invalid;
|
||||
error(x->expr, "built-in expression in binary expression");
|
||||
return;
|
||||
}
|
||||
if (y->mode == Addressing_Builtin) {
|
||||
x->mode = Addressing_Invalid;
|
||||
error(y->expr, "built-in expression in binary expression");
|
||||
return;
|
||||
}
|
||||
|
||||
if (token_is_shift(op.kind)) {
|
||||
check_shift(c, x, y, node);
|
||||
return;
|
||||
@@ -2724,6 +2735,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
|
||||
// TODO(bill): Is this the rule I need?
|
||||
if (operand->mode == Addressing_Immutable) {
|
||||
// Okay
|
||||
} else if (operand->mode == Addressing_Context) {
|
||||
operand->mode = Addressing_Value; // TODO(bill): Should this be Value or Immutable?
|
||||
} else if (sel.indirect || operand->mode != Addressing_Value) {
|
||||
operand->mode = Addressing_Variable;
|
||||
} else {
|
||||
@@ -5211,7 +5224,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
}
|
||||
|
||||
init_core_context(c->checker);
|
||||
o->mode = Addressing_Immutable;
|
||||
o->mode = Addressing_Context;
|
||||
o->type = t_context;
|
||||
break;
|
||||
|
||||
|
||||
@@ -167,10 +167,6 @@ bool check_is_terminating(Ast *node) {
|
||||
}
|
||||
return has_default;
|
||||
case_end;
|
||||
|
||||
case_ast_node(pc, PushContext, node);
|
||||
return check_is_terminating(pc->body);
|
||||
case_end;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -306,6 +302,10 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
|
||||
break;
|
||||
}
|
||||
|
||||
case Addressing_Context: {
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (lhs->expr->kind == Ast_SelectorExpr) {
|
||||
// NOTE(bill): Extra error checks
|
||||
@@ -1597,13 +1597,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(pa, PushContext, node);
|
||||
Operand op = {};
|
||||
check_expr(ctx, &op, pa->expr);
|
||||
check_assignment(ctx, &op, t_context, str_lit("argument to context <-"));
|
||||
check_stmt(ctx, pa->body, mod_flags);
|
||||
case_end;
|
||||
|
||||
case_ast_node(fb, ForeignBlockDecl, node);
|
||||
Ast *foreign_library = fb->foreign_library;
|
||||
CheckerContext c = *ctx;
|
||||
|
||||
@@ -338,6 +338,7 @@ gb_global bool global_module_path_set = false;
|
||||
typedef struct Arena {
|
||||
u8 * ptr;
|
||||
u8 * end;
|
||||
u8 * prev;
|
||||
Array<u8 *> blocks;
|
||||
gbAllocator backing;
|
||||
isize block_size;
|
||||
@@ -363,11 +364,11 @@ void arena_grow(Arena *arena, isize min_size) {
|
||||
isize size = gb_max(arena->block_size, min_size);
|
||||
size = ALIGN_UP(size, ARENA_MIN_ALIGNMENT);
|
||||
void *new_ptr = gb_alloc(arena->backing, size);
|
||||
arena->ptr = cast(u8 *)new_ptr;
|
||||
gb_zero_size(arena->ptr, size);
|
||||
GB_ASSERT(arena->ptr == ALIGN_DOWN_PTR(arena->ptr, ARENA_MIN_ALIGNMENT));
|
||||
arena->end = arena->ptr + size;
|
||||
array_add(&arena->blocks, arena->ptr);
|
||||
arena->ptr = cast(u8 *)new_ptr;
|
||||
gb_zero_size(arena->ptr, size);
|
||||
GB_ASSERT(arena->ptr == ALIGN_DOWN_PTR(arena->ptr, ARENA_MIN_ALIGNMENT));
|
||||
arena->end = arena->ptr + size;
|
||||
array_add(&arena->blocks, arena->ptr);
|
||||
}
|
||||
|
||||
void *arena_alloc(Arena *arena, isize size, isize alignment) {
|
||||
@@ -376,18 +377,19 @@ void *arena_alloc(Arena *arena, isize size, isize alignment) {
|
||||
|
||||
arena->total_used += size;
|
||||
|
||||
if (size > (arena->end - arena->ptr)) {
|
||||
arena_grow(arena, size);
|
||||
GB_ASSERT(size <= (arena->end - arena->ptr));
|
||||
}
|
||||
if (size > (arena->end - arena->ptr)) {
|
||||
arena_grow(arena, size);
|
||||
GB_ASSERT(size <= (arena->end - arena->ptr));
|
||||
}
|
||||
|
||||
isize align = gb_max(alignment, ARENA_MIN_ALIGNMENT);
|
||||
void *ptr = arena->ptr;
|
||||
arena->ptr = cast(u8 *)ALIGN_UP_PTR(arena->ptr + size, align);
|
||||
GB_ASSERT(arena->ptr <= arena->end);
|
||||
GB_ASSERT(ptr == ALIGN_DOWN_PTR(ptr, align));
|
||||
gb_zero_size(ptr, size);
|
||||
return ptr;
|
||||
isize align = gb_max(alignment, ARENA_MIN_ALIGNMENT);
|
||||
void *ptr = arena->ptr;
|
||||
arena->prev = arena->ptr;
|
||||
arena->ptr = cast(u8 *)ALIGN_UP_PTR(arena->ptr + size, align);
|
||||
GB_ASSERT(arena->ptr <= arena->end);
|
||||
GB_ASSERT(ptr == ALIGN_DOWN_PTR(ptr, align));
|
||||
gb_zero_size(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void arena_free_all(Arena *arena) {
|
||||
@@ -395,11 +397,11 @@ void arena_free_all(Arena *arena) {
|
||||
defer (gb_mutex_unlock(&arena->mutex));
|
||||
|
||||
for_array(i, arena->blocks) {
|
||||
gb_free(arena->backing, arena->blocks[i]);
|
||||
}
|
||||
array_clear(&arena->blocks);
|
||||
arena->ptr = nullptr;
|
||||
arena->end = nullptr;
|
||||
gb_free(arena->backing, arena->blocks[i]);
|
||||
}
|
||||
array_clear(&arena->blocks);
|
||||
arena->ptr = nullptr;
|
||||
arena->end = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
104
src/ir.cpp
104
src/ir.cpp
@@ -113,6 +113,11 @@ struct irDebugLocation {
|
||||
irDebugInfo *debug_scope;
|
||||
};
|
||||
|
||||
struct irContextData {
|
||||
irValue *value;
|
||||
i32 scope_index;
|
||||
};
|
||||
|
||||
struct irProcedure {
|
||||
irProcedure * parent;
|
||||
Array<irProcedure *> children;
|
||||
@@ -142,7 +147,7 @@ struct irProcedure {
|
||||
irTargetList * target_list;
|
||||
Array<irValue *> referrers;
|
||||
|
||||
Array<irValue *> context_stack;
|
||||
Array<irContextData> context_stack;
|
||||
|
||||
|
||||
Array<irBranchBlocks> branch_blocks;
|
||||
@@ -443,6 +448,7 @@ enum irAddrKind {
|
||||
irAddr_Default,
|
||||
irAddr_Map,
|
||||
irAddr_BitField,
|
||||
irAddr_Context,
|
||||
};
|
||||
|
||||
struct irAddr {
|
||||
@@ -473,6 +479,13 @@ irAddr ir_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_re
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
irAddr ir_addr_context(irValue *addr) {
|
||||
irAddr v = {irAddr_Context, addr};
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
irAddr ir_addr_bit_field(irValue *addr, i32 bit_field_value_index) {
|
||||
irAddr v = {irAddr_BitField, addr};
|
||||
v.bit_field_value_index = bit_field_value_index;
|
||||
@@ -1354,7 +1367,10 @@ void ir_add_foreign_library_path(irModule *m, Entity *e) {
|
||||
|
||||
|
||||
|
||||
|
||||
void ir_push_context_onto_stack(irProcedure *proc, irValue *ctx) {
|
||||
irContextData cd = {ctx, proc->scope_index};
|
||||
array_add(&proc->context_stack, cd);
|
||||
}
|
||||
|
||||
irValue *ir_add_local(irProcedure *proc, Entity *e, Ast *expr, bool zero_initialized) {
|
||||
irBlock *b = proc->decl_block; // all variables must be in the first block
|
||||
@@ -1622,7 +1638,7 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index);
|
||||
|
||||
irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
|
||||
if (proc->context_stack.count > 0) {
|
||||
return proc->context_stack[proc->context_stack.count-1];
|
||||
return proc->context_stack[proc->context_stack.count-1].value;
|
||||
}
|
||||
|
||||
irBlock *tmp_block = proc->curr_block;
|
||||
@@ -1631,7 +1647,7 @@ irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
|
||||
defer (proc->curr_block = tmp_block);
|
||||
|
||||
irValue *c = ir_add_local_generated(proc, t_context);
|
||||
array_add(&proc->context_stack, c);
|
||||
ir_push_context_onto_stack(proc, c);
|
||||
ir_emit_store(proc, c, ir_emit_load(proc, proc->module->global_default_context));
|
||||
|
||||
irValue *ep = ir_emit_struct_ep(proc, c, 0);
|
||||
@@ -1763,6 +1779,21 @@ void ir_open_scope(irProcedure *proc) {
|
||||
void ir_close_scope(irProcedure *proc, irDeferExitKind kind, irBlock *block) {
|
||||
ir_emit_defer_stmts(proc, kind, block);
|
||||
GB_ASSERT(proc->scope_index > 0);
|
||||
|
||||
|
||||
// NOTE(bill): Remove `context`s made in that scope
|
||||
for (;;) {
|
||||
irContextData *end = array_end_ptr(&proc->context_stack);
|
||||
if (end == nullptr) {
|
||||
break;
|
||||
}
|
||||
if (end->scope_index != proc->scope_index) {
|
||||
break;
|
||||
}
|
||||
array_pop(&proc->context_stack);
|
||||
}
|
||||
|
||||
|
||||
proc->scope_index--;
|
||||
}
|
||||
|
||||
@@ -1923,6 +1954,7 @@ irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, Token
|
||||
irValue *ir_emit_source_code_location(irProcedure *proc, Ast *node);
|
||||
irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset);
|
||||
irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue *right, Type *type);
|
||||
irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel);
|
||||
|
||||
irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type,
|
||||
irValue *map_key, irValue *map_value) {
|
||||
@@ -1945,12 +1977,13 @@ irValue *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, T
|
||||
|
||||
|
||||
|
||||
irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
if (addr.addr == nullptr) {
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
if (addr.kind == irAddr_Map) {
|
||||
return ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
|
||||
ir_insert_dynamic_map_key_and_value(proc, addr.addr, addr.map_type, addr.map_key, value);
|
||||
return;
|
||||
} else if (addr.kind == irAddr_BitField) {
|
||||
gbAllocator a = ir_allocator();
|
||||
|
||||
@@ -1966,7 +1999,7 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
i32 size_in_bytes = next_pow2((size_in_bits+7)/8);
|
||||
if (size_in_bytes == 0) {
|
||||
GB_ASSERT(size_in_bits == 0);
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
Type *int_type = nullptr;
|
||||
@@ -1994,7 +2027,8 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
}
|
||||
irValue *ptr = ir_emit_conv(proc, bytes, alloc_type_pointer(int_type));
|
||||
v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
|
||||
return ir_emit_store(proc, ptr, v);
|
||||
ir_emit_store(proc, ptr, v);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -2015,12 +2049,30 @@ irValue *ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
|
||||
irValue *ptr = ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), alloc_type_pointer(int_type));
|
||||
irValue *v = ir_emit_arith(proc, Token_Shr, value, shift_amount, int_type);
|
||||
v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type);
|
||||
return ir_emit_store(proc, ptr, v);
|
||||
ir_emit_store(proc, ptr, v);
|
||||
return;
|
||||
}
|
||||
} else if (addr.kind == irAddr_Context) {
|
||||
irValue *new_context = ir_emit_conv(proc, value, ir_addr_type(addr));
|
||||
|
||||
irValue *prev = ir_find_or_generate_context_ptr(proc);
|
||||
GB_ASSERT(addr.addr == prev);
|
||||
|
||||
irValue *next = ir_add_local_generated(proc, t_context);
|
||||
ir_emit_store(proc, next, new_context);
|
||||
|
||||
Selection sel = lookup_field(t_context, str_lit("parent"), false);
|
||||
GB_ASSERT(sel.entity != nullptr);
|
||||
irValue *parent_ptr = ir_emit_deep_field_gep(proc, next, sel);
|
||||
ir_emit_store(proc, parent_ptr, prev);
|
||||
|
||||
ir_push_context_onto_stack(proc, next);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
irValue *v = ir_emit_conv(proc, value, ir_addr_type(addr));
|
||||
return ir_emit_store(proc, addr.addr, v);
|
||||
ir_emit_store(proc, addr.addr, v);
|
||||
}
|
||||
|
||||
irValue *ir_addr_load(irProcedure *proc, irAddr const &addr) {
|
||||
@@ -5559,7 +5611,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||
}
|
||||
|
||||
GB_ASSERT(v != nullptr);
|
||||
return ir_addr(v);
|
||||
return ir_addr_context(v);
|
||||
case_end;
|
||||
|
||||
case_ast_node(i, Ident, expr);
|
||||
@@ -7408,32 +7460,6 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
|
||||
ir_emit_jump(proc, block);
|
||||
ir_emit_unreachable(proc);
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(pc, PushContext, node);
|
||||
ir_emit_comment(proc, str_lit("push_context"));
|
||||
irValue *new_context = ir_build_expr(proc, pc->expr);
|
||||
|
||||
ir_open_scope(proc);
|
||||
|
||||
irValue *prev = ir_find_or_generate_context_ptr(proc);
|
||||
irValue *next = ir_add_local_generated(proc, t_context);
|
||||
ir_emit_store(proc, next, new_context);
|
||||
|
||||
Selection sel = lookup_field(t_context, str_lit("parent"), false);
|
||||
GB_ASSERT(sel.entity != nullptr);
|
||||
irValue *parent_ptr = ir_emit_deep_field_gep(proc, next, sel);
|
||||
ir_emit_store(proc, parent_ptr, prev);
|
||||
|
||||
array_add(&proc->context_stack, next);
|
||||
defer (array_pop(&proc->context_stack));
|
||||
|
||||
ir_build_stmt(proc, pc->body);
|
||||
|
||||
ir_close_scope(proc, irDeferExit_Default, nullptr);
|
||||
case_end;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7583,7 +7609,7 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
||||
e->flags |= EntityFlag_NoAlias;
|
||||
irValue *param = ir_value_param(proc, e, e->type);
|
||||
ir_module_add_value(proc->module, e, param);
|
||||
array_add(&proc->context_stack, param);
|
||||
array_add(&proc->context_stack, {param, proc->scope_index});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ Token ast_token(Ast *node) {
|
||||
case Ast_DeferStmt: return node->DeferStmt.token;
|
||||
case Ast_BranchStmt: return node->BranchStmt.token;
|
||||
case Ast_UsingStmt: return node->UsingStmt.token;
|
||||
case Ast_PushContext: return node->PushContext.token;
|
||||
|
||||
case Ast_BadDecl: return node->BadDecl.begin;
|
||||
case Ast_Label: return node->Label.token;
|
||||
@@ -274,10 +273,6 @@ Ast *clone_ast(Ast *node) {
|
||||
case Ast_UsingStmt:
|
||||
n->UsingStmt.list = clone_ast_array(n->UsingStmt.list);
|
||||
break;
|
||||
case Ast_PushContext:
|
||||
n->PushContext.expr = clone_ast(n->PushContext.expr);
|
||||
n->PushContext.body = clone_ast(n->PushContext.body);
|
||||
break;
|
||||
|
||||
case Ast_BadDecl: break;
|
||||
|
||||
@@ -787,15 +782,6 @@ Ast *ast_using_stmt(AstFile *f, Token token, Array<Ast *> list) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Ast *ast_push_context(AstFile *f, Token token, Ast *expr, Ast *body) {
|
||||
Ast *result = alloc_ast_node(f, Ast_PushContext);
|
||||
result->PushContext.token = token;
|
||||
result->PushContext.expr = expr;
|
||||
result->PushContext.body = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Ast *ast_bad_decl(AstFile *f, Token begin, Token end) {
|
||||
@@ -1267,7 +1253,6 @@ bool is_semicolon_optional_for_node(AstFile *f, Ast *s) {
|
||||
case Ast_RangeStmt:
|
||||
case Ast_SwitchStmt:
|
||||
case Ast_TypeSwitchStmt:
|
||||
case Ast_PushContext:
|
||||
return true;
|
||||
|
||||
case Ast_HelperType:
|
||||
@@ -2540,25 +2525,6 @@ Ast *parse_simple_stmt(AstFile *f, u32 flags) {
|
||||
}
|
||||
}
|
||||
return parse_value_decl(f, lhs, docs);
|
||||
|
||||
case Token_ArrowLeft:
|
||||
if ((flags&StmtAllowFlag_Context) && lhs.count == 1) {
|
||||
Token arrow = expect_token(f, Token_ArrowLeft);
|
||||
Ast *body = nullptr;
|
||||
isize prev_level = f->expr_level;
|
||||
f->expr_level = -1;
|
||||
Ast *expr = parse_expr(f, false);
|
||||
f->expr_level = prev_level;
|
||||
|
||||
if (allow_token(f, Token_do)) {
|
||||
body = convert_stmt_to_body(f, parse_stmt(f));
|
||||
} else {
|
||||
body = parse_block_stmt(f, false);
|
||||
}
|
||||
|
||||
return ast_push_context(f, token, expr, body);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (lhs.count > 1) {
|
||||
@@ -3548,7 +3514,7 @@ Ast *parse_stmt(AstFile *f) {
|
||||
case Token_Xor:
|
||||
case Token_Not:
|
||||
case Token_And:
|
||||
s = parse_simple_stmt(f, StmtAllowFlag_Label|StmtAllowFlag_Context);
|
||||
s = parse_simple_stmt(f, StmtAllowFlag_Label);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ enum AddressingMode {
|
||||
Addressing_NoValue, // no value (void in C)
|
||||
Addressing_Value, // computed value (rvalue)
|
||||
Addressing_Immutable, // immutable computed value (const rvalue)
|
||||
Addressing_Context, // context value
|
||||
Addressing_Variable, // addressable variable (lvalue)
|
||||
Addressing_Constant, // constant
|
||||
Addressing_Type, // type
|
||||
@@ -191,7 +192,6 @@ enum StmtAllowFlag {
|
||||
StmtAllowFlag_None = 0,
|
||||
StmtAllowFlag_In = 1<<0,
|
||||
StmtAllowFlag_Label = 1<<1,
|
||||
StmtAllowFlag_Context = 1<<2,
|
||||
};
|
||||
|
||||
#define AST_KINDS \
|
||||
@@ -343,11 +343,6 @@ AST_KIND(_ComplexStmtBegin, "", bool) \
|
||||
Token token; \
|
||||
Array<Ast *> list; \
|
||||
}) \
|
||||
AST_KIND(PushContext, "context <- statement", struct { \
|
||||
Token token; \
|
||||
Ast *expr; \
|
||||
Ast *body; \
|
||||
}) \
|
||||
AST_KIND(_ComplexStmtEnd, "", bool) \
|
||||
AST_KIND(_StmtEnd, "", bool) \
|
||||
AST_KIND(_DeclBegin, "", bool) \
|
||||
|
||||
Reference in New Issue
Block a user