Pārlūkot izejas kodu

Merge pull request #4116 from Kelimion/article

Add table-driven (in)definite article to some errors.
Jeroen van Rijn 1 gadu atpakaļ
vecāks
revīzija
a8bc6f08a9
2 mainītis faili ar 44 papildinājumiem un 7 dzēšanām
  1. 15 7
      src/check_expr.cpp
  2. 29 0
      src/error.cpp

+ 15 - 7
src/check_expr.cpp

@@ -1071,16 +1071,19 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
 		return;
 	}
 
+	// Grab definite or indefinite article matching `context_name`, or "" if not found.
+	String article = error_article(context_name);
+
 	if (is_type_untyped(operand->type)) {
 		Type *target_type = type;
 		if (type == nullptr || is_type_any(type)) {
 			if (type == nullptr && is_type_untyped_uninit(operand->type)) {
-				error(operand->expr, "Use of --- in %.*s", LIT(context_name));
+				error(operand->expr, "Use of --- in %.*s%.*s", LIT(article), LIT(context_name));
 				operand->mode = Addressing_Invalid;
 				return;
 			}
 			if (type == nullptr && is_type_untyped_nil(operand->type)) {
-				error(operand->expr, "Use of untyped nil in %.*s", LIT(context_name));
+				error(operand->expr, "Use of untyped nil in %.*s%.*s", LIT(article), LIT(context_name));
 				operand->mode = Addressing_Invalid;
 				return;
 			}
@@ -1135,9 +1138,10 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
 
 			// TODO(bill): is this a good enough error message?
 			error(operand->expr,
-			      "Cannot assign overloaded procedure group '%s' to '%s' in %.*s",
+			      "Cannot assign overloaded procedure group '%s' to '%s' in %.*s%.*s",
 			      expr_str,
 			      op_type_str,
+			      LIT(article),
 			      LIT(context_name));
 			operand->mode = Addressing_Invalid;
 		}
@@ -1163,20 +1167,23 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
 		switch (operand->mode) {
 		case Addressing_Builtin:
 			error(operand->expr,
-			      "Cannot assign built-in procedure '%s' in %.*s",
+			      "Cannot assign built-in procedure '%s' to %.*s%.*s",
 			      expr_str,
+			      LIT(article),
 			      LIT(context_name));
 			break;
 		case Addressing_Type:
 			if (is_type_polymorphic(operand->type)) {
 				error(operand->expr,
-				      "Cannot assign '%s' which is a polymorphic type in %.*s",
+				      "Cannot assign '%s', a polymorphic type, to %.*s%.*s",
 				      op_type_str,
+				      LIT(article),
 				      LIT(context_name));
 			} else {
 				error(operand->expr,
-				      "Cannot assign '%s' which is a type in %.*s",
+				      "Cannot assign '%s', a type, to %.*s%.*s",
 				      op_type_str,
+				      LIT(article),
 				      LIT(context_name));
 			}
 			break;
@@ -1203,10 +1210,11 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
 
 				ERROR_BLOCK();
 				error(operand->expr,
-				      "Cannot assign value '%s' of type '%s%s' to '%s%s' in %.*s",
+				      "Cannot assign value '%s' of type '%s%s' to '%s%s' in %.*s%.*s",
 				      expr_str,
 				      op_type_str, op_type_extra,
 				      type_str, type_extra,
+				      LIT(article),
 				      LIT(context_name));
 				check_assignment_error_suggestion(c, operand, type);
 

+ 29 - 0
src/error.cpp

@@ -820,6 +820,35 @@ gb_internal int error_value_cmp(void const *a, void const *b) {
 	return token_pos_cmp(x->pos, y->pos);
 }
 
+gb_global String error_article_table[][2] = {
+	{str_lit("a "),  str_lit("bit_set literal")},
+	{str_lit("a "),  str_lit("constant declaration")},
+	{str_lit("a "),  str_lit("dynamiic array literal")},
+	{str_lit("a "),  str_lit("map index")},
+	{str_lit("a "),  str_lit("map literal")},
+	{str_lit("a "),  str_lit("matrix literal")},
+	{str_lit("a "),  str_lit("polymorphic type argument")},
+	{str_lit("a "),  str_lit("procedure argument")},
+	{str_lit("a "),  str_lit("simd vector literal")},
+	{str_lit("a "),  str_lit("slice literal")},
+	{str_lit("a "),  str_lit("structure literal")},
+	{str_lit("a "),  str_lit("variable declaration")},
+	{str_lit("an "), str_lit("'any' literal")},
+	{str_lit("an "), str_lit("array literal")},
+	{str_lit("an "), str_lit("enumerated array literal")},
+
+};
+
+// Returns definite or indefinite article matching `context_name`, or "" if not found.
+gb_internal String error_article(String context_name) {
+	for (int i = 0; i < gb_count_of(error_article_table); i += 1) {
+		if (context_name == error_article_table[i][1]) {
+			return error_article_table[i][0];
+		}
+	}
+	return str_lit("");
+}
+
 gb_internal bool errors_already_printed = false;
 
 gb_internal void print_all_errors(void) {