Browse Source

Make `ODIN_BUILD_MODE` a enum type

gingerBill 3 years ago
parent
commit
6c48670819

+ 13 - 0
core/runtime/core.odin

@@ -386,6 +386,19 @@ Raw_Cstring :: struct {
 }
 
 
+/*
+	// Defined internally by the compiler
+	Odin_Build_Mode_Type :: enum int {
+		Executable,
+		Dynamic,
+		Object,
+		Assembly,
+		LLVM_IR,
+	}
+*/
+Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
+
+
 /////////////////////////////
 // Init Startup Procedures //
 /////////////////////////////

+ 1 - 1
core/runtime/entry_unix.odin

@@ -4,7 +4,7 @@ package runtime
 
 import "core:intrinsics"
 
-when ODIN_BUILD_MODE == "dynamic" {
+when ODIN_BUILD_MODE == .Dynamic {
 	@(link_name="_odin_entry_point", linkage="strong", require, link_section=".init")
 	_odin_entry_point :: proc "c" () {
 		context = default_context()

+ 1 - 1
core/runtime/entry_windows.odin

@@ -4,7 +4,7 @@ package runtime
 
 import "core:intrinsics"
 
-when ODIN_BUILD_MODE == "dynamic" {
+when ODIN_BUILD_MODE == .Dynamic {
 	@(link_name="DllMain", linkage="strong", require)
 	DllMain :: proc "stdcall" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
 		context = default_context()

+ 1 - 1
core/runtime/internal.odin

@@ -8,7 +8,7 @@ IS_WASM :: ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64"
 @(private)
 RUNTIME_LINKAGE :: "strong" when (
 	(ODIN_USE_SEPARATE_MODULES || 
-	ODIN_BUILD_MODE == "dynamic" || 
+	ODIN_BUILD_MODE == .Dynamic ||
 	!ODIN_NO_CRT) &&
 	!IS_WASM) else "internal"
 RUNTIME_REQUIRE :: true

+ 3 - 20
src/build_settings.cpp

@@ -119,6 +119,8 @@ enum BuildModeKind {
 	BuildMode_Object,
 	BuildMode_Assembly,
 	BuildMode_LLVM_IR,
+
+	BuildMode_COUNT,
 };
 
 enum CommandKind : u32 {
@@ -172,10 +174,9 @@ struct BuildContext {
 	String ODIN_VENDOR;  // compiler vendor
 	String ODIN_VERSION; // compiler version
 	String ODIN_ROOT;    // Odin ROOT
-	String ODIN_BUILD_MODE;
 	bool   ODIN_DEBUG;   // Odin in debug mode
 	bool   ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not
-	bool   ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
+bool   ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing)
 
 	TargetEndianKind endian_kind;
 
@@ -855,24 +856,6 @@ void init_build_context(TargetMetrics *cross_target) {
 	bc->ODIN_VENDOR  = str_lit("odin");
 	bc->ODIN_VERSION = ODIN_VERSION;
 	bc->ODIN_ROOT    = odin_root_dir();
-	switch (bc->build_mode) {
-	default:
-	case BuildMode_Executable:
-		bc->ODIN_BUILD_MODE = str_lit("executable");
-		break;
-	case BuildMode_DynamicLibrary:
-		bc->ODIN_BUILD_MODE = str_lit("dynamic");
-		break;
-	case BuildMode_Object:
-		bc->ODIN_BUILD_MODE = str_lit("object");
-		break;
-	case BuildMode_Assembly:
-		bc->ODIN_BUILD_MODE = str_lit("assembly");
-		break;
-	case BuildMode_LLVM_IR:
-		bc->ODIN_BUILD_MODE = str_lit("llvm-ir");
-		break;
-	}
 	
 	bc->copy_file_contents = true;
 

+ 62 - 50
src/check_expr.cpp

@@ -119,6 +119,58 @@ void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name
 void check_or_else_expr_no_value_error(CheckerContext *c, String const &name, Operand const &x, Type *type_hint);
 void check_or_return_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_);
 
+
+void check_did_you_mean_print(DidYouMeanAnswers *d, char const *prefix = "") {
+	auto results = did_you_mean_results(d);
+	if (results.count != 0) {
+		error_line("\tSuggestion: Did you mean?\n");
+		for_array(i, results) {
+			String const &target = results[i].target;
+			error_line("\t\t%s%.*s\n", prefix, LIT(target));
+			// error_line("\t\t%.*s %td\n", LIT(target), results[i].distance);
+		}
+	}
+}
+
+void check_did_you_mean_type(String const &name, Array<Entity *> const &fields, char const *prefix = "") {
+	ERROR_BLOCK();
+
+	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name);
+	defer (did_you_mean_destroy(&d));
+
+	for_array(i, fields) {
+		did_you_mean_append(&d, fields[i]->token.string);
+	}
+	check_did_you_mean_print(&d, prefix);
+}
+
+void check_did_you_mean_type(String const &name, Slice<Entity *> const &fields, char const *prefix = "") {
+	ERROR_BLOCK();
+
+	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name);
+	defer (did_you_mean_destroy(&d));
+
+	for_array(i, fields) {
+		did_you_mean_append(&d, fields[i]->token.string);
+	}
+	check_did_you_mean_print(&d, prefix);
+}
+
+void check_did_you_mean_scope(String const &name, Scope *scope, char const *prefix = "") {
+	ERROR_BLOCK();
+
+	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.entries.count, name);
+	defer (did_you_mean_destroy(&d));
+
+	mutex_lock(&scope->mutex);
+	for_array(i, scope->elements.entries) {
+		Entity *e = scope->elements.entries[i].value;
+		did_you_mean_append(&d, e->token.string);
+	}
+	mutex_unlock(&scope->mutex);
+	check_did_you_mean_print(&d, prefix);
+}
+
 Entity *entity_from_expr(Ast *expr) {
 	expr = unparen_expr(expr);
 	switch (expr->kind) {
@@ -3361,7 +3413,17 @@ void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_typ
 			}
 		}
 	}
+	ERROR_BLOCK();
+
 	error(operand->expr, "Cannot convert untyped value '%s' to '%s' from '%s'%s", expr_str, type_str, from_type_str, extra_text);
+	if (operand->value.kind == ExactValue_String) {
+		String key = operand->value.value_string;
+		if (is_type_string(operand->type) && is_type_enum(target_type)) {
+			gb_printf_err("HERE!\n");
+			Type *et = base_type(target_type);
+			check_did_you_mean_type(key, et->Enum.fields, ".");
+		}
+	}
 
 	gb_string_free(from_type_str);
 	gb_string_free(type_str);
@@ -3979,56 +4041,6 @@ ExactValue get_constant_field(CheckerContext *c, Operand const *operand, Selecti
 	if (success_) *success_ = true;
 	return empty_exact_value;
 }
-void check_did_you_mean_print(DidYouMeanAnswers *d) {
-	auto results = did_you_mean_results(d);
-	if (results.count != 0) {
-		error_line("\tSuggestion: Did you mean?\n");
-		for_array(i, results) {
-			String const &target = results[i].target;
-			error_line("\t\t%.*s\n", LIT(target));
-			// error_line("\t\t%.*s %td\n", LIT(target), results[i].distance);
-		}
-	}
-}
-
-void check_did_you_mean_type(String const &name, Array<Entity *> const &fields) {
-	ERROR_BLOCK();
-	
-	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name);
-	defer (did_you_mean_destroy(&d));
-
-	for_array(i, fields) {
-		did_you_mean_append(&d, fields[i]->token.string);
-	}
-	check_did_you_mean_print(&d);
-}
-
-void check_did_you_mean_type(String const &name, Slice<Entity *> const &fields) {
-	ERROR_BLOCK();
-	
-	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name);
-	defer (did_you_mean_destroy(&d));
-
-	for_array(i, fields) {
-		did_you_mean_append(&d, fields[i]->token.string);
-	}
-	check_did_you_mean_print(&d);
-}
-
-void check_did_you_mean_scope(String const &name, Scope *scope) {
-	ERROR_BLOCK();
-	
-	DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), scope->elements.entries.count, name);
-	defer (did_you_mean_destroy(&d));
-
-	mutex_lock(&scope->mutex);
-	for_array(i, scope->elements.entries) {
-		Entity *e = scope->elements.entries[i].value;
-		did_you_mean_append(&d, e->token.string);
-	}
-	mutex_unlock(&scope->mutex);
-	check_did_you_mean_print(&d);
-}
 
 Type *determine_swizzle_array_type(Type *original_type, Type *type_hint, isize new_count) {
 	Type *array_type = base_type(type_deref(original_type));

+ 63 - 1
src/checker.cpp

@@ -780,6 +780,54 @@ AstPackage *create_builtin_package(char const *name) {
 	return pkg;
 }
 
+struct GlobalEnumValue {
+	char const *name;
+	i64 value;
+};
+
+Slice<Entity *> add_global_enum_type(String const &type_name, GlobalEnumValue *values, isize value_count) {
+	Scope *scope = create_scope(nullptr, builtin_pkg->scope);
+	Entity *e = alloc_entity_type_name(scope, make_token_ident(type_name), nullptr, EntityState_Resolved);
+
+	Type *enum_type = alloc_type_enum();
+	Type *named_type = alloc_type_named(type_name, enum_type, e);
+	set_base_type(named_type, enum_type);
+	enum_type->Enum.base_type = t_int;
+	enum_type->Enum.scope = scope;
+
+	auto fields = array_make<Entity *>(permanent_allocator(), value_count);
+	for (isize i = 0; i < value_count; i++) {
+		i64 value = values[i].value;
+		Entity *e = alloc_entity_constant(scope, make_token_ident(values[i].name), named_type, exact_value_i64(value));
+		e->flags |= EntityFlag_Visited;
+		e->state = EntityState_Resolved;
+		fields[i] = e;
+
+		Entity *ie = scope_insert(scope, e);
+		GB_ASSERT(ie == nullptr);
+	}
+
+
+	enum_type->Enum.fields = fields;
+	enum_type->Enum.min_value_index = 0;
+	enum_type->Enum.max_value_index = value_count-1;
+	enum_type->Enum.min_value = &enum_type->Enum.fields[enum_type->Enum.min_value_index]->Constant.value;
+	enum_type->Enum.max_value = &enum_type->Enum.fields[enum_type->Enum.max_value_index]->Constant.value;
+
+	return slice_from_array(fields);
+}
+void add_global_enum_constant(Slice<Entity *> const &fields, char const *name, i64 value) {
+	for (Entity *field : fields) {
+		GB_ASSERT(field->kind == Entity_Constant);
+		if (value == exact_value_to_i64(field->Constant.value)) {
+			add_global_constant(name, field->type, field->Constant.value);
+			return;
+		}
+	}
+	GB_PANIC("Unfound enum value for global constant: %s %lld", name, cast(long long)value);
+}
+
+
 void init_universal(void) {
 	BuildContext *bc = &build_context;
 
@@ -815,7 +863,21 @@ void init_universal(void) {
 	add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION);
 	add_global_string_constant("ODIN_ROOT",    bc->ODIN_ROOT);
 	
-	add_global_string_constant("ODIN_BUILD_MODE", bc->ODIN_BUILD_MODE);
+	{
+		GlobalEnumValue values[BuildMode_COUNT] = {
+			{"Executable", BuildMode_Executable},
+			{"Dynamic",    BuildMode_DynamicLibrary},
+			{"Object",     BuildMode_Object},
+			{"Assembly",   BuildMode_Assembly},
+			{"LLVM_IR",    BuildMode_LLVM_IR},
+		};
+
+		auto fields = add_global_enum_type(str_lit("Odin_Build_Mode_Type"), values, gb_count_of(values));
+		add_global_enum_constant(fields, "ODIN_BUILD_MODE", bc->build_mode);
+	}
+
+	// add_global_string_constant("ODIN_BUILD_MODE", bc->ODIN_BUILD_MODE);
+
 	add_global_bool_constant("ODIN_DEBUG",                    bc->ODIN_DEBUG);
 	add_global_bool_constant("ODIN_DISABLE_ASSERT",           bc->ODIN_DISABLE_ASSERT);
 	add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR);