Browse Source

Any order declarations at procedure scope (except variables)

Ginger Bill 9 years ago
parent
commit
ff229054a1
5 changed files with 109 additions and 30 deletions
  1. 3 5
      code/demo.odin
  2. 7 6
      core/runtime.odin
  3. 84 12
      src/checker/stmt.cpp
  4. 4 0
      src/codegen/codegen.cpp
  5. 11 7
      src/codegen/ssa.cpp

+ 3 - 5
code/demo.odin

@@ -4,17 +4,15 @@
 
 
 main :: proc() {
-	x :: proc() -> (int, int) {
-		return 1, 2
-	}
 	y :: proc() -> (int, int) {
 		return x()
 	}
+	x :: proc() -> (int, int) {
+		return 1, 2
+	}
 
 	fmt.println(y())
 
-
-
 	arena: mem.Arena
 	mem.init_arena_from_context(^arena, 1000)
 	defer mem.free_arena(^arena)

+ 7 - 6
core/runtime.odin

@@ -175,13 +175,12 @@ Context :: struct #ordered {
 DEFAULT_ALIGNMENT :: align_of({4}f32)
 
 
-current_context :: proc() -> ^Context {
-	return ^__context
+current_context :: proc() -> Context { // Copy of context
+	return __context
 }
 
 __check_context :: proc() {
-	c := current_context()
-	assert(c != null)
+	c := ^__context
 
 	if c.allocator.procedure == null {
 		c.allocator = __default_allocator()
@@ -202,12 +201,14 @@ alloc_align :: proc(size, alignment: int) -> rawptr #inline {
 free :: proc(ptr: rawptr) #inline {
 	__check_context()
 	a := current_context().allocator
-	_ = a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
+	if ptr != null {
+		a.procedure(a.data, Allocator.Mode.FREE, 0, 0, ptr, 0, 0)
+	}
 }
 free_all :: proc() #inline {
 	__check_context()
 	a := current_context().allocator
-	_ = a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0)
+	a.procedure(a.data, Allocator.Mode.FREE_ALL, 0, 0, null, 0, 0)
 }
 
 

+ 84 - 12
src/checker/stmt.cpp

@@ -9,10 +9,91 @@ enum StmtFlag : u32 {
 
 void check_stmt(Checker *c, AstNode *node, u32 flags);
 void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
+void check_const_decl_node(Checker *c, AstNode *node);
 
 void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
 	// TODO(bill): Allow declaration (expect variable) in any order
 	// even within a procedure
+	struct Delay {
+		Entity *e;
+		DeclInfo *d;
+	};
+	gbArray(Delay) delayed; gb_array_init(delayed, gb_heap_allocator());
+
+	gb_for_array(i, stmts) {
+		AstNode *node = stmts[i];
+		switch (node->kind) {
+		case_ast_node(cd, ConstDecl, node);
+			gb_for_array(i, cd->values) {
+				AstNode *name = cd->names[i];
+				AstNode *value = cd->values[i];
+				ExactValue v = {ExactValue_Invalid};
+
+				Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
+				add_entity(c, e->scope, name, e);
+
+				DeclInfo *di = make_declaration_info(c->allocator, e->scope);
+				di->type_expr = cd->type;
+				di->init_expr = value;
+
+				Delay delay = {e, di};
+				gb_array_append(delayed, delay);
+			}
+
+			isize lhs_count = gb_array_count(cd->names);
+			isize rhs_count = gb_array_count(cd->values);
+
+			if (rhs_count == 0 && cd->type == NULL) {
+				error(ast_node_token(node), "Missing type or initial expression");
+			} else if (lhs_count < rhs_count) {
+				error(ast_node_token(node), "Extra initial expression");
+			}
+		case_end;
+
+		case_ast_node(td, TypeDecl, node);
+			Entity *e = make_entity_type_name(c->allocator, c->context.scope, td->name->Ident, NULL);
+			add_entity(c, c->context.scope, td->name, e);
+
+			DeclInfo *d = make_declaration_info(c->allocator, e->scope);
+			d->type_expr = td->type;
+
+			Delay delay = {e, d};
+			gb_array_append(delayed, delay);
+		case_end;
+
+		case_ast_node(pd, ProcDecl, node);
+			ast_node(name, Ident, pd->name);
+			Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL);
+			add_entity(c, c->context.scope, pd->name, e);
+
+			DeclInfo *d = make_declaration_info(c->allocator, e->scope);
+			d->proc_decl = node;
+
+			Delay delay = {e, d};
+			gb_array_append(delayed, delay);
+		case_end;
+		}
+	}
+
+	auto check_scope_entity = [](Checker *c, gbArray(Delay) delayed, EntityKind kind) {
+		gb_for_array(i, delayed) {
+			auto delay = delayed[i];
+			Entity *e = delay.e;
+			if (e->kind == kind) {
+				DeclInfo *d = delay.d;
+				Scope *prev_scope = c->context.scope;
+				c->context.scope = d->scope;
+				GB_ASSERT(d->scope == e->scope);
+				check_entity_decl(c, e, d, NULL);
+				c->context.scope = prev_scope;
+			}
+		}
+	};
+	check_scope_entity(c, delayed, Entity_TypeName);
+	check_scope_entity(c, delayed, Entity_Constant);
+	check_scope_entity(c, delayed, Entity_Procedure);
+
+
 
 	b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
 	u32 f = flags & (~Stmt_FallthroughAllowed);
@@ -1512,24 +1593,15 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 	case_end;
 
 	case_ast_node(cd, ConstDecl, node);
-		check_const_decl_node(c, node);
+		// NOTE(bill): Handled elsewhere
 	case_end;
 
 	case_ast_node(pd, ProcDecl, node);
-		ast_node(name, Ident, pd->name);
-		Entity *e = make_entity_procedure(c->allocator, c->context.scope, *name, NULL);
-		add_entity(c, c->context.scope, pd->name, e);
-
-		DeclInfo *decl = make_declaration_info(c->allocator, e->scope);
-		decl->proc_decl = node;
-		check_proc_decl(c, e, decl);
+		// NOTE(bill): Handled elsewhere
 	case_end;
 
 	case_ast_node(td, TypeDecl, node);
-		ast_node(name, Ident, td->name);
-		Entity *e = make_entity_type_name(c->allocator, c->context.scope, *name, NULL);
-		add_entity(c, c->context.scope, td->name, e);
-		check_type_decl(c, e, td->type, NULL, NULL);
+		// NOTE(bill): Handled elsewhere
 	case_end;
 	}
 }

