Browse Source

Replace `context <- c {}` with `context = c;`. context assignments are scope based

gingerBill 7 years ago
parent
commit
cdbf831a7a
10 changed files with 133 additions and 136 deletions
  1. 4 5
      core/mem/mem.odin
  2. 2 6
      core/thread/thread_windows.odin
  3. 9 11
      examples/demo/demo.odin
  4. 9 0
      src/array.cpp
  5. 15 2
      src/check_expr.cpp
  6. 4 11
      src/check_stmt.cpp
  7. 23 21
      src/common.cpp
  8. 65 39
      src/ir.cpp
  9. 1 35
      src/parser.cpp
  10. 1 6
      src/parser.hpp

+ 4 - 5
core/mem/mem.odin

@@ -211,12 +211,11 @@ context_from_allocator :: proc(a: Allocator) -> runtime.Context {
 
 
 destroy_arena :: proc(using a: ^Arena) {
 destroy_arena :: proc(using a: ^Arena) {
 	if backing.procedure != nil {
 	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;
 	}
 	}
 }
 }
 
 

+ 2 - 6
core/thread/thread_windows.odin

@@ -29,13 +29,9 @@ create :: proc(procedure: Thread_Proc) -> ^Thread {
 		if t.use_init_context {
 		if t.use_init_context {
 			c = t.init_context;
 			c = t.init_context;
 		}
 		}
+		context = c;
 
 
-		exit := 0;
-		context <- c {
-			exit = t.procedure(t);
-		}
-
-		return i32(exit);
+		return i32(t.procedure(t));
 	}
 	}
 
 
 
 

+ 9 - 11
examples/demo/demo.odin

@@ -364,26 +364,24 @@ parametric_polymorphism :: proc() {
 		allocate :: proc(table: ^$T/Table, capacity: int) {
 		allocate :: proc(table: ^$T/Table, capacity: int) {
 			c := context;
 			c := context;
 			if table.allocator.procedure != nil do c.allocator = table.allocator;
 			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) {
 		expand :: proc(table: ^$T/Table) {
 			c := context;
 			c := context;
 			if table.allocator.procedure != nil do c.allocator = table.allocator;
 			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);
 			}
 			}
 		}
 		}
 
 

+ 9 - 0
src/array.cpp

