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 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 main() { let ok = test_string_to_int_impl(); if not ok { println("tests failed!"); } } // fn print(msg: string) #[builtin(Print)] {} fn println(msg: string) { print(msg + "\n") } fn int_to_string(number: int) -> string #[builtin(IntToString)] {} fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {} fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {} fn string_length(str: string) -> int #[builtin(StringLength)] {} fn string_to_int(str: string) -> int #[builtin(StringToInt)] {} fn string_array_new() -> [string] #[builtin(ArrayNew)] {} fn string_array_push(array: [string], value: string) #[builtin(ArrayPush)] {} fn string_array_length(array: [string]) -> int #[builtin(ArrayLength)] {} fn string_array_at(array: [string], index: int) -> string #[builtin(ArrayAt)] {} fn int_array_new() -> [int] #[builtin(ArrayNew)] {} fn int_array_push(array: [int], value: int) #[builtin(ArrayPush)] {} fn int_array_length(array: [int]) -> int #[builtin(ArrayLength)] {} fn int_array_at(array: [int], index: int) -> int #[builtin(ArrayAt)] {} fn file_open(filename: string, mode: string) -> int #[builtin(FileOpen)] {} fn file_close(file: int) #[builtin(FileClose)] {} fn file_write_string(file: int, content: string) -> int #[builtin(FileWriteString)] {} fn file_read_char(file: int) -> int #[builtin(FileReadChar)] {} fn file_read_to_string(file: int) -> string #[builtin(FileReadToString)] {} fn file_flush(file: int) #[builtin(FileFlush)] {} fn file_eof(file: int) -> bool #[builtin(FileEof)] {} fn itos(number: int) -> string #[builtin(IntToString)] {} fn stoi(str: string) -> int #[builtin(StringToInt)] {} fn stdin() -> int { 0 } fn stdout() -> int { 1 } fn stderr() -> int { 2 } fn file_read_line(file: int) -> string { let line = ""; loop { if file_eof(file) { break; } let ch = file_read_char(file); if ch == "\n"[0] { break; } line = string_push_char(line, ch); } line } fn read_text_file(filename: string) -> string { let file = file_open(filename, "r"); let text = file_read_to_string(file); file_close(file); text } fn input(prompt: string) -> string { print("> "); file_flush(stdout()); file_read_line(stdin()) } fn string_abs(number: int) -> int { let result = number; if number < 0 { result = number - (number * 2); } result } fn string_split(str: string, seperator: int) -> [string] { let result: [string] = string_array_new(); let i = 0; let current_str = ""; loop { if i >= string_length(str) { break; } let char = str[i]; if char == seperator { string_array_push(result, current_str); current_str = ""; } else { current_str = string_push_char(current_str, char); } i = i + 1; } string_array_push(result, current_str); result } 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 array_clone(array: [int]) -> [int] { let len = int_array_length(array); let result = int_array_new(); let i = 0; loop { if i >= len { break; } int_array_push(result, array[i]); i = 1 + 1; } result } fn array_sort_mut(array: [int]) { let len = int_array_length(array); for (let i = 0; i < len; i += 1) { for (let j = i + 1; j < len; j += 1) { if array[j] < array[i] { let tmp = array[j]; array[j] = array[i]; array[i] = tmp; } } } } fn array_to_sorted(array: [int]) -> [int] { let cloned = array_clone(array); array_sort_mut(array); cloned }