- New syntax for declaring quoted code blocks.
- `[captures] { body }` for blocks.
- `[captures] ( expr )` for expressions.
+- User-level stack trace.
+ - Enable with `--stack-trace`
+ - Use `runtime.info.get_stack_trace()` to get the current stack trace.
+ - Used in assertions and heap allocator for better error reporting
- `Optional.with` for running a block of code with the value in an Optional, if one is present.
- `iter.flatten`
- `-Dvariable=value` command line option to add symbols to the `runtime.vars` package.
- `--no-type-info` command line option to omit type information from the binary.
+- `conv.encode_hex` and `conv.decode_hex`
+ - Quickly convrt a byte array to and from its hex equivalent.
Removals:
- Remove old syntax for quoted blocks, `#quote` and `#()`.
// Enable this to enable checking for invalid blocks and other corruptions
// that may happen on the heap, with the added overhead of checking that
// on every alloc/resize/free.
-Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
-Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory)
+#local Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
+#local Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory)
+#local Enable_Stack_Trace :: runtime.Stack_Trace_Enabled
#load "core/intrinsics/wasm"
#if runtime.Multi_Threading_Enabled do sync.scoped_mutex(&heap_mutex);
#if Enable_Debug {
+ // RELOCATE
+ trace :: macro () {
+ #if Enable_Stack_Trace {
+ trace := runtime.info.get_stack_trace();
+ for trace {
+ log(.Error, "Core", core.tprintf("in {} ({}:{})", it.func_name, it.file, it.line));
+ }
+ }
+ }
+
if cast(uintptr) hb_ptr < cast(uintptr) __heap_start {
log(.Error, "Core", "FREEING STATIC DATA");
+ trace();
return;
}
if hb_ptr.size & Allocated_Flag != Allocated_Flag {
log(.Error, "Core", "INVALID DOUBLE FREE");
+ trace();
return;
}
if hb_ptr.magic_number != Alloc_Block_Magic_Number {
log(.Error, "Core", "FREEING INVALID BLOCK");
+ trace();
return;
}
}
format_int :: i64_to_str
format_uint :: u64_to_str
format_float :: f64_to_str
+
+
+
+
+encode_hex :: (s: str, allocator := context.allocator) -> str {
+ #persist encode_map := u8.['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
+
+ new_str := make([] u8, s.count * 2, allocator);
+ for i: s.count {
+ new_str[2 * i + 0] = encode_map[(s[i] & 0xf0) >> 4];
+ new_str[2 * i + 1] = encode_map[s[i] & 0xf];
+ }
+
+ return new_str;
+}
+
+decode_hex :: (s: str, allocator := context.allocator) -> str {
+ assert(s.count & 1 == 0, "Expected string of even length");
+
+ new_str := make([] u8, s.count >> 1, allocator);
+ for i: range.{0, s.count, 2} {
+ new_str[i >> 1] = ~~((digit_to_value(s[i + 0]) << 4) | (digit_to_value(s[i + 1])));
+ }
+
+ return new_str;
+
+ digit_to_value :: (it: u8) -> u32 {
+ switch it {
+ case #char "0" .. #char "9" do return ~~(it - #char "0");
+ case #char "a" .. #char "f" do return ~~(it - #char "a" + 10);
+ case #char "A" .. #char "F" do return ~~(it - #char "A" + 10);
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file
__output_string("Assert failed: ");
__output_string(msg);
- if site.file.data != null {
- __output_string(" in ");
- __output_string(site.file);
+
+ #if Stack_Trace_Enabled {
+ __output_string("\n");
+ trace := info.get_stack_trace();
+ for trace[1..trace.length] {
+ __output_string(" in ");
+ __output_string(it.func_name);
+ __output_string(" (");
+ __output_string(it.file);
+ __output_string(")\n");
+ }
+
+ } else {
+ if site.file.data != null {
+ __output_string(" in ");
+ __output_string(site.file);
+ }
}
__output_string("\n");
--- /dev/null
+The quick brown fox jumps over the lazy dog
+54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67
+The quick brown fox jumps over the lazy dog
--- /dev/null
+
+use core {*}
+
+main :: () {
+ s := "The quick brown fox jumps over the lazy dog";
+ println(s);
+
+ encoded := conv.encode_hex(s);
+ println(encoded);
+
+ decoded := conv.decode_hex(encoded);
+ println(decoded);
+}