@@ -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> 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> 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>
 template <typename T>
 gb_inline void array_init(Array<T> *array, gbAllocator const &a) {
 gb_inline void array_init(Array<T> *array, gbAllocator const &a) {
 	isize cap = ARRAY_GROW_FORMULA(0);
 	isize cap = ARRAY_GROW_FORMULA(0);

+ 15 - 2
src/check_expr.cpp

@@ -578,7 +578,7 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
 
 
 	if (is_type_any(dst)) {
 	if (is_type_any(dst)) {
 		if (!is_type_polymorphic(src)) {
 		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;
 				return -1;
 			} else {
 			} else {
 				// NOTE(bill): Anything can cast to 'Any'
 				// NOTE(bill): Anything can cast to 'Any'
@@ -2040,6 +2040,17 @@ void check_binary_expr(CheckerContext *c, Operand *x, Ast *node) {
 		return;
 		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)) {
 	if (token_is_shift(op.kind)) {
 		check_shift(c, x, y, node);
 		check_shift(c, x, y, node);
 		return;
 		return;
@@ -2724,6 +2735,8 @@ Entity *check_selector(CheckerContext *c, Operand *operand, Ast *node, Type *typ
 		// TODO(bill): Is this the rule I need?
 		// TODO(bill): Is this the rule I need?
 		if (operand->mode == Addressing_Immutable) {
 		if (operand->mode == Addressing_Immutable) {
 			// Okay
 			// 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) {
 		} else if (sel.indirect || operand->mode != Addressing_Value) {
 			operand->mode = Addressing_Variable;
 			operand->mode = Addressing_Variable;
 		} else {
 		} else {
@@ -5211,7 +5224,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
 			}
 			}
 
 
 			init_core_context(c->checker);
 			init_core_context(c->checker);
-			o->mode = Addressing_Immutable;
+			o->mode = Addressing_Context;
 			o->type = t_context;
 			o->type = t_context;
 			break;
 			break;
 
 

+ 4 - 11
src/check_stmt.cpp

@@ -167,10 +167,6 @@ bool check_is_terminating(Ast *node) {
 		}
 		}
 		return has_default;
 		return has_default;
 	case_end;
 	case_end;
-
-	case_ast_node(pc, PushContext, node);
-		return check_is_terminating(pc->body);
-	case_end;
 	}
 	}
 
 
 	return false;
 	return false;
@@ -306,6 +302,10 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
 		break;
 		break;
 	}
 	}
 
 
+	case Addressing_Context: {
+		break;
+	}
+
 	default: {
 	default: {
 		if (lhs->expr->kind == Ast_SelectorExpr) {
 		if (lhs->expr->kind == Ast_SelectorExpr) {
 			// NOTE(bill): Extra error checks
 			// NOTE(bill): Extra error checks
@@ -1597,13 +1597,6 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
 		}
 		}
 	case_end;
 	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);
 	case_ast_node(fb, ForeignBlockDecl, node);
 		Ast *foreign_library = fb->foreign_library;
 		Ast *foreign_library = fb->foreign_library;
 		CheckerContext c = *ctx;
 		CheckerContext c = *ctx;

+ 23 - 21
src/common.cpp

@@ -338,6 +338,7 @@ gb_global bool global_module_path_set = false;
 typedef struct Arena {
 typedef struct Arena {
 	u8 *        ptr;
 	u8 *        ptr;
 	u8 *        end;
 	u8 *        end;
+	u8 *        prev;
 	Array<u8 *> blocks;
 	Array<u8 *> blocks;
 	gbAllocator backing;
 	gbAllocator backing;
 	isize       block_size;
 	isize       block_size;
@@ -363,11 +364,11 @@ void arena_grow(Arena *arena, isize min_size) {
 	isize size = gb_max(arena->block_size, min_size);
 	isize size = gb_max(arena->block_size, min_size);
 	size = ALIGN_UP(size, ARENA_MIN_ALIGNMENT);
 	size = ALIGN_UP(size, ARENA_MIN_ALIGNMENT);
 	void *new_ptr = gb_alloc(arena->backing, size);
 	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) {
 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;
 	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) {
 void arena_free_all(Arena *arena) {
@@ -395,11 +397,11 @@ void arena_free_all(Arena *arena) {
 	defer (gb_mutex_unlock(&arena->mutex));
 	defer (gb_mutex_unlock(&arena->mutex));
 
 
 	for_array(i, arena->blocks) {
 	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;
 }
 }
 
 
 
 

+ 65 - 39
src/ir.cpp

@@ -113,6 +113,11 @@ struct irDebugLocation {
 	irDebugInfo *debug_scope;
 	irDebugInfo *debug_scope;
 };
 };
 
 
+struct irContextData {
+	irValue *value;
+	i32 scope_index;
+};
+
 struct irProcedure {
 struct irProcedure {
 	irProcedure *         parent;
 	irProcedure *         parent;
 	Array<irProcedure *>  children;
 	Array<irProcedure *>  children;
@@ -142,7 +147,7 @@ struct irProcedure {
 	irTargetList *        target_list;
 	irTargetList *        target_list;
 	Array<irValue *>      referrers;
 	Array<irValue *>      referrers;
 
 
-	Array<irValue *>      context_stack;
+	Array<irContextData>  context_stack;
 
 
 
 
 	Array<irBranchBlocks> branch_blocks;
 	Array<irBranchBlocks> branch_blocks;
@@ -443,6 +448,7 @@ enum irAddrKind {
 	irAddr_Default,
 	irAddr_Default,
 	irAddr_Map,
 	irAddr_Map,
 	irAddr_BitField,
 	irAddr_BitField,
+	irAddr_Context,
 };
 };
 
 
 struct irAddr {
 struct irAddr {
@@ -473,6 +479,13 @@ irAddr ir_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *map_re
 	return v;
 	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 ir_addr_bit_field(irValue *addr, i32 bit_field_value_index) {
 	irAddr v = {irAddr_BitField, addr};
 	irAddr v = {irAddr_BitField, addr};
 	v.bit_field_value_index = bit_field_value_index;
 	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) {
 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
 	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) {
 irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
 	if (proc->context_stack.count > 0) {
 	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;
 	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);
 	defer (proc->curr_block = tmp_block);
 
 
 	irValue *c = ir_add_local_generated(proc, t_context);
 	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));
 	ir_emit_store(proc, c, ir_emit_load(proc, proc->module->global_default_context));
 
 
 	irValue *ep = ir_emit_struct_ep(proc, c, 0);
 	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) {
 void ir_close_scope(irProcedure *proc, irDeferExitKind kind, irBlock *block) {
 	ir_emit_defer_stmts(proc, kind, block);
 	ir_emit_defer_stmts(proc, kind, block);
 	GB_ASSERT(proc->scope_index > 0);
 	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--;
 	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_source_code_location(irProcedure *proc, Ast *node);
 irValue *ir_emit_ptr_offset(irProcedure *proc, irValue *ptr, irValue *offset);
 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_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 *ir_insert_dynamic_map_key_and_value(irProcedure *proc, irValue *addr, Type *map_type,
                                              irValue *map_key, irValue *map_value) {
                                              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) {
 	if (addr.addr == nullptr) {
-		return nullptr;
+		return;
 	}
 	}
 	if (addr.kind == irAddr_Map) {
 	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) {
 	} else if (addr.kind == irAddr_BitField) {
 		gbAllocator a = ir_allocator();
 		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);
 		i32 size_in_bytes = next_pow2((size_in_bits+7)/8);
 		if (size_in_bytes == 0) {
 		if (size_in_bytes == 0) {
 			GB_ASSERT(size_in_bits == 0);
 			GB_ASSERT(size_in_bits == 0);
-			return nullptr;
+			return;
 		}
 		}
 
 
 		Type *int_type = nullptr;
 		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));
 			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);
 			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 *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);
 			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);
 			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));
 	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) {
 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);
 		GB_ASSERT(v != nullptr);
-		return ir_addr(v);
+		return ir_addr_context(v);
 	case_end;
 	case_end;
 
 
 	case_ast_node(i, Ident, expr);
 	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_jump(proc, block);
 		ir_emit_unreachable(proc);
 		ir_emit_unreachable(proc);
 	case_end;
 	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;
 		e->flags |= EntityFlag_NoAlias;
 		irValue *param = ir_value_param(proc, e, e->type);
 		irValue *param = ir_value_param(proc, e, e->type);
 		ir_module_add_value(proc->module, e, param);
 		ir_module_add_value(proc->module, e, param);
-		array_add(&proc->context_stack, param);
+		array_add(&proc->context_stack, {param, proc->scope_index});
 	}
 	}
 }
 }
 
 

