Browse Source

`#location(..)` and `#call_location`

Ginger Bill 8 years ago
parent
commit
4236519b84
11 changed files with 242 additions and 97 deletions
  1. 13 0
      core/_preload.odin
  2. 86 26
      src/check_expr.cpp
  3. 1 1
      src/check_stmt.cpp
  4. 19 6
      src/checker.cpp
  5. 1 0
      src/entity.cpp
  6. 6 1
      src/integer128.cpp
  7. 52 9
      src/ir.cpp
  8. 2 2
      src/main.cpp
  9. 19 15
      src/parser.cpp
  10. 5 2
      src/string.cpp
  11. 38 35
      src/types.cpp

+ 13 - 0
core/_preload.odin

@@ -184,6 +184,19 @@ type (
 #thread_local var __context: Context;
 #thread_local var __context: Context;
 
 
 
 
+
+type SourceCodeLocation struct {
+	fully_pathed_filename: string,
+	procedure:             string,
+	line, column:          i64,
+}
+
+proc make_source_code_location(file, procedure: string, line, column: i64) -> SourceCodeLocation {
+	return SourceCodeLocation{file, procedure, line, column};
+}
+
+
+
 const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
 const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
 
 
 
 

+ 86 - 26
src/check_expr.cpp

@@ -1062,22 +1062,30 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 		ast_node(p, Field, param);
 		ast_node(p, Field, param);
 		AstNode *type_expr = p->type;
 		AstNode *type_expr = p->type;
 		Type *type = NULL;
 		Type *type = NULL;
-		AstNode *default_value = p->default_value;
+		AstNode *default_value = unparen_expr(p->default_value);
 		ExactValue value = {};
 		ExactValue value = {};
 		bool default_is_nil = false;
 		bool default_is_nil = false;
+		bool default_is_location = false;
 
 
 		if (type_expr == NULL) {
 		if (type_expr == NULL) {
-			Operand o = {};
-			check_expr_or_type(c, &o, default_value);
-			if (is_operand_nil(o)) {
-				default_is_nil = true;
-			} else if (o.mode != Addressing_Constant) {
-				error_node(default_value, "Default parameter must be a constant");
+			if (default_value->kind == AstNode_BasicDirective &&
+			    default_value->BasicDirective.name == "caller_location") {
+				init_preload(c);
+				default_is_location = true;
+				type = t_source_code_location;
 			} else {
 			} else {
-				value = o.value;
-			}
+				Operand o = {};
+				check_expr_or_type(c, &o, default_value);
+				if (is_operand_nil(o)) {
+					default_is_nil = true;
+				} else if (o.mode != Addressing_Constant) {
+					error_node(default_value, "Default parameter must be a constant");
+				} else {
+					value = o.value;
+				}
 
 
-			type = default_type(o.type);
+				type = default_type(o.type);
+			}
 		} else {
 		} else {
 			if (type_expr->kind == AstNode_Ellipsis) {
 			if (type_expr->kind == AstNode_Ellipsis) {
 				type_expr = type_expr->Ellipsis.expr;
 				type_expr = type_expr->Ellipsis.expr;
@@ -1095,14 +1103,22 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 
 
 			if (default_value != NULL) {
 			if (default_value != NULL) {
 				Operand o = {};
 				Operand o = {};
-				check_expr_with_type_hint(c, &o, default_value, type);
-
-				if (is_operand_nil(o)) {
-					default_is_nil = true;
-				} else if (o.mode != Addressing_Constant) {
-					error_node(default_value, "Default parameter must be a constant");
+				if (default_value->kind == AstNode_BasicDirective &&
+				    default_value->BasicDirective.name == "caller_location") {
+					init_preload(c);
+					default_is_location = true;
+					o.type = t_source_code_location;
+					o.mode = Addressing_Value;
 				} else {
 				} else {
-					value = o.value;
+					check_expr_with_type_hint(c, &o, default_value, type);
+
+					if (is_operand_nil(o)) {
+						default_is_nil = true;
+					} else if (o.mode != Addressing_Constant) {
+						error_node(default_value, "Default parameter must be a constant");
+					} else {
+						value = o.value;
+					}
 				}
 				}
 
 
 				check_is_assignable_to(c, &o, type);
 				check_is_assignable_to(c, &o, type);
@@ -1145,6 +1161,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 					                          (p->flags&FieldFlag_using) != 0, false);
 					                          (p->flags&FieldFlag_using) != 0, false);
 					param->Variable.default_value = value;
 					param->Variable.default_value = value;
 					param->Variable.default_is_nil = default_is_nil;
 					param->Variable.default_is_nil = default_is_nil;
+					param->Variable.default_is_location = default_is_location;
 				}
 				}
 				if (p->flags&FieldFlag_no_alias) {
 				if (p->flags&FieldFlag_no_alias) {
 					param->flags |= EntityFlag_NoAlias;
 					param->flags |= EntityFlag_NoAlias;
@@ -3639,7 +3656,10 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		break;
 		break;
 	default:
 	default:
-		check_multi_expr(c, operand, ce->args[0]);
+		if (ce->args.count > 0) {
+			check_multi_expr(c, operand, ce->args[0]);
+		}
+		break;
 	}
 	}
 
 
 	switch (id) {
 	switch (id) {
@@ -3647,6 +3667,32 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_procs[id].name));
 		GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_procs[id].name));
 		break;
 		break;
 
 
+	case BuiltinProc_DIRECTIVE: {
+		ast_node(bd, BasicDirective, ce->proc);
+		String name = bd->name;
+		GB_ASSERT(name == "location");
+		if (ce->args.count > 1) {
+			error_node(ce->args[0], "`#location` expects either 0 or 1 arguments, got %td", ce->args.count);
+		}
+		if (ce->args.count > 0) {
+			AstNode *arg = ce->args[0];
+			Entity *e = NULL;
+			Operand o = {};
+			if (arg->kind == AstNode_Ident) {
+				e = check_ident(c, &o, arg, NULL, NULL, true);
+			} else if (arg->kind == AstNode_SelectorExpr) {
+				e = check_selector(c, &o, arg, NULL);
+			}
+			if (e == NULL) {
+				error_node(ce->args[0], "`#location` expected a valid entity name");
+			}
+		}
+
+
+		operand->type = t_source_code_location;
+		operand->mode = Addressing_Value;
+	} break;
+
 	case BuiltinProc_len:
 	case BuiltinProc_len:
 	case BuiltinProc_cap: {
 	case BuiltinProc_cap: {
 		// proc len(Type) -> int
 		// proc len(Type) -> int
@@ -4822,11 +4868,9 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 			}
 			}
 
 
 			GB_ASSERT(e->kind == Entity_Variable);
 			GB_ASSERT(e->kind == Entity_Variable);
-			if (e->Variable.default_value.kind != ExactValue_Invalid) {
-				param_count_excluding_defaults--;
-				continue;
-			}
-			if (e->Variable.default_is_nil) {
+			if (e->Variable.default_value.kind != ExactValue_Invalid ||
+			    e->Variable.default_is_nil ||
+			    e->Variable.default_is_location) {
 				param_count_excluding_defaults--;
 				param_count_excluding_defaults--;
 				continue;
 				continue;
 			}
 			}
@@ -5214,7 +5258,19 @@ Entity *find_using_index_expr(Type *t) {
 ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
 	GB_ASSERT(call->kind == AstNode_CallExpr);
 	GB_ASSERT(call->kind == AstNode_CallExpr);
 	ast_node(ce, CallExpr, call);
 	ast_node(ce, CallExpr, call);
-	check_expr_or_type(c, operand, ce->proc);
+	if (ce->proc != NULL &&
+	    ce->proc->kind == AstNode_BasicDirective) {
+		ast_node(bd, BasicDirective, ce->proc);
+		String name = bd->name;
+		GB_ASSERT(name == "location");
+		operand->mode = Addressing_Builtin;
+		operand->builtin_id = BuiltinProc_DIRECTIVE;
+		operand->expr = ce->proc;
+		operand->type = t_invalid;
+		add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value);
+	} else {
+		check_expr_or_type(c, operand, ce->proc);
+	}
 
 
 	if (ce->args.count > 0) {
 	if (ce->args.count > 0) {
 		bool fail = false;
 		bool fail = false;
@@ -5508,9 +5564,13 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
 				o->type = t_untyped_string;
 				o->type = t_untyped_string;
 				o->value = exact_value_string(c->context.proc_name);
 				o->value = exact_value_string(c->context.proc_name);
 			}
 			}
-
+		} else if (bd->name == "caller_location") {
+			init_preload(c);
+			error_node(node, "#caller_location may only be used as a default argument parameter");
+			o->type = t_source_code_location;
+			o->mode = Addressing_Value;
 		} else {
 		} else {
-			GB_PANIC("Unknown basic basic directive");
+			GB_PANIC("Unknown basic directive");
 		}
 		}
 		o->mode = Addressing_Constant;
 		o->mode = Addressing_Constant;
 	case_end;
 	case_end;

