#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");
   });
}