+ 4 - 0
src/codegen/codegen.cpp

@@ -635,6 +635,10 @@ void ssa_gen_tree(ssaGen *s) {
 		ssa_end_procedure_body(proc);
 	}
 
+	gb_for_array(i, m->procs) {
+		ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent);
+	}
+
 
 
 

+ 11 - 7
src/codegen/ssa.cpp

@@ -62,6 +62,8 @@ struct ssaModule {
 	Map<String>         type_names; // Key: Type *
 	Map<ssaDebugInfo *> debug_info; // Key: Unique pointer
 	i32                 global_string_index;
+
+	gbArray(ssaValue *) procs; // NOTE(bill): Procedures to generate
 };
 
 
@@ -405,6 +407,7 @@ void ssa_init_module(ssaModule *m, Checker *c) {
 	map_init(&m->members,    gb_heap_allocator());
 	map_init(&m->debug_info, gb_heap_allocator());
 	map_init(&m->type_names, gb_heap_allocator());
+	gb_array_init(m->procs,  gb_heap_allocator());
 
 	// Default states
 	m->stmt_state_flags = 0;
@@ -468,6 +471,7 @@ void ssa_destroy_module(ssaModule *m) {
 	map_destroy(&m->members);
 	map_destroy(&m->type_names);
 	map_destroy(&m->debug_info);
+	gb_array_free(m->procs);
 	gb_arena_free(&m->arena);
 }
 
@@ -3199,10 +3203,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			                                           proc->module, e, e->type, pd->type, pd->body, name);
 
 			value->Proc.tags = pd->tags;
+			value->Proc.parent = proc;
 
 			ssa_module_add_value(proc->module, e, value);
 			gb_array_append(proc->children, &value->Proc);
-			ssa_build_proc(value, proc);
+			gb_array_append(proc->module->procs, value);
 		} else {
 			// FFI - Foreign function interace
 			String original_name = pd->name->Ident.string;
@@ -3390,10 +3395,10 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			Type *ret_type = proc->type->Proc.results;
 			v = ssa_add_local_generated(proc, ret_type);
 			gb_for_array(i, results) {
-				Type *t = return_type_tuple->variables[i]->type;
-				ssaValue *e = ssa_emit_conv(proc, results[i], t);
-				ssaValue *gep = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, t));
-				ssa_emit_store(proc, gep, e);
+				Entity *e = return_type_tuple->variables[i];
+				ssaValue *res = ssa_emit_conv(proc, results[i], e->type);
+				ssaValue *field = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, e->type));
+				ssa_emit_store(proc, field, res);
 			}
 
 			v = ssa_emit_load(proc, v);
@@ -3410,7 +3415,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			gb_for_array(i, rs->results) {
 				Entity *e = return_type_tuple->variables[i];
 				ssaValue *res = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[i]), e->type);
-				ssaValue *field = ssa_emit_struct_gep(proc, v, i, e->type);
+				ssaValue *field = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, e->type));
 				ssa_emit_store(proc, field, res);
 			}
 			v = ssa_emit_load(proc, v);
@@ -3452,7 +3457,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
 			ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
 			proc->scope_index--;
 
-
 			ssa_emit_jump(proc, done);
 		}
 		gb_array_append(proc->blocks, done);