diff --git a/std/README.md b/std/README.md new file mode 100644 index 00000000..1ce852a7 --- /dev/null +++ b/std/README.md @@ -0,0 +1,3 @@ +# Wave Standard Library + +This is Wave's standard library. This standard library operates independently of Wave's compiler and is not part of the compiler itself. \ No newline at end of file diff --git a/std/io/format.wave b/std/io/format.wave deleted file mode 100644 index 9a66ebe3..00000000 --- a/std/io/format.wave +++ /dev/null @@ -1,3 +0,0 @@ -fun std_format_dummy() { - println("std::io::format loaded"); -} \ No newline at end of file diff --git a/std/manifest.json b/std/manifest.json index 30d3b55e..99c3c43c 100644 --- a/std/manifest.json +++ b/std/manifest.json @@ -1,5 +1,5 @@ { "name": "std", "format": 1, - "modules": ["io", "fs", "net", "math", "sys", "json"] + "modules": ["string", "math"] } diff --git a/std/math/bits.wave b/std/math/bits.wave new file mode 100644 index 00000000..af44114b --- /dev/null +++ b/std/math/bits.wave @@ -0,0 +1,84 @@ +fun is_pow2(x: i32) -> bool { + if (x <= 0) { + return false; + } + + if ((x & (x - 1)) == 0) { + return true; + } + + return false; +} + +fun align_down(x: i32, align: i32) -> i32 { + if (align <= 0) { + return x; + } + + return x & ~(align - 1); +} + +fun align_up(x: i32, align: i32) -> i32 { + if (align <= 0) { + return x; + } + + return (x + (align - 1)) & ~(align - 1); +} + +fun low_bit(x: i32) -> i32 { + return x & (-x); +} + +fun popcount(x0: i32) -> i32 { + let mut x: i32 = x0; + let mut c: i32 = 0; + + while (x != 0) { + x = x & (x - 1); + c += 1; + } + + return c; +} + +fun ctz32(x: i32) -> i32 { + if (x == 0) { + return 32; + } + + let lb: i32 = low_bit(x); + return popcount(lb - 1); +} + +fun bit_length(x0: i32) -> i32 { + if (x0 <= 0) { + return 0; + } + + let mut x: i32 = x0; + let mut n: i32 = 0; + + while (x > 0) { + x = x >> 1; + n += 1; + } + + return n; +} + +fun ilog2_floor(x: i32) -> i32 { + if (x <= 0) { + return -1; + } + + return bit_length(x) - 1; +} + +fun ilog2_ceil(x: i32) -> i32 { + if (x <= 1) { + return 0; + } + + return ilog2_floor(x - 1) + 1; +} diff --git a/std/math/float.wave b/std/math/float.wave new file mode 100644 index 00000000..52f65898 --- /dev/null +++ b/std/math/float.wave @@ -0,0 +1,35 @@ +fun abs_f32(x: f32) -> f32 { + if (x < 0.0) { + return -x; + } + + return x; +} + +fun min_f32(a: f32, b: f32) -> f32 { + if (a < b) { + return a; + } + + return b; +} + +fun max_f32(a: f32, b: f32) -> f32 { + if (a > b) { + return a; + } + + return b; +} + +fun clamp_f32(x: f32, lo: f32, hi: f32) -> f32 { + if (x < lo) { + return lo; + } + + if (x > hi) { + return hi; + } + + return x; +} diff --git a/std/math/int.wave b/std/math/int.wave new file mode 100644 index 00000000..57896425 --- /dev/null +++ b/std/math/int.wave @@ -0,0 +1,94 @@ +fun abs(x: i32) -> i32 { + if (x < 0) { + return -x; + } + + return x; +} + +fun min(a: i32, b: i32) -> i32 { + if (a < b) { + return a; + } + + return b; +} + +fun max(a: i32, b: i32) -> i32 { + if (a > b) { + return a; + } + + return b; +} + +fun clamp(x: i32, lo: i32, hi: i32) -> i32 { + if (x < lo) { + return lo; + } + + if (x > hi) { + return hi; + } + + return x; +} + +fun sign(x: i32) -> i32 { + if (x < 0) { + return -1; + } + + if (x > 0) { + return 1; + } + + return 0; +} + +fun is_even(x: i32) -> bool { + if ((x % 2) == 0) { + return true; + } + + return false; +} + +fun is_odd(x: i32) -> bool { + if ((x % 2) != 0) { + return true; + } + + return false; +} + +fun div_ceil_pos(a: i32, b: i32) -> i32 { + if (b == 0) { + return 0; + } + + if (a <= 0) { + return 0; + } + + return (a + (b - 1)) / b; +} + +fun div_floor_pos(a: i32, b: i32) -> i32 { + if (b == 0) { + return 0; + } + + if (a <= 0) { + return 0; + } + + return a / b; +} + +fun swap_i32(a: ptr, b: ptr) { + let t: i32 = deref a; + + deref a = deref b; + deref b = t; +} diff --git a/std/math/num.wave b/std/math/num.wave new file mode 100644 index 00000000..a43a3798 --- /dev/null +++ b/std/math/num.wave @@ -0,0 +1,53 @@ +fun gcd(a0: i32, b0: i32) -> i32 { + let mut a: i32 = a0; + let mut b: i32 = b0; + + if (a < 0) { + a = -a; + } + + if (b < 0) { + b = -b; + } + + while (b != 0) { + let t: i32 = a % b; + a = b; + b = t; + } + + return a; +} + +fun lcm(a: i32, b: i32) -> i32 { + if (a == 0 || b == 0) { + return 0; + } + + let g: i32 = gcd(a, b); + let x: i32 = a / g; + let mut r: i32 = x * b; + + if (r < 0) { + r = -r; + } + + return r; +} + +fun pow_i32(base0: i32, exp0: i32) -> i32 { + let mut base: i32 = base0; + let mut exp: i32 = exp0; + let mut result: i32 = 1; + + while (exp > 0) { + if ((exp & 1) == 1) { + result = result * base; + } + + base = base * base; + exp = exp >> 1; + } + + return result; +} diff --git a/std/string/ascii.wave b/std/string/ascii.wave new file mode 100644 index 00000000..27f4c03c --- /dev/null +++ b/std/string/ascii.wave @@ -0,0 +1,83 @@ +fun is_digit(c: u8) -> bool { + if (c >= 48 && c <= 57) { + return true; + } + + return false; +} + +fun is_lower(c: u8) -> bool { + if (c >= 97 && c <= 122) { + return true; + } + + return false; +} + +fun is_upper(c: u8) -> bool { + if (c >= 65 && c <= 90) { + return true; + } + + return false; +} + +fun is_alpha(c: u8) -> bool { + if (is_lower(c)) { + return true; + } + + if (is_upper(c)) { + return true; + } + + return false; +} + +fun is_alnum(c: u8) -> bool { + if (is_alpha(c)) { + return true; + } + + if (is_digit(c)) { + return true; + } + + return false; +} + +fun is_space(c: u8) -> bool { + if (c == 32) { + return true; + } + + if (c == 9) { + return true; + } + + if (c == 10) { + return true; + } + + if (c == 13) { + return true; + } + + return false; +} + +fun to_lower(c: u8) -> u8 { + if (is_upper(c)) { + return c + 32; + } + + return c; +} + +fun to_upper(c: u8) -> u8 { + if (is_lower(c)) { + return c - 32; + } + + return c; +} diff --git a/std/string/cmp.wave b/std/string/cmp.wave new file mode 100644 index 00000000..88005c88 --- /dev/null +++ b/std/string/cmp.wave @@ -0,0 +1,86 @@ +fun eq(a: str, b: str) -> bool { + let mut i: i32 = 0; + + while (true) { + let ca: u8 = a[i]; + let cb: u8 = b[i]; + + if (ca != cb) { + return false; + } + + if (ca == 0) { + return true; + } + + i += 1; + } + + return true; +} + +fun cmp(a: str, b: str) -> i32 { + let mut i: i32 = 0; + + while (true) { + let ca: u8 = a[i]; + let cb: u8 = b[i]; + + if (ca < cb) { + return -1; + } + + if (ca > cb) { + return 1; + } + + if (ca == 0) { + return 0; + } + + i += 1; + } + + return 0; +} + +fun starts_with(s: str, prefix: str) -> bool { + let mut i: i32 = 0; + + while (prefix[i] != 0) { + if (s[i] != prefix[i]) { + return false; + } + + i += 1; + } + + return true; +} + +fun ends_with(s: str, suffix: str) -> bool { + let mut sl: i32 = 0; + while (s[sl] != 0) { + sl += 1; + } + + let mut tl: i32 = 0; + while (suffix[tl] != 0) { + tl += 1; + } + + if (tl > sl) { + return false; + } + + let mut i: i32 = 0; + while (i < tl) { + if (s[sl - tl + i] != suffix[i]) { + return false; + } + + i += 1; + } + + return true; +} diff --git a/std/string/find.wave b/std/string/find.wave new file mode 100644 index 00000000..40b087a6 --- /dev/null +++ b/std/string/find.wave @@ -0,0 +1,148 @@ +fun find_char(s: str, c: u8) -> i32 { + let mut i: i32 = 0; + + while (s[i] != 0) { + if (s[i] == c) { + return i; + } + + i += 1; + } + + return -1; +} + +fun rfind_char(s: str, c: u8) -> i32 { + let mut last: i32 = -1; + let mut i: i32 = 0; + + while (s[i] != 0) { + if (s[i] == c) { + last = i; + } + + i += 1; + } + + return last; +} + +fun contains_char(s: str, c: u8) -> bool { + if (find_char(s, c) != -1) { + return true; + } + + return false; +} + +fun count_char(s: str, c: u8) -> i32 { + let mut i: i32 = 0; + let mut count: i32 = 0; + + while (s[i] != 0) { + if (s[i] == c) { + count += 1; + } + + i += 1; + } + + return count; +} + +fun find(s: str, needle: str) -> i32 { + if (needle[0] == 0) { + return 0; + } + + let mut nl: i32 = 0; + while (needle[nl] != 0) { + nl += 1; + } + + let mut sl: i32 = 0; + while (s[sl] != 0) { + sl += 1; + } + + if (nl > sl) { + return -1; + } + + let mut i: i32 = 0; + while (i <= (sl - nl)) { + let mut j: i32 = 0; + let mut ok: bool = true; + + while (j < nl) { + if (s[i + j] != needle[j]) { + ok = false; + j = nl; + } else { + j += 1; + } + } + + if (ok) { + return i; + } + + i += 1; + } + + return -1; +} + +fun contains(s: str, needle: str) -> bool { + if (find(s, needle) != -1) { + return true; + } + + return false; +} + +fun count(s: str, needle: str) -> i32 { + if (needle[0] == 0) { + return 0; + } + + let mut nl: i32 = 0; + while (needle[nl] != 0) { + nl += 1; + } + + let mut sl: i32 = 0; + while (s[sl] != 0) { + sl += 1; + } + + if (nl > sl) { + return 0; + } + + let mut i: i32 = 0; + let mut total: i32 = 0; + + while (i <= (sl - nl)) { + let mut j: i32 = 0; + let mut ok: bool = true; + + while (j < nl) { + if (s[i + j] != needle[j]) { + ok = false; + j = nl; + } else { + j += 1; + } + } + + if (ok) { + total += 1; + i += nl; + } else { + i += 1; + } + } + + return total; +} diff --git a/std/string/hash.wave b/std/string/hash.wave new file mode 100644 index 00000000..e69de29b diff --git a/std/string/len.wave b/std/string/len.wave new file mode 100644 index 00000000..417d3c04 --- /dev/null +++ b/std/string/len.wave @@ -0,0 +1,14 @@ +fun len(s: str) -> i32 { + let mut i: i32 = 0; + while (s[i] != 0) { + i += 1; + } + return i; +} + +fun is_empty(s: str) -> bool { + if (s[0] == 0) { + return true; + } + return false; +} diff --git a/std/string/trim.wave b/std/string/trim.wave new file mode 100644 index 00000000..6a98e5f8 --- /dev/null +++ b/std/string/trim.wave @@ -0,0 +1,49 @@ +fun trim_left_index(s: str) -> i32 { + let mut i: i32 = 0; + + while (s[i] != 0) { + let c: u8 = s[i]; + + if (c == 32 || c == 9 || c == 10 || c == 13) { + i += 1; + } else { + return i; + } + } + + return i; +} + +fun trim_right_index(s: str) -> i32 { + let mut sl: i32 = 0; + + while (s[sl] != 0) { + sl += 1; + } + + if (sl == 0) { + return 0; + } + + let mut i: i32 = sl - 1; + + while (i >= 0) { + let c: u8 = s[i]; + + if (c == 32 || c == 9 || c == 10 || c == 13) { + i -= 1; + } else { + return i + 1; + } + } + + return 0; +} + +fun trim_range(s: str, out_start: ptr, out_end: ptr) { + let start: i32 = trim_left_index(s); + let end: i32 = trim_right_index(s); + + deref out_start = start; + deref out_end = end; +} diff --git a/test/test3.wave b/test/test3.wave index e4164624..305fb497 100644 --- a/test/test3.wave +++ b/test/test3.wave @@ -1,5 +1,3 @@ -import("std::iosys"); - fun main() { let a :i32 = 10; var b :i32 = 5; diff --git a/test/test58.wave b/test/test58.wave index 91b5fc6a..ca7c183c 100644 --- a/test/test58.wave +++ b/test/test58.wave @@ -1,5 +1,3 @@ -import("std::iosys"); - fun main() { println("This should fail in standalone mode"); } \ No newline at end of file