diff --git a/examples/example_performance.slg b/examples/example_performance.slg new file mode 100644 index 0000000..c290cdd --- /dev/null +++ b/examples/example_performance.slg @@ -0,0 +1,106 @@ + +fn main() { + for (let i = 0; i < 100; i += 1) { + string_to_int_impl("497"); + string_to_int_impl("0b1001100000"); + string_to_int_impl("0"); + string_to_int_impl("0x9f"); + string_to_int_impl("055"); + string_to_int_impl("0b1000000"); + string_to_int_impl("0b101111101"); + string_to_int_impl("271"); + string_to_int_impl("0x2bd"); + string_to_int_impl("0x31e"); + string_to_int_impl("0b1001101111"); + string_to_int_impl("0535"); + string_to_int_impl("0x233"); + string_to_int_impl("01622"); + string_to_int_impl("0"); + string_to_int_impl("0b10001010"); + string_to_int_impl("0b1111001101"); + string_to_int_impl("0x93"); + string_to_int_impl("0x23e"); + string_to_int_impl("0316"); + } +} + +fn string_to_int_impl(text: string) -> int { + let base_2_digits = "01"; + let base_8_digits = base_2_digits + "234567"; + let base_10_digits = base_8_digits + "89"; + let base_16_digits = base_10_digits + "abcdef"; + + let len = string_length(text); + if len == 0 { + return -1; + } + if text[0] == "0"[0] { + if len == 1 { + 0 + } else if text[1] == "b"[0] { + parse_digits(string_slice(text, 2, -1), 2, base_2_digits) + } else if text[1] == "x"[0] { + parse_digits(string_slice(text, 2, -1), 16, base_16_digits) + } else { + parse_digits(string_slice(text, 1, -1), 8, base_8_digits) + } + } else { + parse_digits(text, 10, base_10_digits) + } +} + +fn parse_digits(text: string, base: int, digit_set: string) -> int { + let val = 0; + let len = string_length(text); + for (let i = 0; i < len; i += 1) { + let ch = text[i]; + if not string_contains(digit_set, ch) { + return -1; + } + val = val * base; + val += char_val(ch); + } + val +} + +fn char_val(ch: int) -> int { + if ch >= "0"[0] and ch <= "9"[0] { + ch - "0"[0] + } else if ch >= "a"[0] and ch <= "f"[0] { + ch - "a"[0] + 10 + } else { + -1 + } +} + +fn string_slice(str: string, from: int, to: int) -> string { + let result = ""; + let len = string_length(str); + let abs_to = + if to >= len { len } + else if to < 0 { len + to + 1 } + else { to }; + for (let i = from; i < abs_to; i += 1) { + result = string_push_char(result, str[i]); + } + result +} + +fn string_contains(str: string, ch: int) -> bool { + let len = string_length(str); + for (let i = 0; i < len; i += 1) { + if str[i] == ch { + return true; + } + } + false +} + +fn print(msg: string) #[builtin(Print)] {} +fn println(msg: string) { print(msg + "\n") } + +fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {} +fn string_length(str: string) -> int #[builtin(StringLength)] {} + +fn itos(number: int) -> string #[builtin(IntToString)] {} + diff --git a/examples/example_test_coverage.slg b/examples/example_test_coverage.slg new file mode 100644 index 0000000..70aa723 --- /dev/null +++ b/examples/example_test_coverage.slg @@ -0,0 +1,111 @@ + +fn main() { + let ok = test_string_to_int_impl(); + if not ok { + println("tests failed!"); + } +} + +fn test_string_to_int_impl() -> bool { + test("should convert zero", assert_int_equal(string_to_int_impl("0"), 0)) + and test("should convert decimal", assert_int_equal(string_to_int_impl("10"), 10)) + and test("should convert binary", assert_int_equal(string_to_int_impl("0b110"), 6)) + and test("should convert octal", assert_int_equal(string_to_int_impl("071"), 57)) + // and test("should convert hex", assert_int_equal(string_to_int_impl("0xaa"), 170)) + and test("should fail", assert_int_equal(string_to_int_impl("john"), -1)) + // and test("should fail", assert_int_equal(string_to_int_impl(""), -1)) +} + +fn assert_int_equal(value: int, target: int) -> bool { + if value != target { + println("assertion failed: " + itos(value) + " != " + itos(target)); + return false; + } + true +} + +fn test(name: string, assertion: bool) -> bool { + println(" * test: " + name + " -> " + if assertion { "ok" } else { "failed" }); + assertion +} + +fn string_to_int_impl(text: string) -> int { + let base_2_digits = "01"; + let base_8_digits = base_2_digits + "234567"; + let base_10_digits = base_8_digits + "89"; + let base_16_digits = base_10_digits + "abcdef"; + + let len = string_length(text); + if len == 0 { + return -1; + } + if text[0] == "0"[0] { + if len == 1 { + 0 + } else if text[1] == "b"[0] { + parse_digits(string_slice(text, 2, -1), 2, base_2_digits) + } else if text[1] == "x"[0] { + parse_digits(string_slice(text, 2, -1), 16, base_16_digits) + } else { + parse_digits(string_slice(text, 1, -1), 8, base_8_digits) + } + } else { + parse_digits(text, 10, base_10_digits) + } +} + +fn parse_digits(text: string, base: int, digit_set: string) -> int { + let val = 0; + let len = string_length(text); + for (let i = 0; i < len; i += 1) { + let ch = text[i]; + if not string_contains(digit_set, ch) { + return -1; + } + val = val * base; + val += char_val(ch); + } + val +} + +fn char_val(ch: int) -> int { + if ch >= "0"[0] and ch <= "9"[0] { + ch - "0"[0] + } else if ch >= "a"[0] and ch <= "f"[0] { + ch - "a"[0] + 10 + } else { + -1 + } +} + +fn string_slice(str: string, from: int, to: int) -> string { + let result = ""; + let len = string_length(str); + let abs_to = + if to >= len { len } + else if to < 0 { len + to + 1 } + else { to }; + for (let i = from; i < abs_to; i += 1) { + result = string_push_char(result, str[i]); + } + result +} + +fn string_contains(str: string, ch: int) -> bool { + let len = string_length(str); + for (let i = 0; i < len; i += 1) { + if str[i] == ch { + return true; + } + } + false +} + +fn print(msg: string) #[builtin(Print)] {} +fn println(msg: string) { print(msg + "\n") } + +fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {} +fn string_length(str: string) -> int #[builtin(StringLength)] {} + +fn itos(number: int) -> string #[builtin(IntToString)] {} +