+ 1 - 1
src/check_stmt.cpp

@@ -1161,7 +1161,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
 					}
 					}
 
 
 
 
-					TokenKind op = {};
+					TokenKind op = Token_Invalid;
 
 
 					Operand a = lhs;
 					Operand a = lhs;
 					Operand b = rhs;
 					Operand b = rhs;

+ 19 - 6
src/checker.cpp

@@ -65,9 +65,11 @@ enum BuiltinProcId {
 
 
 	BuiltinProc_transmute,
 	BuiltinProc_transmute,
 
 
-	BuiltinProc_Count,
+	BuiltinProc_DIRECTIVE,
+
+	BuiltinProc_COUNT,
 };
 };
-gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
+gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT(""),                 0, false, Expr_Stmt},
 	{STR_LIT(""),                 0, false, Expr_Stmt},
 
 
 	{STR_LIT("len"),              1, false, Expr_Expr},
 	{STR_LIT("len"),              1, false, Expr_Expr},
@@ -110,6 +112,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("clamp"),            3, false, Expr_Expr},
 	{STR_LIT("clamp"),            3, false, Expr_Expr},
 
 
 	{STR_LIT("transmute"),        2, false, Expr_Expr},
 	{STR_LIT("transmute"),        2, false, Expr_Expr},
