Browse Source

Support string literals for fixed arrays of runes; Add %q support for arrays/slices of bytes

gingerBill 4 years ago
parent
commit
63e4a2341f
6 changed files with 96 additions and 29 deletions
  1. 2 2
      core/fmt/fmt.odin
  2. 10 3
      src/check_expr.cpp
  3. 5 3
      src/ir.cpp
  4. 22 0
      src/ir_print.cpp
  5. 26 0
      src/llvm_backend.cpp
  6. 31 21
      src/types.cpp

+ 2 - 2
core/fmt/fmt.odin

@@ -1599,7 +1599,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 		}
 
 	case runtime.Type_Info_Array:
-		if verb == 's' && reflect.is_byte(info.elem) {
+		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
 			s := strings.string_from_ptr((^byte)(v.data), info.count);
 			fmt_string(fi, s, verb);
 		} else {
@@ -1664,7 +1664,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
 
 	case runtime.Type_Info_Slice:
 		slice := cast(^mem.Raw_Slice)v.data;
-		if verb == 's' && reflect.is_byte(info.elem) {
+		if (verb == 's' || verb == 'q') && reflect.is_byte(info.elem) {
 			s := strings.string_from_ptr((^byte)(slice.data), slice.len);
 			fmt_string(fi, s, verb);
 		} else if verb == 'p' {

+ 10 - 3
src/check_expr.cpp

@@ -2955,10 +2955,17 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
 		if (check_is_assignable_to(c, operand, elem)) {
 			operand->mode = Addressing_Value;
 		} else {
-			if (operand->value.kind == ExactValue_String && is_type_u8_array(t)) {
+			if (operand->value.kind == ExactValue_String) {
 				String s = operand->value.value_string;
-				if (s.len == t->Array.count) {
-					break;
+				if (is_type_u8_array(t)) {
+					if (s.len == t->Array.count) {
+						break;
+					}
+				} else if (is_type_rune_array(t)) {
+					isize rune_count = s.len;
+					if (rune_count == t->Array.count) {
+						break;
+					}
 				}
 			}
 			operand->mode = Addressing_Invalid;

+ 5 - 3
src/ir.cpp

@@ -7801,9 +7801,11 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) {
 
 	if (tv.value.kind != ExactValue_Invalid) {
 		// NOTE(bill): Edge case
-	    	if (is_type_u8_array(tv.type) && tv.value.kind == ExactValue_String) {
-	    		return ir_add_module_constant(proc->module, tv.type, tv.value);
-	    	} else if (tv.value.kind != ExactValue_Compound &&
+		if (is_type_u8_array(tv.type) && tv.value.kind == ExactValue_String) {
+			return ir_add_module_constant(proc->module, tv.type, tv.value);
+		} else if (is_type_rune_array(tv.type) && tv.value.kind == ExactValue_String) {
+			return ir_add_module_constant(proc->module, tv.type, tv.value);
+		} else if (tv.value.kind != ExactValue_Compound &&
 		    is_type_array(tv.type)) {
 			Type *elem = core_array_type(tv.type);
 			ExactValue value = convert_exact_value_for_type(tv.value, elem);

+ 22 - 0
src/ir_print.cpp

@@ -734,6 +734,28 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 	if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) {
 		i64 count  = type->Array.count;
 		Type *elem = type->Array.elem;
+
+		if (is_type_rune_array(type)) {
+			Rune rune;
+			isize offset = 0;
+			isize width = 1;
+			String s = value.value_string;
+			ir_write_byte(f, '[');
+			for (i64 i = 0; i < count && offset < s.len; i++) {
+				width = gb_utf8_decode(s.text+offset, s.len-offset, &rune);
+				if (i > 0) ir_write_str_lit(f, ", ");
+				ir_print_type(f, m, elem);
+				ir_write_byte(f, ' ');
+				ir_print_exact_value(f, m, exact_value_i64(rune), elem);
+				offset += width;
+			}
+			GB_ASSERT(offset == s.len);
+
+			ir_write_byte(f, ']');
+			return;
+		}
+
+
 		ir_write_byte(f, '[');
 
 		for (i64 i = 0; i < count; i++) {

+ 26 - 0
src/llvm_backend.cpp

@@ -5123,6 +5123,32 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc
 
 		}
 	} else if (is_type_array(type) && value.kind == ExactValue_String && !is_type_u8(core_array_type(type))) {
+		if (is_type_rune_array(type) && value.kind == ExactValue_String) {
+			i64 count  = type->Array.count;
+			Type *elem = type->Array.elem;
+			LLVMTypeRef et = lb_type(m, elem);
+
+			Rune rune;
+			isize offset = 0;
+			isize width = 1;
+			String s = value.value_string;
+
+			LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count);
+
+			for (i64 i = 0; i < count && offset < s.len; i++) {
+				width = gb_utf8_decode(s.text+offset, s.len-offset, &rune);
+				offset += width;
+
+				elems[i] = LLVMConstInt(et, rune, true);
+
+			}
+			GB_ASSERT(offset == s.len);
+
+			res.value = LLVMConstArray(et, elems, cast(unsigned)count);
+			return res;
+		}
+		GB_PANIC("HERE!\n");
+
 		LLVMValueRef data = LLVMConstStringInContext(ctx,
 			cast(char const *)value.value_string.text,
 			cast(unsigned)value.value_string.len,

+ 31 - 21
src/types.cpp

@@ -1214,27 +1214,6 @@ bool is_type_slice(Type *t) {
 	t = base_type(t);
 	return t->kind == Type_Slice;
 }
-bool is_type_u8_slice(Type *t) {
-	t = base_type(t);
-	if (t->kind == Type_Slice) {
-		return is_type_u8(t->Slice.elem);
-	}
-	return false;
-}
-bool is_type_u8_array(Type *t) {
-	t = base_type(t);
-	if (t->kind == Type_Array) {
-		return is_type_u8(t->Array.elem);
-	}
-	return false;
-}
-bool is_type_u8_ptr(Type *t) {
-	t = base_type(t);
-	if (t->kind == Type_Pointer) {
-		return is_type_u8(t->Slice.elem);
-	}
-	return false;
-}
 bool is_type_proc(Type *t) {
 	t = base_type(t);
 	return t->kind == Type_Proc;
@@ -1278,6 +1257,37 @@ bool is_type_relative_slice(Type *t) {
 	return t->kind == Type_RelativeSlice;
 }
 
+bool is_type_u8_slice(Type *t) {
+	t = base_type(t);
+	if (t->kind == Type_Slice) {
+		return is_type_u8(t->Slice.elem);
+	}
+	return false;
+}
+bool is_type_u8_array(Type *t) {
+	t = base_type(t);
+	if (t->kind == Type_Array) {
+		return is_type_u8(t->Array.elem);
+	}
+	return false;
+}
+bool is_type_u8_ptr(Type *t) {
+	t = base_type(t);
+	if (t->kind == Type_Pointer) {
+		return is_type_u8(t->Slice.elem);
+	}
+	return false;
+}
+bool is_type_rune_array(Type *t) {
+	t = base_type(t);
+	if (t->kind == Type_Array) {
+		return is_type_rune(t->Array.elem);
+	}
+	return false;
+}
+
+
+
 
 Type *core_array_type(Type *t) {
 	for (;;) {