aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2019-08-23 11:51:04 +0100
committergingerBill <bill@gingerbill.org>2019-08-23 11:51:04 +0100
commitcf23954297993b3e574c295f95f75b294fdca4ec (patch)
treee37561a4e46243ce4985cf53c77e02da54c4dc7d /src
parentd1cc6534cdb25c95f948a81e863f9348dfb5122e (diff)
Improve #assert to show the procedure and signature it was called with; Allow the ability to print ExactValue correct now.
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp9
-rw-r--r--src/exact_value.cpp46
-rw-r--r--src/string.cpp84
-rw-r--r--src/types.cpp65
4 files changed, 179 insertions, 25 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 6c252b9b6..24a130d62 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -3360,6 +3360,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
if (!operand->value.value_bool) {
gbString arg = expr_to_string(ce->args[0]);
error(call, "Compile time assertion: %s", arg);
+ if (c->proc_name != "") {
+ gbString str = type_to_string(c->curr_proc_sig);
+ error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str);
+ gb_string_free(str);
+ }
gb_string_free(arg);
}
@@ -3744,7 +3749,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
}
if (x.mode == Addressing_Constant && y.mode == Addressing_Constant) {
- operand->value = exact_binary_operator_value(Token_Add, x.value, y.value);
+ f64 r = exact_value_to_float(x.value).value_float;
+ f64 i = exact_value_to_float(y.value).value_float;
+ operand->value = exact_value_complex(r, i);
operand->mode = Addressing_Constant;
} else {
operand->mode = Addressing_Value;
diff --git a/src/exact_value.cpp b/src/exact_value.cpp
index 7d822512b..be034ecc5 100644
--- a/src/exact_value.cpp
+++ b/src/exact_value.cpp
@@ -718,3 +718,49 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
GB_PANIC("Invalid comparison");
return false;
}
+
+
+gbString write_exact_value_to_string(gbString str, ExactValue const &v, isize string_limit=36) {
+ switch (v.kind) {
+ case ExactValue_Invalid:
+ return str;
+ case ExactValue_Bool:
+ return gb_string_appendc(str, v.value_bool ? "true" : "false");
+ case ExactValue_String: {
+ String s = quote_to_ascii(heap_allocator(), v.value_string);
+ string_limit = gb_max(string_limit, 36);
+ if (s.len <= string_limit) {
+ str = gb_string_append_length(str, s.text, s.len);
+ } else {
+ isize n = string_limit/5;
+ str = gb_string_append_length(str, s.text, n);
+ str = gb_string_append_fmt(str, "\"..%lld chars..\"", s.len-(2*n));
+ str = gb_string_append_length(str, s.text+s.len-n, n);
+ }
+ gb_free(heap_allocator(), s.text);
+ return str;
+ }
+ case ExactValue_Integer: {
+ String s = big_int_to_string(heap_allocator(), &v.value_integer);
+ str = gb_string_append_length(str, s.text, s.len);
+ gb_free(heap_allocator(), s.text);
+ return str;
+ }
+ case ExactValue_Float:
+ return gb_string_append_fmt(str, "%f", v.value_float);
+ case ExactValue_Complex:
+ return gb_string_append_fmt(str, "%f+%fi", v.value_complex.real, v.value_complex.imag);
+
+ case ExactValue_Pointer:
+ return str;
+ case ExactValue_Compound:
+ return str;
+ case ExactValue_Procedure:
+ return str;
+ }
+ return str;
+};
+
+gbString exact_value_to_string(ExactValue const &v, isize string_limit=35) {
+ return write_exact_value_to_string(gb_string_make(heap_allocator(), ""), v, string_limit);
+}
diff --git a/src/string.cpp b/src/string.cpp
index 774061edf..a29f3bd77 100644
--- a/src/string.cpp
+++ b/src/string.cpp
@@ -440,12 +440,94 @@ String string16_to_string(gbAllocator a, String16 s) {
+bool is_printable(Rune r) {
+ if (r <= 0xff) {
+ if (0x20 <= r && r <= 0x7e) {
+ return true;
+ }
+ if (0xa1 <= r && r <= 0xff) {
+ return r != 0xad;
+ }
+ return false;
+ }
+ return false;
+}
+gb_global char const lower_hex[] = "0123456789abcdef";
+
+String quote_to_ascii(gbAllocator a, String str, u8 quote='"') {
+ u8 *s = str.text;
+ isize n = str.len;
+ auto buf = array_make<u8>(a, 0, n);
+ array_add(&buf, quote);
+ for (isize width = 0; n > 0; s += width, n -= width) {
+ Rune r = cast(Rune)s[0];
+ width = 1;
+ if (r >= 0x80) {
+ width = gb_utf8_decode(s, n, &r);
+ }
+ if (width == 1 && r == GB_RUNE_INVALID) {
+ array_add(&buf, cast(u8)'\\');
+ array_add(&buf, cast(u8)'x');
+ array_add(&buf, cast(u8)lower_hex[s[0]>>4]);
+ array_add(&buf, cast(u8)lower_hex[s[0]&0xf]);
+ continue;
+ }
+ if (r == quote || r == '\\') {
+ array_add(&buf, cast(u8)'\\');
+ array_add(&buf, u8(r));
+ continue;
+ }
+ if (r < 0x80 && is_printable(r)) {
+ array_add(&buf, u8(r));
+ continue;
+ }
+ switch (r) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ default:
+ if (r < ' ') {
+ u8 b = cast(u8)r;
+ array_add(&buf, cast(u8)'\\');
+ array_add(&buf, cast(u8)'x');
+ array_add(&buf, cast(u8)lower_hex[b>>4]);
+ array_add(&buf, cast(u8)lower_hex[b&0xf]);
+ }
+ if (r > GB_RUNE_MAX) {
+ r = 0XFFFD;
+ }
+ if (r < 0x10000) {
+ u8 b = cast(u8)r;
+ array_add(&buf, cast(u8)'\\');
+ array_add(&buf, cast(u8)'u');
+ for (isize i = 12; i >= 0; i -= 4) {
+ array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]);
+ }
+ } else {
+ u8 b = cast(u8)r;
+ array_add(&buf, cast(u8)'\\');
+ array_add(&buf, cast(u8)'U');
+ for (isize i = 28; i >= 0; i -= 4) {
+ array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]);
+ }
+ }
+ }
+ }
-
+ array_add(&buf, quote);
+ String res = {};
+ res.text = buf.data;
+ res.len = buf.count;
+ return res;
+}
diff --git a/src/types.cpp b/src/types.cpp
index 4404882a9..b5c9152b6 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -2968,35 +2968,54 @@ gbString write_type_to_string(gbString str, Type *type) {
isize comma_index = 0;
for_array(i, type->Tuple.variables) {
Entity *var = type->Tuple.variables[i];
- if (var != nullptr) {
- if (var->kind == Entity_Constant) {
- // Ignore
- continue;
+ if (var == nullptr) {
+ continue;
+ }
+ String name = var->token.string;
+ if (var->kind == Entity_Constant) {
+ str = gb_string_appendc(str, "$");
+ str = gb_string_append_length(str, name.text, name.len);
+ if (!is_type_untyped(var->type)) {
+ str = gb_string_appendc(str, ": ");
+ str = write_type_to_string(str, var->type);
+ str = gb_string_appendc(str, " = ");
+ str = write_exact_value_to_string(str, var->Constant.value);
+ } else {
+ str = gb_string_appendc(str, "=");
+ str = write_exact_value_to_string(str, var->Constant.value);
}
+ continue;
+ }
- if (comma_index++ > 0) {
- str = gb_string_appendc(str, ", ");
- }
+ if (comma_index++ > 0) {
+ str = gb_string_appendc(str, ", ");
+ }
- if (var->kind == Entity_Variable) {
- if (var->flags&EntityFlag_CVarArg) {
- str = gb_string_appendc(str, "#c_vararg ");
- }
- if (var->flags&EntityFlag_Ellipsis) {
- Type *slice = base_type(var->type);
- str = gb_string_appendc(str, "..");
- GB_ASSERT(var->type->kind == Type_Slice);
- str = write_type_to_string(str, slice->Slice.elem);
- } else {
- str = write_type_to_string(str, var->type);
- }
+ if (var->kind == Entity_Variable) {
+ if (var->flags&EntityFlag_CVarArg) {
+ str = gb_string_appendc(str, "#c_vararg ");
+ }
+ if (var->flags&EntityFlag_Ellipsis) {
+ Type *slice = base_type(var->type);
+ str = gb_string_appendc(str, "..");
+ GB_ASSERT(var->type->kind == Type_Slice);
+ str = write_type_to_string(str, slice->Slice.elem);
+ } else {
+ str = write_type_to_string(str, var->type);
+ }
+ } else {
+ GB_ASSERT(var->kind == Entity_TypeName);
+ if (var->type->kind == Type_Generic) {
+ str = gb_string_appendc(str, "typeid/");
+ str = write_type_to_string(str, var->type);
} else {
- GB_ASSERT(var->kind == Entity_TypeName);
- if (var->type->kind == Type_Generic) {
- str = gb_string_appendc(str, "type/");
+ if (var->kind == Entity_TypeName) {
+ str = gb_string_appendc(str, "$");
+ str = gb_string_append_length(str, name.text, name.len);
+ str = gb_string_appendc(str, "=");
str = write_type_to_string(str, var->type);
} else {
- str = gb_string_appendc(str, "type");
+ str = gb_string_appendc(str, "typeid");
}
}
}