+
+	{STR_LIT(""),                 0, true,  Expr_Expr}, // DIRECTIVE
 };
 };
 
 
 
 
@@ -660,9 +664,12 @@ void init_universal_scope(void) {
 // Builtin Procedures
 // Builtin Procedures
 	for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
 	for (isize i = 0; i < gb_count_of(builtin_procs); i++) {
 		BuiltinProcId id = cast(BuiltinProcId)i;
 		BuiltinProcId id = cast(BuiltinProcId)i;
-		Entity *entity = alloc_entity(a, Entity_Builtin, NULL, make_token_ident(builtin_procs[i].name), t_invalid);
-		entity->Builtin.id = id;
-		add_global_entity(entity);
+		String name = builtin_procs[i].name;
+		if (name != "") {
+			Entity *entity = alloc_entity(a, Entity_Builtin, NULL, make_token_ident(name), t_invalid);
+			entity->Builtin.id = id;
+			add_global_entity(entity);
+		}
 	}
 	}
 
 
 
 
@@ -1284,6 +1291,12 @@ void init_preload(Checker *c) {
 		t_context_ptr = make_type_pointer(c->allocator, t_context);
 		t_context_ptr = make_type_pointer(c->allocator, t_context);
 	}
 	}
 
 
+	if (t_source_code_location == NULL) {
+		Entity *e = find_core_entity(c, str_lit("SourceCodeLocation"));
+		t_source_code_location = e->type;
+		t_source_code_location_ptr = make_type_pointer(c->allocator, t_allocator);
+	}
+
 	if (t_map_key == NULL) {
 	if (t_map_key == NULL) {
 		Entity *e = find_core_entity(c, str_lit("__MapKey"));
 		Entity *e = find_core_entity(c, str_lit("__MapKey"));
 		t_map_key = e->type;
 		t_map_key = e->type;
@@ -1755,7 +1768,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
 
 
 
 
 void check_all_global_entities(Checker *c) {
 void check_all_global_entities(Checker *c) {
-	Scope *prev_file = {};
+	Scope *prev_file = NULL;
 
 
 	for_array(i, c->info.entities.entries) {
 	for_array(i, c->info.entities.entries) {
 		auto *entry = &c->info.entities.entries[i];
 		auto *entry = &c->info.entities.entries[i];

+ 1 - 0
src/entity.cpp

@@ -86,6 +86,7 @@ struct Entity {
 			i32        field_src_index;
 			i32        field_src_index;
 			ExactValue default_value;
 			ExactValue default_value;
 			bool       default_is_nil;
 			bool       default_is_nil;
+			bool       default_is_location;
 			bool       is_immutable;
 			bool       is_immutable;
 			bool       is_thread_local;
 			bool       is_thread_local;
 			bool       is_foreign;
 			bool       is_foreign;

+ 6 - 1
src/integer128.cpp

@@ -152,7 +152,12 @@ u64 bit128__digit_value(Rune r) {
 	return 16; // NOTE(bill): Larger than highest possible
 	return 16; // NOTE(bill): Larger than highest possible
 }
 }
 
 
-u128 u128_lo_hi(u64 lo, u64 hi) { return u128{lo, hi}; }
+u128 u128_lo_hi(u64 lo, u64 hi) {
+	u128 r = {};
+	r.lo = lo;
+	r.hi = hi;
+	return r;
+}
 u128 u128_from_u32(u32 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_u32(u32 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_u64(u64 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_u64(u64 u)       { return u128_lo_hi(cast(u64)u, 0); }
 u128 u128_from_i64(i64 u)       { return u128_lo_hi(cast(u64)u, u < 0 ? -1 : 0); }
 u128 u128_from_i64(i64 u)       { return u128_lo_hi(cast(u64)u, u < 0 ? -1 : 0); }

+ 52 - 9
src/ir.cpp

@@ -3522,7 +3522,8 @@ irBranchBlocks ir_lookup_branch_blocks(irProcedure *proc, AstNode *ident) {
 	}
 	}
 
 
 	GB_PANIC("Unreachable");
 	GB_PANIC("Unreachable");
-	return irBranchBlocks{};
+	irBranchBlocks empty = {};
+	return empty;
 }
 }
 
 
 
 
@@ -3628,10 +3629,46 @@ bool is_double_pointer(Type *t) {
 	return is_type_pointer(td);
 	return is_type_pointer(td);
 }
 }
 
 
-irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, Entity *e) {
+irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos) {
+	gbAllocator a = proc->module->allocator;
+	irValue **args = gb_alloc_array(a, irValue *, 4);
+	args[0] = ir_const_string(a, pos.file);
+	args[1] = ir_const_string(a, procedure);
+	args[2] = ir_const_i64(a, pos.line);
+	args[3] = ir_const_i64(a, pos.column);
+	return ir_emit_global_call(proc, "make_source_code_location", args, 4);
+}
+
+irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv, BuiltinProcId id) {
 	ast_node(ce, CallExpr, expr);
 	ast_node(ce, CallExpr, expr);
 
 
-	switch (e->Builtin.id) {
+	switch (id) {
+	case BuiltinProc_DIRECTIVE: {
+		ast_node(bd, BasicDirective, ce->proc);
+		String name = bd->name;
+		GB_ASSERT(name == "location");
+		String procedure = proc->entity->token.string;
+		TokenPos pos = ast_node_token(ce->proc).pos;
+		if (ce->args.count > 0) {
+			AstNode *ident = ce->args[0];;
+
+			while (ident->kind == AstNode_SelectorExpr) {
+				ident = ident->SelectorExpr.selector;
+			}
+			Entity *e = entity_of_ident(proc->module->info, ident);
+			GB_ASSERT(e != NULL);
+
+			if (e->parent_proc_decl != NULL) {
+				procedure = e->parent_proc_decl->entities[0]->token.string;
+			} else {
+				procedure = str_lit("");
+			}
+			pos = e->token.pos;
+
+		}
+		return ir_emit_source_code_location(proc, procedure, pos);
+	} break;
+
 	case BuiltinProc_type_info: {
 	case BuiltinProc_type_info: {
 		Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
 		Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
 		return ir_type_info(proc, t);
 		return ir_type_info(proc, t);
@@ -4573,7 +4610,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 
 
 
 	case_ast_node(ce, CallExpr, expr);
 	case_ast_node(ce, CallExpr, expr);
-		if (type_and_value_of_expr(proc->module->info, ce->proc).mode == Addressing_Type) {
+		TypeAndValue proc_tv = type_and_value_of_expr(proc->module->info, ce->proc);
+		AddressingMode proc_mode = proc_tv.mode;
+		if (proc_mode == Addressing_Type) {
 			GB_ASSERT(ce->args.count == 1);
 			GB_ASSERT(ce->args.count == 1);
 			irValue *x = ir_build_expr(proc, ce->args[0]);
 			irValue *x = ir_build_expr(proc, ce->args[0]);
 			irValue *y = ir_emit_conv(proc, x, tv.type);
 			irValue *y = ir_emit_conv(proc, x, tv.type);
@@ -4581,11 +4620,10 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 		}
 		}
 
 
 		AstNode *p = unparen_expr(ce->proc);
 		AstNode *p = unparen_expr(ce->proc);
-		if (p->kind == AstNode_Ident) {
+		if (proc_mode == Addressing_Builtin) {
 			Entity *e = entity_of_ident(proc->module->info, p);
 			Entity *e = entity_of_ident(proc->module->info, p);
-			if (e != NULL && e->kind == Entity_Builtin) {
-				return ir_build_builtin_proc(proc, expr, tv, e);
-			}
+			BuiltinProcId id = cast(BuiltinProcId)(e != NULL ? e->Builtin.id : BuiltinProc_DIRECTIVE);
+			return ir_build_builtin_proc(proc, expr, tv, id);
 		}
 		}
 
 
 		// NOTE(bill): Regular call
 		// NOTE(bill): Regular call
@@ -4664,6 +4702,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 		TypeTuple *pt = &type->params->Tuple;
 		TypeTuple *pt = &type->params->Tuple;
 
 
 		if (arg_count < type->param_count) {
 		if (arg_count < type->param_count) {
+			String procedure = proc->entity->token.string;
+			TokenPos pos = ast_node_token(ce->proc).pos;
+
 			isize end = type->param_count;
 			isize end = type->param_count;
 			if (variadic) {
 			if (variadic) {
 				end--;
 				end--;
@@ -4673,6 +4714,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 				GB_ASSERT(e->kind == Entity_Variable);
 				GB_ASSERT(e->kind == Entity_Variable);
 				if (e->Variable.default_value.kind != ExactValue_Invalid) {
 				if (e->Variable.default_value.kind != ExactValue_Invalid) {
 					args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
 					args[arg_index++] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
+				} else if (e->Variable.default_is_location) {
+					args[arg_index++] = ir_emit_source_code_location(proc, procedure, pos);
 				} else {
 				} else {
 					args[arg_index++] = ir_value_nil(proc->module->allocator, e->type);
 					args[arg_index++] = ir_value_nil(proc->module->allocator, e->type);
 				}
 				}
@@ -6459,7 +6502,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 				irValue *cond = v_false;
 				irValue *cond = v_false;
 				if (is_ast_node_a_range(expr)) {
 				if (is_ast_node_a_range(expr)) {
 					ast_node(ie, BinaryExpr, expr);
 					ast_node(ie, BinaryExpr, expr);
-					TokenKind op = {};
+					TokenKind op = Token_Invalid;
 					switch (ie->op.kind) {
 					switch (ie->op.kind) {
 					case Token_Ellipsis:   op = Token_LtEq; break;
 					case Token_Ellipsis:   op = Token_LtEq; break;
 					case Token_HalfClosed: op = Token_Lt;   break;
 					case Token_HalfClosed: op = Token_Lt;   break;

+ 2 - 2
src/main.cpp

@@ -1,4 +1,4 @@
-#define USE_CUSTOM_BACKEND false
+#define USE_CUSTOM_BACKEND 0
 
 
 #include "common.cpp"
 #include "common.cpp"
 #include "timings.cpp"
 #include "timings.cpp"
@@ -205,7 +205,7 @@ int main(int argc, char **argv) {
 
 
 
 
 #endif
 #endif
-#if USE_CUSTOM_BACKEND
+#if defined(USE_CUSTOM_BACKEND) && USE_CUSTOM_BACKEND
 	if (global_error_collector.count != 0) {
 	if (global_error_collector.count != 0) {
 		return 1;
 		return 1;
 	}
 	}

+ 19 - 15
src/parser.cpp

@@ -114,10 +114,9 @@ enum StmtAllowFlag {
 
 
 
 
 
 
-Array<AstNode *> make_ast_node_array(AstFile *f) {
+Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
 	Array<AstNode *> a;
 	Array<AstNode *> a;
-	// array_init(&a, gb_arena_allocator(&f->arena));
-	array_init(&a, heap_allocator());
+	array_init(&a, heap_allocator(), init_capacity);
 	return a;
 	return a;
 }
 }
 
 
@@ -2029,8 +2028,9 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *link_name, ProcCallingConven
 
 
 Array<AstNode *> parse_lhs_expr_list(AstFile *f);
 Array<AstNode *> parse_lhs_expr_list(AstFile *f);
 Array<AstNode *> parse_rhs_expr_list(AstFile *f);
 Array<AstNode *> parse_rhs_expr_list(AstFile *f);
-AstNode *    parse_simple_stmt  (AstFile *f, StmtAllowFlag flags);
-AstNode *    parse_type         (AstFile *f);
+AstNode *        parse_simple_stmt  (AstFile *f, StmtAllowFlag flags);
+AstNode *        parse_type         (AstFile *f);
+AstNode *        parse_call_expr    (AstFile *f, AstNode *operand);
 
 
 AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
 AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) {
 	if (statement == NULL) {
 	if (statement == NULL) {
@@ -2117,7 +2117,10 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
 		} else if (name.string == "file") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "file") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
 		} else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
-		// } else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false));
+		} else if (name.string == "caller_location") { return ast_basic_directive(f, token, name.string);
+		} else if (name.string == "location") {
+			AstNode *tag = ast_basic_directive(f, token, name.string);
+			return parse_call_expr(f, tag);
 		} else {
 		} else {
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 			operand = ast_tag_expr(f, token, name, parse_expr(f, false));
 		}
 		}
@@ -2613,7 +2616,7 @@ AstNode *parse_gen_decl(AstFile *f, Token token, ParseSpecFunc *func) {
 			expect_semicolon(f, NULL);
 			expect_semicolon(f, NULL);
 		}
 		}
 	} else {
 	} else {
-		array_init(&specs, heap_allocator(), 1);
+		specs = make_ast_node_array(f, 1);
 		AstNode *spec = func(f, token);
 		AstNode *spec = func(f, token);
 		array_add(&specs, spec);
 		array_add(&specs, spec);
 	}
 	}
@@ -2942,9 +2945,8 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
 			AstNode *expr = parse_expr(f, false);
 			AstNode *expr = parse_expr(f, false);
 			f->allow_range = prev_allow_range;
 			f->allow_range = prev_allow_range;
 
 
-			Array<AstNode *> rhs = {};
-			array_init_count(&rhs, heap_allocator(), 1);
-			rhs[0] = expr;
+			Array<AstNode *> rhs = make_ast_node_array(f, 1);
+			array_add(&rhs, expr);
 
 
 			return ast_assign_stmt(f, token, lhs, rhs);
 			return ast_assign_stmt(f, token, lhs, rhs);
 		}
 		}
@@ -3031,8 +3033,8 @@ AstNode *parse_results(AstFile *f) {
 }
 }
 
 
 AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
 AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
-	AstNode *params = {};
-	AstNode *results = {};
+	AstNode *params = NULL;
+	AstNode *results = NULL;
 
 
 	expect_token(f, Token_OpenParen);
 	expect_token(f, Token_OpenParen);
 	params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
 	params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
@@ -3166,8 +3168,7 @@ struct AstNodeAndFlags {
 };
 };
 
 
 Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list, bool ignore_flags) {
 Array<AstNode *> convert_to_ident_list(AstFile *f, Array<AstNodeAndFlags> list, bool ignore_flags) {
-	Array<AstNode *> idents = {};
-	array_init(&idents, heap_allocator(), list.count);
+	Array<AstNode *> idents = make_ast_node_array(f, list.count);
 	// Convert to ident list
 	// Convert to ident list
 	for_array(i, list) {
 	for_array(i, list) {
 		AstNode *ident = list[i].node;
 		AstNode *ident = list[i].node;
@@ -3211,7 +3212,10 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
 	Token start_token = f->curr_token;
 	Token start_token = f->curr_token;
 
 
 	Array<AstNode *> params = make_ast_node_array(f);
 	Array<AstNode *> params = make_ast_node_array(f);
-	Array<AstNodeAndFlags> list = {}; array_init(&list, heap_allocator()); // LEAK(bill):
+
+	Array<AstNodeAndFlags> list = {}; array_init(&list, heap_allocator());
+	defer (array_free(&list));
+
 	isize total_name_count = 0;
 	isize total_name_count = 0;
 	bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
 	bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
 	bool is_procedure = allowed_flags == FieldFlag_Signature;
 	bool is_procedure = allowed_flags == FieldFlag_Signature;

+ 5 - 2
src/string.cpp

@@ -25,8 +25,11 @@ struct String {
 // NOTE(bill): used for printf style arguments
 // NOTE(bill): used for printf style arguments
 #define LIT(x) ((int)(x).len), (x).text
 #define LIT(x) ((int)(x).len), (x).text
 #define STR_LIT(c_str) {cast(u8 *)c_str, gb_size_of(c_str)-1}
 #define STR_LIT(c_str) {cast(u8 *)c_str, gb_size_of(c_str)-1}
-#define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1}
-
+#if defined(GB_COMPILER_MSVC) && _MSC_VER < 1700
+	#define str_lit(c_str) make_string(cast(u8 *)c_str, gb_size_of(c_str)-1)
+#else
+	#define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1}
+#endif
 
 
 // NOTE(bill): String16 is only used for Windows due to its file directories
 // NOTE(bill): String16 is only used for Windows due to its file directories
 struct String16 {
 struct String16 {

+ 38 - 35
src/types.cpp

@@ -321,35 +321,35 @@ gb_global Type *t_string_slice = NULL;
 
 
 
 
 // Type generated for the "preload" file
 // Type generated for the "preload" file
-gb_global Type *t_type_info                = NULL;
-gb_global Type *t_type_info_record         = NULL;
-gb_global Type *t_type_info_enum_value     = NULL;
-gb_global Type *t_type_info_ptr            = NULL;
-gb_global Type *t_type_info_record_ptr     = NULL;
-gb_global Type *t_type_info_enum_value_ptr = NULL;
-
-gb_global Type *t_type_info_named         = NULL;
-gb_global Type *t_type_info_integer       = NULL;
-gb_global Type *t_type_info_rune          = NULL;
-gb_global Type *t_type_info_float         = NULL;
-gb_global Type *t_type_info_complex       = NULL;
-gb_global Type *t_type_info_any           = NULL;
-gb_global Type *t_type_info_string        = NULL;
-gb_global Type *t_type_info_boolean       = NULL;
-gb_global Type *t_type_info_pointer       = NULL;
-gb_global Type *t_type_info_atomic        = NULL;
-gb_global Type *t_type_info_procedure     = NULL;
-gb_global Type *t_type_info_array         = NULL;
-gb_global Type *t_type_info_dynamic_array = NULL;
-gb_global Type *t_type_info_slice         = NULL;
-gb_global Type *t_type_info_vector        = NULL;
-gb_global Type *t_type_info_tuple         = NULL;
-gb_global Type *t_type_info_struct        = NULL;
-gb_global Type *t_type_info_raw_union     = NULL;
-gb_global Type *t_type_info_union         = NULL;
-gb_global Type *t_type_info_enum          = NULL;
-gb_global Type *t_type_info_map           = NULL;
-gb_global Type *t_type_info_bit_field     = NULL;
+gb_global Type *t_type_info                   = NULL;
+gb_global Type *t_type_info_record            = NULL;
+gb_global Type *t_type_info_enum_value        = NULL;
+gb_global Type *t_type_info_ptr               = NULL;
+gb_global Type *t_type_info_record_ptr        = NULL;
+gb_global Type *t_type_info_enum_value_ptr    = NULL;
+
+gb_global Type *t_type_info_named             = NULL;
+gb_global Type *t_type_info_integer           = NULL;
+gb_global Type *t_type_info_rune              = NULL;
+gb_global Type *t_type_info_float             = NULL;
+gb_global Type *t_type_info_complex           = NULL;
+gb_global Type *t_type_info_any               = NULL;
+gb_global Type *t_type_info_string            = NULL;
+gb_global Type *t_type_info_boolean           = NULL;
+gb_global Type *t_type_info_pointer           = NULL;
+gb_global Type *t_type_info_atomic            = NULL;
+gb_global Type *t_type_info_procedure         = NULL;
+gb_global Type *t_type_info_array             = NULL;
+gb_global Type *t_type_info_dynamic_array     = NULL;
+gb_global Type *t_type_info_slice             = NULL;
+gb_global Type *t_type_info_vector            = NULL;
+gb_global Type *t_type_info_tuple             = NULL;
+gb_global Type *t_type_info_struct            = NULL;
+gb_global Type *t_type_info_raw_union         = NULL;
+gb_global Type *t_type_info_union             = NULL;
+gb_global Type *t_type_info_enum              = NULL;
+gb_global Type *t_type_info_map               = NULL;
+gb_global Type *t_type_info_bit_field         = NULL;
 
 
 gb_global Type *t_type_info_named_ptr         = NULL;
 gb_global Type *t_type_info_named_ptr         = NULL;
 gb_global Type *t_type_info_integer_ptr       = NULL;
 gb_global Type *t_type_info_integer_ptr       = NULL;
@@ -375,13 +375,16 @@ gb_global Type *t_type_info_enum_ptr          = NULL;
 gb_global Type *t_type_info_map_ptr           = NULL;
 gb_global Type *t_type_info_map_ptr           = NULL;
 gb_global Type *t_type_info_bit_field_ptr     = NULL;
 gb_global Type *t_type_info_bit_field_ptr     = NULL;
 
 
-gb_global Type *t_allocator            = NULL;
-gb_global Type *t_allocator_ptr        = NULL;
-gb_global Type *t_context              = NULL;
-gb_global Type *t_context_ptr          = NULL;
+gb_global Type *t_allocator                   = NULL;
+gb_global Type *t_allocator_ptr               = NULL;
+gb_global Type *t_context                     = NULL;
+gb_global Type *t_context_ptr                 = NULL;
 
 
-gb_global Type *t_map_key               = NULL;
-gb_global Type *t_map_header            = NULL;
+gb_global Type *t_source_code_location        = NULL;
+gb_global Type *t_source_code_location_ptr    = NULL;
+
+gb_global Type *t_map_key                     = NULL;
+gb_global Type *t_map_header                  = NULL;