Răsfoiți Sursa

Allow _ in floats

Ginger Bill 8 ani în urmă
părinte
comite
0ca1b4612c
4 a modificat fișierele cu 100 adăugiri și 26 ștergeri
  1. 7 7
      code/demo.odin
  2. 2 2
      core/_preload.odin
  3. 79 14
      src/exact_value.c
  4. 12 3
      src/ir.c

+ 7 - 7
code/demo.odin

@@ -1,13 +1,13 @@
 #import "fmt.odin";
 
 main :: proc() {
-	foo :: proc() -> [dynamic]int {
-		x: [dynamic]int;
-		append(^x, 2, 3, 5, 7);
-		return x;
-	}
+	x: [dynamic]f64;
+	defer free(x);
+	append(^x, 2_000_000.500_000, 3, 5, 7);
 
-	for p in foo() {
-		fmt.println(p);
+	for p, i in x {
+		if i > 0 { fmt.print(", "); }
+		fmt.print(p);
 	}
+	fmt.println();
 }

+ 2 - 2
core/_preload.odin

@@ -357,9 +357,9 @@ __dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
 	array := cast(^Raw_Dynamic_Array)array_;
 
 	ok := true;
-	if array.data == nil || array.capacity <= array.count+item_count {
+	if array.capacity <= array.count+item_count {
 		capacity := 2 * array.capacity + max(8, item_count);
-		ok := __dynamic_array_reserve(array, elem_size, elem_align, capacity);
+		ok = __dynamic_array_reserve(array, elem_size, elem_align, capacity);
 	}
 	if !ok {
 		// TODO(bill): Better error handling for failed reservation

+ 79 - 14
src/exact_value.c

@@ -60,6 +60,19 @@ ExactValue make_exact_value_integer(i64 i) {
 	return result;
 }
 
+ExactValue make_exact_value_float(f64 f) {
+	ExactValue result = {ExactValue_Float};
+	result.value_float = f;
+	return result;
+}
+
+ExactValue make_exact_value_pointer(i64 ptr) {
+	ExactValue result = {ExactValue_Pointer};
+	result.value_pointer = ptr;
+	return result;
+}
+
+
 ExactValue make_exact_value_integer_from_string(String string) {
 	// TODO(bill): Allow for numbers with underscores in them
 	i32 base = 10;
@@ -106,24 +119,76 @@ ExactValue make_exact_value_integer_from_string(String string) {
 
 
 ExactValue make_exact_value_float_from_string(String string) {
-	// TODO(bill): Allow for numbers with underscores in them
-	ExactValue result = {ExactValue_Float};
-	result.value_float = gb_str_to_f64(cast(char *)string.text, NULL);
-	return result;
-}
+	isize i = 0;
+	u8 *str = string.text;
+	isize len = string.len;
 
-ExactValue make_exact_value_float(f64 f) {
-	ExactValue result = {ExactValue_Float};
-	result.value_float = f;
-	return result;
-}
+	f64 sign = 1.0;
+	if (str[i] == '-') {
+		sign = -1.0;
+		i++;
+	} else if (*str == '+') {
+		i++;
+	}
 
-ExactValue make_exact_value_pointer(i64 ptr) {
-	ExactValue result = {ExactValue_Pointer};
-	result.value_pointer = ptr;
-	return result;
+	f64 value = 0.0;
+	for (; i < len; i++) {
+		Rune r = cast(Rune)str[i];
+		if (r == '_') {
+			continue;
+		}
+		if (!gb_char_is_digit(r)) {
+			break;
+		}
+		i64 v = r - '0';
+		value *= 10.0;
+		value += v;
+	}
+
+	if (str[i] == '.') {
+		f64 pow10 = 10.0;
+		i++;
+		for (; i < string.len; i++) {
+			Rune r = cast(Rune)str[i];
+			if (r == '_') {
+				continue;
+			}
+			if (!gb_char_is_digit(r)) {
+				break;
+			}
+			value += (r-'0')/pow10;
+			pow10 *= 10.0;
+		}
+	}
+
+	f64 frac = 0;
+	f64 scale = 1.0;
+	if ((str[i] == 'e') || (str[i] == 'E')) {
+		i++;
+
+		if (str[i] == '-') {
+			frac = 1;
+			i++;
+		} else if (str[i] == '+') {
+			i++;
+		}
+
+		u32 exp;
+		for (exp = 0; gb_char_is_digit(str[i]); i++) {
+			exp = exp * 10 + (str[i]-'0');
+		}
+		if (exp > 308) exp = 308;
+
+		while (exp >= 50) { scale *= 1e50; exp -= 50; }
+		while (exp >=  8) { scale *= 1e8;  exp -=  8; }
+		while (exp >   0) { scale *= 10.0; exp -=  1; }
+	}
+
+	f64 result = sign * (frac ? (value / scale) : (value * scale));
+	return make_exact_value_float(result);
 }
 
+
 ExactValue make_exact_value_from_basic_literal(Token token) {
 	switch (token.kind) {
 	case Token_String:  return make_exact_value_string(token.string);

+ 12 - 3
src/ir.c

@@ -1734,6 +1734,8 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, Type *type, irValue *e, Selec
 			}
 		} else if (type->kind == Type_Slice) {
 			e = ir_emit_struct_ep(proc, e, index);
+		} else if (type->kind == Type_DynamicArray) {
+			e = ir_emit_struct_ep(proc, e, index);
 		} else if (type->kind == Type_Vector) {
 			e = ir_emit_array_epi(proc, e, index);
 		} else if (type->kind == Type_Array) {
@@ -3551,6 +3553,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			}
 		} else {
 			Type *type = base_type(type_of_expr(proc->module->info, se->expr));
+			GB_ASSERT(is_type_integer(type));
 			ExactValue val = type_and_value_of_expression(proc->module->info, sel)->value;
 			i64 index = val.value_integer;
 
@@ -3581,6 +3584,14 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			ir_emit_store(proc, v, ir_emit_transmute(proc, ir_build_expr(proc, ce->expr), type));
 			return ir_make_addr(v, expr);
 		}
+		case Token_down_cast: {
+			ir_emit_comment(proc, str_lit("Cast - down_cast"));
+			// NOTE(bill): Needed for dereference of pointer conversion
+			Type *type = type_of_expr(proc->module->info, expr);
+			irValue *v = ir_add_local_generated(proc, type);
+			ir_emit_store(proc, v, ir_emit_down_cast(proc, ir_build_expr(proc, ce->expr), type));
+			return ir_make_addr(v, expr);
+		}
 		default:
 			GB_PANIC("Unknown cast expression");
 		}
@@ -3860,13 +3871,13 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(ce, CallExpr, expr);
+		// NOTE(bill): This is make sure you never need to have an `array_ev`
 		irValue *e = ir_build_expr(proc, expr);
 		irValue *v = ir_add_local_generated(proc, ir_type(e));
 		ir_emit_store(proc, v, e);
 		return ir_make_addr(v, expr);
 	case_end;
 
-
 	case_ast_node(cl, CompoundLit, expr);
 		ir_emit_comment(proc, str_lit("CompoundLit"));
 		Type *type = type_of_expr(proc->module->info, expr);
@@ -4046,8 +4057,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 
 		return ir_make_addr(v, expr);
 	case_end;
-
-
 	}
 
 	TokenPos token_pos = ast_node_token(expr).pos;