+ 1 - 35
src/parser.cpp

@@ -53,7 +53,6 @@ Token ast_token(Ast *node) {
 	case Ast_DeferStmt:          return node->DeferStmt.token;
 	case Ast_DeferStmt:          return node->DeferStmt.token;
 	case Ast_BranchStmt:         return node->BranchStmt.token;
 	case Ast_BranchStmt:         return node->BranchStmt.token;
 	case Ast_UsingStmt:          return node->UsingStmt.token;
 	case Ast_UsingStmt:          return node->UsingStmt.token;
-	case Ast_PushContext:        return node->PushContext.token;
 
 
 	case Ast_BadDecl:            return node->BadDecl.begin;
 	case Ast_BadDecl:            return node->BadDecl.begin;
 	case Ast_Label:              return node->Label.token;
 	case Ast_Label:              return node->Label.token;
@@ -274,10 +273,6 @@ Ast *clone_ast(Ast *node) {
 	case Ast_UsingStmt:
 	case Ast_UsingStmt:
 		n->UsingStmt.list = clone_ast_array(n->UsingStmt.list);
 		n->UsingStmt.list = clone_ast_array(n->UsingStmt.list);
 		break;
 		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;
 	case Ast_BadDecl: break;
 
 
@@ -787,15 +782,6 @@ Ast *ast_using_stmt(AstFile *f, Token token, Array<Ast *> list) {
 	return result;
 	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) {
 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_RangeStmt:
 	case Ast_SwitchStmt:
 	case Ast_SwitchStmt:
 	case Ast_TypeSwitchStmt:
 	case Ast_TypeSwitchStmt:
-	case Ast_PushContext:
 		return true;
 		return true;
 
 
 	case Ast_HelperType:
 	case Ast_HelperType:
@@ -2540,25 +2525,6 @@ Ast *parse_simple_stmt(AstFile *f, u32 flags) {
 			}
 			}
 		}
 		}
 		return parse_value_decl(f, lhs, docs);
 		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) {
 	if (lhs.count > 1) {
@@ -3548,7 +3514,7 @@ Ast *parse_stmt(AstFile *f) {
 	case Token_Xor:
 	case Token_Xor:
 	case Token_Not:
 	case Token_Not:
 	case Token_And:
 	case Token_And:
-		s = parse_simple_stmt(f, StmtAllowFlag_Label|StmtAllowFlag_Context);
+		s = parse_simple_stmt(f, StmtAllowFlag_Label);
 		expect_semicolon(f, s);
 		expect_semicolon(f, s);
 		return s;
 		return s;
 
 

+ 1 - 6
src/parser.hpp

@@ -11,6 +11,7 @@ enum AddressingMode {
 	Addressing_NoValue,       // no value (void in C)
 	Addressing_NoValue,       // no value (void in C)
 	Addressing_Value,         // computed value (rvalue)
 	Addressing_Value,         // computed value (rvalue)
 	Addressing_Immutable,     // immutable computed value (const rvalue)
 	Addressing_Immutable,     // immutable computed value (const rvalue)
+	Addressing_Context,       // context value
 	Addressing_Variable,      // addressable variable (lvalue)
 	Addressing_Variable,      // addressable variable (lvalue)
 	Addressing_Constant,      // constant
 	Addressing_Constant,      // constant
 	Addressing_Type,          // type
 	Addressing_Type,          // type
@@ -191,7 +192,6 @@ enum StmtAllowFlag {
 	StmtAllowFlag_None    = 0,
 	StmtAllowFlag_None    = 0,
 	StmtAllowFlag_In      = 1<<0,
 	StmtAllowFlag_In      = 1<<0,
 	StmtAllowFlag_Label   = 1<<1,
 	StmtAllowFlag_Label   = 1<<1,
-	StmtAllowFlag_Context = 1<<2,
 };
 };
 
 
 #define AST_KINDS \
 #define AST_KINDS \
@@ -343,11 +343,6 @@ AST_KIND(_ComplexStmtBegin, "", bool) \
 		Token token; \
 		Token token; \
 		Array<Ast *> list; \
 		Array<Ast *> list; \
 	}) \
 	}) \
-	AST_KIND(PushContext, "context <- statement", struct { \
-		Token token; \
-		Ast *expr; \
-		Ast *body; \
-	}) \
 AST_KIND(_ComplexStmtEnd, "", bool) \
 AST_KIND(_ComplexStmtEnd, "", bool) \
 AST_KIND(_StmtEnd,        "", bool) \
 AST_KIND(_StmtEnd,        "", bool) \
 AST_KIND(_DeclBegin,      "", bool) \
 AST_KIND(_DeclBegin,      "", bool) \