diff --git a/skiplang/prelude/runtime/runtime32_specific.c b/skiplang/prelude/runtime/runtime32_specific.c index 8057ec060..8e7654b7a 100644 --- a/skiplang/prelude/runtime/runtime32_specific.c +++ b/skiplang/prelude/runtime/runtime32_specific.c @@ -158,6 +158,16 @@ uint64_t SKIP_time_ms() { return (((uint64_t)hi) << 32) | ((uint64_t)lo); } +uint64_t SKIP_time_ns() { + // No nanosecond precision on 32-bit/WASM; fall back to milliseconds * 1e6. + return SKIP_time_ms() * 1000000; +} + +void SKIP_sleep_ms(uint64_t ms) { + // Not implemented on 32-bit/WASM. + (void)ms; +} + void SKIP_flush_stdout() { // Not implemented } diff --git a/skiplang/prelude/runtime/runtime64_specific.cpp b/skiplang/prelude/runtime/runtime64_specific.cpp index c1a0ef697..8be18e416 100644 --- a/skiplang/prelude/runtime/runtime64_specific.cpp +++ b/skiplang/prelude/runtime/runtime64_specific.cpp @@ -32,6 +32,7 @@ extern "C" { #include #include #include +#include #include extern "C" { @@ -442,6 +443,17 @@ uint64_t SKIP_time_ms() { .count(); } +uint64_t SKIP_time_ns() { + using namespace std::chrono; + + return duration_cast(steady_clock::now().time_since_epoch()) + .count(); +} + +void SKIP_sleep_ms(uint64_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +} + char* SKIP_unix_strftime(char* formatp, char* timep) { struct tm* tm = (struct tm*)timep; char buffer[1024]; diff --git a/skiplang/prelude/src/stdlib/other/Time.sk b/skiplang/prelude/src/stdlib/other/Time.sk index ca9362066..e546ea8f7 100644 --- a/skiplang/prelude/src/stdlib/other/Time.sk +++ b/skiplang/prelude/src/stdlib/other/Time.sk @@ -10,6 +10,17 @@ native fun time(): Int; @cpp_extern("SKIP_time_ms") native fun time_ms(): Int; +// Current time in nanoseconds from a monotonic clock (steady_clock). +// Suitable for measuring elapsed time, not wall-clock time. +@debug +@cpp_extern("SKIP_time_ns") +native fun time_ns(): Int; + +// Sleep for the given number of milliseconds. +@debug +@cpp_extern("SKIP_sleep_ms") +native fun sleep_ms(ms: Int): void; + @cpp_extern("SKIP_strftime") native fun strftime(format: String, timestamp: Int): String; diff --git a/skiplang/prelude/tests/skfs/TestRuntime.sk b/skiplang/prelude/tests/skfs/TestRuntime.sk index a69867271..e047a405f 100644 --- a/skiplang/prelude/tests/skfs/TestRuntime.sk +++ b/skiplang/prelude/tests/skfs/TestRuntime.sk @@ -151,4 +151,22 @@ fun testRuntime(): void { ); } +@test +fun testTimeNs(): void { + t1 = Time.time_ns(); + SKTest.expectTrue(t1 > 0, "time_ns: returns positive value"); + t2 = Time.time_ns(); + SKTest.expectTrue(t2 >= t1, "time_ns: monotonically non-decreasing"); +} + +@test +fun testSleepMs(): void { + before = Time.time_ns(); + Time.sleep_ms(1); + after = Time.time_ns(); + elapsed = after - before; + SKTest.expectTrue(elapsed > 1000000, "sleep_ms: slept at least 1ms"); + SKTest.expectTrue(elapsed < 10000000, "sleep_ms: slept less than 10ms"); +} + module end;