#module_parameters(RUN_TESTS := false); get_stack_trace_caller_location :: (loc := #caller_location) -> Source_Code_Location { if context.stack_trace == null || context.stack_trace.info == null { return loc; } cur := context.stack_trace; while cur != null { if cur.info == null break; if cur.info.location.fully_pathed_filename != loc.fully_pathed_filename { break; } cur = cur.next; } return cur.info.location; } check_bounds :: ($$index: $T, $$count: T, loc := #caller_location) #expand { MESSAGE :: "bounds check failed! index % (max %)"; #if is_constant(index) && is_constant(count) { if index < 0 || index >= count { message := basic.tprint(MESSAGE, index, count - 1); compiler.compiler_report(message, mode = .ERROR, loc = loc); } } else { basic.assert(index >= 0 && index < count, MESSAGE, index, count - 1, loc = loc); } } // Can be passed directly to using,map remap_snake_to_pascal :: (names: []string) { for names { names[it_index] = snake_to_pascal(it); } } snake_to_pascal :: (name: string) -> string { b: basic.String_Builder; upper := true; for i: 0..name.count - 1 { c := name[i]; if c == #char "_" { upper = true; continue; } if upper { basic.append(*b, basic.to_upper(c)); upper = false; } else { basic.append(*b, c); } } return basic.builder_to_string(*b); } #load "macros.jai"; #load "type_info.jai"; #scope_module; mem :: #import "jc/memory"; basic :: #import "Basic"; // @future compiler :: #import "Compiler"; // @future // ---------------------------------------------------------- // TESTS // ---------------------------------------------------------- #if RUN_TESTS { test :: #import "jc/test"; #run test.run("snake_to_pascal", t => { test.expect(t, snake_to_pascal("some_name") == "SomeName"); test.expect(t, snake_to_pascal("_some_name") == "SomeName"); test.expect(t, snake_to_pascal("some__name") == "SomeName"); test.expect(t, snake_to_pascal("some_name_") == "SomeName"); test.expect(t, snake_to_pascal("X_Y_Z") == "XYZ"); test.expect(t, snake_to_pascal("XY_Z") == "XYZ"); }); }