diff --git a/README.md b/README.md index 9325959..b796fd8 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ A very cool language * Clean indentation-based syntax * Compiles to x86_64 Assembly * Almost works +* Has the pipe operator ## Syntax ```rust diff --git a/examples/brainfuck.zr b/examples/brainfuck.zr index 028d061..96a2eed 100644 --- a/examples/brainfuck.zr +++ b/examples/brainfuck.zr @@ -1,45 +1,45 @@ func main[] : I64 // https://brainfuck.org/sierpinski.b let src: String = "++++++++[>+>++++<<-]>++>>+<[-[>>+<<-]+>>]>+[-<<<[->[+[-]+>++>>>-<<]<[<]>>++++++[<<+++++>>-]+<<++.[-]<<]>.>+[>>]>+]" - let src_len: I64 = strlen(src) + let src_len: I64 = c.strlen(src) let i: I64 = 0 - let memory: Ptr = calloc(1, 30000) + let memory: Ptr = c.calloc(1, 30000) let p: I64 = 0 while i < src_len - let op: U8 = String.nth(src, i) + let op: U8 = str.nth(src, i) if op == '>' p = p + 1 else if op == '<' p = p - 1 else if op == '+' - String.set(memory, p, String.nth(memory, p)+1) + str.set(memory, p, str.nth(memory, p)+1) else if op == '-' - String.set(memory, p, String.nth(memory, p)-1) + str.set(memory, p, str.nth(memory, p)-1) else if op == '.' - printf("%c", String.nth(memory, p)) + c.printf("%c", str.nth(memory, p)) else if op == ',' - String.set(memory, p, getchar()) + str.set(memory, p, c.getchar()) else if op == '[' - if !String.nth(memory, p) + if !str.nth(memory, p) i = i + 1 let opened: I64 = 0 - while i < src_len && !(String.nth(src, i) == ']' && !opened) - if String.nth(src, i) == '[' + while i < src_len && !(str.nth(src, i) == ']' && !opened) + if str.nth(src, i) == '[' opened = opened + 1 - else if String.nth(src, i) == ']' + else if str.nth(src, i) == ']' opened = opened - 1 i = i + 1 else if op == ']' - if String.nth(memory, p) + if str.nth(memory, p) i = i - 1 let closed: I64 = 0 - while i >= 0 && !(String.nth(src, i) == '[' && !closed) - if String.nth(src, i) == ']' + while i >= 0 && !(str.nth(src, i) == '[' && !closed) + if str.nth(src, i) == ']' closed = closed + 1 - else if String.nth(src, i) == '[' + else if str.nth(src, i) == '[' closed = closed - 1 i = i - 1 diff --git a/examples/euler1.zr b/examples/euler1.zr index cded008..dfc09cf 100644 --- a/examples/euler1.zr +++ b/examples/euler1.zr @@ -4,4 +4,4 @@ func main[] : I64 for i in 0..1000 if i % 5 == 0 || i % 3 == 0 sum = sum + i - print_i64(sum) \ No newline at end of file + io.print_i64(sum) \ No newline at end of file diff --git a/examples/euler10.zr b/examples/euler10.zr index 57a8d68..33f02ba 100644 --- a/examples/euler10.zr +++ b/examples/euler10.zr @@ -2,6 +2,6 @@ func main[] : I64 let sum: I64 = 0 for i in 0..2000000 - if Math.is_prime(i) + if math.is_prime(i) sum = sum + i - print_i64(sum) \ No newline at end of file + io.print_i64(sum) \ No newline at end of file diff --git a/examples/euler12.zr b/examples/euler12.zr index a5bd93e..5dbb9bb 100644 --- a/examples/euler12.zr +++ b/examples/euler12.zr @@ -1,5 +1,5 @@ func num_divisors[n: I64] : I64 - let end: I64 = Math.isqrt(n) + let end: I64 = math.isqrt(n) let out: I64 = 0 for i in 1..end+1 @@ -16,6 +16,6 @@ func main[] : I64 while true n = n + i if num_divisors(n) > 500 - print_i64(n) + io.print_i64(n) break i = i + 1 \ No newline at end of file diff --git a/examples/euler13.zr b/examples/euler13.zr index 12b5d88..1bd21eb 100644 --- a/examples/euler13.zr +++ b/examples/euler13.zr @@ -1,5 +1,5 @@ func main[] : I64 37107287533 + 46376937677 + 74324986199 + 91942213363 + 23067588207 + 89261670696 + 28112879812 + 44274228917 + 47451445736 + 70386486105 + 62176457141 + 64906352462 + 92575867718 + 58203565325 + 80181199384 + 35398664372 + 86515506006 + 71693888707 + 54370070576 + 53282654108 + 36123272525 + 45876576172 + 17423706905 + 81142660418 + 51934325451 + 62467221648 + 15732444386 + 55037687525 + 18336384825 + 80386287592 + 78182833757 + 16726320100 + 48403098129 + 87086987551 + 59959406895 + 69793950679 + 41052684708 + 65378607361 + 35829035317 + 94953759765 + 88902802571 + 25267680276 + 36270218540 + 24074486908 + 91430288197 + 34413065578 + 23053081172 + 11487696932 + 63783299490 + 67720186971 + 95548255300 + 76085327132 + 37774242535 + 23701913275 + 29798860272 + 18495701454 + 38298203783 + 34829543829 + 40957953066 + 29746152185 + 41698116222 + 62467957194 + 23189706772 + 86188088225 + 11306739708 + 82959174767 + 97623331044 + 42846280183 + 55121603546 + 32238195734 + 75506164965 + 62177842752 + 32924185707 + 99518671430 + 73267460800 + 76841822524 + 97142617910 + 87783646182 + 10848802521 + 71329612474 + 62184073572 + 66627891981 + 60661826293 + 85786944089 + 66024396409 + 64913982680 + 16730939319 + 94809377245 + 78639167021 + 15368713711 + 40789923115 + 44889911501 + 41503128880 + 81234880673 + 82616570773 + 22918802058 + 77158542502 + 72107838435 + 20849603980 + 53503534226 - |> I64.to_string() - |> String.substr(0, 10) - |> print() \ No newline at end of file + |> str.from_i64() + |> str.substr(0, 10) + |> io.print() \ No newline at end of file diff --git a/examples/euler14.zr b/examples/euler14.zr index d570e72..11a43c1 100644 --- a/examples/euler14.zr +++ b/examples/euler14.zr @@ -19,4 +19,4 @@ func main[] : I64 if seq > max max = seq max_index = i - print_i64(max_index) \ No newline at end of file + io.print_i64(max_index) \ No newline at end of file diff --git a/examples/euler15.zr b/examples/euler15.zr index defd65e..f9ce07b 100644 --- a/examples/euler15.zr +++ b/examples/euler15.zr @@ -6,4 +6,4 @@ func main[] : I64 for i in 1..r+1 out = out * (n - (r - i)) / i - print_i64(out) \ No newline at end of file + io.print_i64(out) \ No newline at end of file diff --git a/examples/euler2.zr b/examples/euler2.zr index 6bb61c0..9714c64 100644 --- a/examples/euler2.zr +++ b/examples/euler2.zr @@ -10,4 +10,4 @@ func main[] : I64 b = a + b a = temp - print_i64(sum) \ No newline at end of file + io.print_i64(sum) \ No newline at end of file diff --git a/examples/euler3.zr b/examples/euler3.zr index 3dc3736..d3ce76b 100644 --- a/examples/euler3.zr +++ b/examples/euler3.zr @@ -8,4 +8,4 @@ func main[] : I64 else f = f + 1 - print_i64(n) \ No newline at end of file + io.print_i64(n) \ No newline at end of file diff --git a/examples/euler4.zr b/examples/euler4.zr index e083b20..8dc3a2a 100644 --- a/examples/euler4.zr +++ b/examples/euler4.zr @@ -4,10 +4,10 @@ func main[] : I64 for a in 500..1000 for b in 500..1000 if a * b > out - let s: String = I64.to_string(a * b) - let s_rev: String = String.rev(s) - if strcmp(s, s_rev) == 0 + let s: String = str.from_i64(a * b) + let s_rev: String = str.reverse(s) + if c.strcmp(s, s_rev) == 0 out = a * b - free(s) - free(s_rev) - print_i64(out) \ No newline at end of file + c.free(s) + c.free(s_rev) + io.print_i64(out) \ No newline at end of file diff --git a/examples/euler5.zr b/examples/euler5.zr index 8920438..d46e565 100644 --- a/examples/euler5.zr +++ b/examples/euler5.zr @@ -2,5 +2,5 @@ func main[] : I64 let out: I64 = 1 for i in 1..21 - out = Math.lcm(out, i) - print_i64(out) \ No newline at end of file + out = math.lcm(out, i) + io.print_i64(out) \ No newline at end of file diff --git a/examples/euler6.zr b/examples/euler6.zr index 95072be..98adbf1 100644 --- a/examples/euler6.zr +++ b/examples/euler6.zr @@ -8,4 +8,4 @@ func main[] : I64 square_of_sum = square_of_sum + i square_of_sum = square_of_sum * square_of_sum - print_i64(square_of_sum - sum_of_squares) \ No newline at end of file + io.print_i64(square_of_sum - sum_of_squares) \ No newline at end of file diff --git a/examples/euler7.zr b/examples/euler7.zr index b4a4961..db51b02 100644 --- a/examples/euler7.zr +++ b/examples/euler7.zr @@ -3,9 +3,9 @@ func main[] : I64 let i: I64 = 1 while true - if Math.is_prime(i) + if math.is_prime(i) found = found + 1 if found == 10001 - print_i64(i) + io.print_i64(i) break i = i + 1 \ No newline at end of file diff --git a/examples/euler8.zr b/examples/euler8.zr index 9bc1f6a..db8adbc 100644 --- a/examples/euler8.zr +++ b/examples/euler8.zr @@ -2,13 +2,13 @@ func main[] : I64 let n: String = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450" let out: I64 = 0 - let max: I64 = strlen(n) - 13 + let max: I64 = c.strlen(n) - 13 for i in 0..max let s: I64 = 1 let j: I64 = 0 while j < 13 - s = s * (String.nth(n, i + j) - '0') + s = s * (str.nth(n, i + j) - '0') j = j + 1 if s > out out = s - print_i64(out) \ No newline at end of file + io.print_i64(out) \ No newline at end of file diff --git a/examples/euler9.zr b/examples/euler9.zr index 8a2016d..f120000 100644 --- a/examples/euler9.zr +++ b/examples/euler9.zr @@ -3,5 +3,5 @@ func main[] : I64 for b in 1..1000 let c: I64 = 1000 - b - a if a * a + b * b == c * c - print_i64(a * b * c) + io.print_i64(a * b * c) return 0 \ No newline at end of file diff --git a/examples/fib.zr b/examples/fib.zr index afe69ec..0840eab 100644 --- a/examples/fib.zr +++ b/examples/fib.zr @@ -3,7 +3,7 @@ func main[] : I64 let b: I64 = 1 while a < 100000 - print_i64(a) + io.print_i64(a) let temp: I64 = b b = a + b a = temp \ No newline at end of file diff --git a/examples/guess_number.zr b/examples/guess_number.zr index f33c24a..e9f8c23 100644 --- a/examples/guess_number.zr +++ b/examples/guess_number.zr @@ -1,14 +1,14 @@ func main[] : I64 - let answer: I64 = Math.abs(Math.urandom()) % 100 + let answer: I64 = math.abs(math.urandom()) % 100 while true - print("Guess a number: ") - let guess: I64 = IO.read_line() |> String.trim() |> I64.parse() + io.print("Guess a number: ") + let guess: I64 = io.read_line() |> str.trim() |> str.parse_i64() if guess == answer - print("You win!") + io.print("You win!") break else if guess < answer - print("Too low!") + io.print("Too low!") else - print("Too high!") \ No newline at end of file + io.print("Too high!") \ No newline at end of file diff --git a/examples/hello.zr b/examples/hello.zr index d6e4f48..baad92e 100644 --- a/examples/hello.zr +++ b/examples/hello.zr @@ -1,2 +1,2 @@ func main[] : I64 - print("Hello, World!") \ No newline at end of file + io.print("Hello, World!") \ No newline at end of file diff --git a/examples/quicksort.zr b/examples/quicksort.zr index 70b0a4e..eddd5f5 100644 --- a/examples/quicksort.zr +++ b/examples/quicksort.zr @@ -1,5 +1,5 @@ func quicksort[arr: Array] : Void - do_quicksort(arr, 0, Array.size(arr)-1) + do_quicksort(arr, 0, array.size(arr)-1) func do_quicksort[arr: Array, low: I64, high: I64] : Void if low < high @@ -14,23 +14,23 @@ func partition[arr: Array, low: I64, high: I64] : I64 if arr[j] <= pivot i = i + 1 let temp: I64 = arr[i] - Array.set(arr, i, arr[j]) - Array.set(arr, j, temp) + array.set(arr, i, arr[j]) + array.set(arr, j, temp) let temp: I64 = arr[i + 1] - Array.set(arr, i + 1, arr[high]) - Array.set(arr, high, temp) + array.set(arr, i + 1, arr[high]) + array.set(arr, high, temp) return i + 1 func main[] : I64 let arr: Array = [] for i in 0..10 - Array.push(arr, Math.abs(Math.urandom() % 1000)) + array.push(arr, math.abs(math.urandom() % 1000)) - for i in 0..Array.size(arr) - print_i64(arr[i]) - print("------------") + for i in 0..array.size(arr) + io.print_i64(arr[i]) + io.print("------------") quicksort(arr) - for i in 0..Array.size(arr) - print_i64(arr[i]) \ No newline at end of file + for i in 0..array.size(arr) + io.print_i64(arr[i]) \ No newline at end of file diff --git a/examples/rule110.zr b/examples/rule110.zr index 410a7f6..4915389 100644 --- a/examples/rule110.zr +++ b/examples/rule110.zr @@ -1,6 +1,6 @@ func rule110_step[state: Array] : Array let new_state: Array = [] - let state_len: I64 = Array.size(state) + let state_len: I64 = array.size(state) for i in 0..state_len let left: Bool = false @@ -11,17 +11,17 @@ func rule110_step[state: Array] : Array if i + 1 < state_len right = state[i+1] - Array.push(new_state, !((!left && !center && !right) || (left && !center && !right) || (left && center && right))) + array.push(new_state, !((!left && !center && !right) || (left && !center && !right) || (left && center && right))) return new_state func to_str[state: Array]: String - let out: String = malloc(Array.size(state)) - for i in 0..Array.size(state) + let out: String = malloc(array.size(state)) + for i in 0..array.size(state) if state[i] - String.set(out, i, '#') + str.set(out, i, '#') else - String.set(out, i, ' ') + str.set(out, i, ' ') return out func main[] : I64 @@ -29,10 +29,10 @@ func main[] : I64 let state: Array = [] for i in 0..SIZE - Array.push(state, false) - Array.push(state, true) + array.push(state, false) + array.push(state, true) - print(to_str(state)) + io.print(to_str(state)) for i in 0..SIZE state = rule110_step(state) - print(to_str(state)) \ No newline at end of file + io.print(to_str(state)) \ No newline at end of file diff --git a/examples/tcp_client.zr b/examples/tcp_client.zr index edab374..5f966ee 100644 --- a/examples/tcp_client.zr +++ b/examples/tcp_client.zr @@ -1,31 +1,31 @@ func main[] : I64 - let s: I64 = socket(2, 1, 0) + let s: I64 = c.socket(2, 1, 0) if s < 0 - panic("socket() failed") + dbg.panic("socket() failed") let port: I64 = 80 - let sa: Ptr = calloc(1, 16) - String.set(sa, 0, 2) - String.set(sa, 1, 0) - String.set(sa, 2, Bit.rshift(port, 8) && 255) - String.set(sa, 3, port && 255) + let sa: Ptr = c.calloc(1, 16) + str.set(sa, 0, 2) + str.set(sa, 1, 0) + str.set(sa, 2, bit.rshift(port, 8) && 255) + str.set(sa, 3, port && 255) // 23.192.228.80 (example.com) - String.set(sa, 4, 23) - String.set(sa, 5, 192) - String.set(sa, 6, 228) - String.set(sa, 7, 80) + str.set(sa, 4, 23) + str.set(sa, 5, 192) + str.set(sa, 6, 228) + str.set(sa, 7, 80) - if connect(s, sa, 16) < 0 - panic("connect() failed") - free(sa) + if c.connect(s, sa, 16) < 0 + dbg.panic("connect() failed") + c.free(sa) let req: String = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" - send(s, req, strlen(req), 0) + c.send(s, req, c.strlen(req), 0) - let resp: String = malloc(60000) - let n: I64 = read(s, resp, 60000) - String.set(resp, n, 0) - print(resp) - free(resp) + let resp: String = c.malloc(60000) + let n: I64 = c.read(s, resp, 60000) + str.set(resp, n, 0) + io.print(resp) + c.free(resp) - close(s) \ No newline at end of file + c.close(s) \ No newline at end of file diff --git a/examples/tcp_server.zr b/examples/tcp_server.zr index fd2fea7..ee847a9 100644 --- a/examples/tcp_server.zr +++ b/examples/tcp_server.zr @@ -1,27 +1,27 @@ func main[] : I64 - let s: I64 = socket(2, 1, 0) + let s: I64 = c.socket(2, 1, 0) if s < 0 - panic("socket() failed") + dbg.panic("socket() failed") let port: I64 = 8080 - let sa: Ptr = calloc(1, 16) - String.set(sa, 0, 2) - String.set(sa, 1, 0) - String.set(sa, 2, Bit.rshift(port, 8) && 255) - String.set(sa, 3, port && 255) + let sa: Ptr = c.calloc(1, 16) + str.set(sa, 0, 2) + str.set(sa, 1, 0) + str.set(sa, 2, bit.rshift(port, 8) && 255) + str.set(sa, 3, port && 255) - if bind(s, sa, 16) < 0 - panic("bind() failed") + if c.bind(s, sa, 16) < 0 + dbg.panic("bind() failed") - if listen(s, 1) < 0 - panic("listen() failed") + if c.listen(s, 1) < 0 + dbg.panic("listen() failed") - let resp: String = malloc(60000) + let resp: String = c.malloc(60000) while true - let c: I64 = accept(s, 0, 0) + let c: I64 = c.accept(s, 0, 0) if c < 0 - panic("accept() failed") + dbg.panic("accept() failed") - let n: I64 = read(c, resp, 60000) - send(c, resp, n, 0) - close(c) \ No newline at end of file + let n: I64 = c.read(c, resp, 60000) + c.send(c, resp, n, 0) + c.close(c) \ No newline at end of file diff --git a/src/codegen_x86_64.rs b/src/codegen_x86_64.rs index f1e9af1..1ecc4e7 100644 --- a/src/codegen_x86_64.rs +++ b/src/codegen_x86_64.rs @@ -100,44 +100,80 @@ impl CodegenX86_64 { db 0 section .text -extern stdin extern malloc +c.malloc equ malloc extern calloc +c.calloc equ calloc extern realloc +c.realloc equ realloc extern free +c.free equ free +extern puts +c.puts equ puts extern printf +c.printf equ printf extern sprintf +c.sprintf equ sprintf extern strtol +c.strtol equ strtol extern strlen +c.strlen equ strlen extern strcmp +c.strcmp equ strcmp extern strcat +c.strcat equ strcat extern strcpy +c.strcpy equ strcpy extern strdup +c.strdup equ strdup extern strncpy +c.strncpy equ strncpy extern syscall +c.syscall equ syscall extern fopen +c.fopen equ fopen extern fseek +c.fseek equ fseek extern ftell +c.ftell equ ftell extern fread +c.fread equ fread extern fwrite +c.fwrite equ fwrite extern fclose +c.fclose equ fclose extern rewind +c.rewind equ rewind extern system +c.system equ system extern opendir +c.opendir equ opendir extern readdir +c.readdir equ readdir extern closedir +c.closedir equ closedir extern exit +c.exit equ exit extern gettimeofday +c.gettimeofday equ gettimeofday extern connect -extern inet_addr +c.connect equ connect extern socket +c.socket equ socket extern send +c.send equ send extern read +c.read equ read extern close +c.close equ close extern bind +c.bind equ bind extern listen +c.listen equ listen extern accept +c.accept equ accept extern getchar +c.getchar equ getchar section .text._builtin_deref8 _builtin_deref8: @@ -418,22 +454,19 @@ _builtin_rshift: .replace("\\033", "\x1b") .replace("\\0", "\0"); + let label = format!("str_{:03}", self.data_counter); + if value.is_empty() { - emit!(&mut self.data_section, " S{} db 0", self.data_counter); + emit!(&mut self.data_section, " {} db 0", label); } else { let charcodes = value .chars() .map(|x| (x as u8).to_string()) .collect::>() .join(","); - emit!( - &mut self.data_section, - " S{} db {},0", - self.data_counter, - charcodes, - ); + emit!(&mut self.data_section, " {} db {},0", label, charcodes,); } - emit!(&mut self.output, " mov rax, S{}", self.data_counter); + emit!(&mut self.output, " mov rax, {}", label); self.data_counter += 1; } TokenType::True => { @@ -512,7 +545,7 @@ _builtin_rshift: emit!(&mut self.output, " call {}", callee); } Expr::ArrayLiteral(exprs) => { - emit!(&mut self.output, " call Array.new"); + emit!(&mut self.output, " call array.new"); emit!(&mut self.output, " push rax"); for expr in exprs { @@ -520,7 +553,7 @@ _builtin_rshift: emit!(&mut self.output, " mov rsi, rax"); emit!(&mut self.output, " pop rdi"); emit!(&mut self.output, " push rdi"); - emit!(&mut self.output, " call Array.push"); + emit!(&mut self.output, " call array.push"); } emit!(&mut self.output, " pop rax"); } diff --git a/src/std.zr b/src/std.zr index 84744c5..54c6e84 100644 --- a/src/std.zr +++ b/src/std.zr @@ -1,136 +1,136 @@ -func panic[msg: String] : Void - printf("PANIC: %s\n", msg) - exit(1) +func dbg.panic[msg: String] : Void + c.printf("PANIC: %s\n", msg) + c.exit(1) -func print[x: String] : Void - printf("%s\n", x) +func io.print[x: String] : Void + c.puts(x) -func print_i64[x: I64] : Void - printf("%ld\n", x) +func io.print_i64[x: I64] : Void + c.printf("%ld\n", x) -func String.nth[s: String, n: I64] : U8 +func str.nth[s: String, n: I64] : U8 return _builtin_deref8(s + n) -func String.set[s: String, n: I64, c: U8] : Void +func str.set[s: String, n: I64, c: U8] : Void _builtin_set8(s+n, c) -func String.is_whitespace[c: U8] : Bool +func str.is_whitespace[c: U8] : Bool return c == ' ' || c == 10 || c == 13 || c == 9 -func String.concat[a: String, b: String] : String - let c: String = malloc(strlen(a) + strlen(b) + 1) - strcpy(c, a) - strcat(c, b) +func str.concat[a: String, b: String] : String + let c: String = c.malloc(c.strlen(a) + c.strlen(b) + 1) + c.strcpy(c, a) + c.strcat(c, b) return c -func String.find[s: String, c: U8] : I64 - let s_len: I64 = strlen(s) +func str.find[s: String, c: U8] : I64 + let s_len: I64 = c.strlen(s) for i in 0..s_len - if String.nth(s, i) == c + if str.nth(s, i) == c return i return -1 -func String.substr[s: String, start: I64, length: I64] : String - if start < 0 || length < 0 || start + length > strlen(s) - panic("String.substr out of bounds") +func str.substr[s: String, start: I64, length: I64] : String + if start < 0 || length < 0 || start + length > c.strlen(s) + dbg.panic("String.substr out of bounds") - let out: String = malloc(length + 1) - strncpy(out, s + start, length) - String.set(out, length, 0) + let out: String = c.malloc(length + 1) + c.strncpy(out, s + start, length) + str.set(out, length, 0) return out -func String.trim[s: String] : String +func str.trim[s: String] : String let start: I64 = 0 - let end: I64 = strlen(s) - 1 + let end: I64 = c.strlen(s) - 1 - while start <= end && String.is_whitespace(String.nth(s, start)) + while start <= end && str.is_whitespace(str.nth(s, start)) start = start + 1 - while end >= start && String.is_whitespace(String.nth(s, end)) + while end >= start && str.is_whitespace(str.nth(s, end)) end = end - 1 - return String.substr(s, start, end - start + 1) + return str.substr(s, start, end - start + 1) -func String.rev[s: String] : String - let len: I64 = strlen(s) - let out: String = malloc(len + 1) +func str.reverse[s: String] : String + let len: I64 = c.strlen(s) + let out: String = c.malloc(len + 1) for i in 0..len - String.set(out, i, String.nth(s, len - i - 1)) - String.set(out, len, 0) + str.set(out, i, str.nth(s, len - i - 1)) + str.set(out, len, 0) return out -func IO.read_line[]: String - let buffer: String = malloc(1024) +func io.read_line[]: String + let buffer: String = c.malloc(1024) let sys_read: I64 = 0 let stdin: I64 = 0 - syscall(sys_read, stdin, buffer, 1024) + c.syscall(sys_read, stdin, buffer, 1024) return buffer -func IO.read_file[path: String]: String - let file: Ptr = fopen(path, "rb") +func io.read_file[path: String]: String + let file: Ptr = c.fopen(path, "rb") if !file - panic("failed to open file") + dbg.panic("failed to open file") - fseek(file, 0, 2) - let size: I64 = ftell(file) - rewind(file) + c.fseek(file, 0, 2) + let size: I64 = c.ftell(file) + c.rewind(file) - let buffer: String = malloc(size + 1) + let buffer: String = c.malloc(size + 1) - let n: I64 = fread(buffer, 1, size, file) - String.set(buffer, n, 0) - fclose(file) + let n: I64 = c.fread(buffer, 1, size, file) + str.set(buffer, n, 0) + c.fclose(file) return buffer -func IO.write_file[path: String, content: String] : Void - let file: Ptr = fopen(path, "wb") +func io.write_file[path: String, content: String] : Void + let file: Ptr = c.fopen(path, "wb") if !file - panic("failed to open file") + dbg.panic("failed to open file") - fwrite(content, 1, strlen(content), file) - fclose(file) + c.fwrite(content, 1, c.strlen(content), file) + c.fclose(file) -func I64.to_string[n: I64] : String - let x: String = malloc(21) - sprintf(x, "%ld", n) +func str.from_i64[n: I64] : String + let x: String = c.malloc(21) + c.sprintf(x, "%ld", n) return x -func I64.parse[s: String] : I64 - return strtol(s, 0, 0) +func str.parse_i64[s: String] : I64 + return c.strtol(s, 0, 0) -func Math.gcd[a: I64, b: I64] : I64 +func math.gcd[a: I64, b: I64] : I64 while b != 0 let tmp: I64 = b b = a % b a = tmp return a -func Math.min[a: I64, b: I64] : I64 +func math.min[a: I64, b: I64] : I64 if a < b return a return b -func Math.max[a: I64, b: I64] : I64 +func math.max[a: I64, b: I64] : I64 if a > b return a return b -func Math.abs[n: I64] : I64 +func math.abs[n: I64] : I64 if n < 0 return -n return n -func Math.pow[b: I64, e: I64] : I64 +func math.pow[b: I64, e: I64] : I64 let out: I64 = 1 for i in 0..e out = out * b return out -func Math.lcm[a: I64, b: I64] : I64 - return (a * b) / Math.gcd(a, b) +func math.lcm[a: I64, b: I64] : I64 + return (a * b) / math.gcd(a, b) -func Math.isqrt[n: I64] : I64 +func math.isqrt[n: I64] : I64 if n < 0 return -1 if n == 0 || n == 1 @@ -145,7 +145,7 @@ func Math.isqrt[n: I64] : I64 return guess -func Math.is_prime[n: I64]: Bool +func math.is_prime[n: I64]: Bool if n <= 1 return false if n == 2 || n == 3 @@ -160,23 +160,23 @@ func Math.is_prime[n: I64]: Bool i = i + 6 return true -func Math.urandom[]: I64 - let buffer: Ptr = malloc(8) - let file: Ptr = fopen("/dev/urandom", "rb") - fread(buffer, 8, 1, file) - fclose(file) +func math.urandom[]: I64 + let buffer: Ptr = c.malloc(8) + let file: Ptr = c.fopen("/dev/urandom", "rb") + c.fread(buffer, 8, 1, file) + c.fclose(file) let n: I64 = _builtin_deref64(buffer) - free(buffer) + c.free(buffer) return n -func Array.new[] : Array - return calloc(1, 24) +func array.new[] : Array + return c.calloc(1, 24) -func Array.set[xs: Array, n: I64, x: I64] : Void +func array.set[xs: Array, n: I64, x: I64] : Void let data: Ptr = _builtin_deref64(xs) _builtin_set64(data+n*8, x) -func Array.push[xs: Array, x: I64] : Void +func array.push[xs: Array, x: I64] : Void let data: Ptr = _builtin_deref64(xs) let capacity: I64 = _builtin_deref64(xs+8) let size: I64 = _builtin_deref64(xs+16) @@ -185,7 +185,7 @@ func Array.push[xs: Array, x: I64] : Void let new_capacity: I64 = 4 if capacity != 0 new_capacity = capacity * 2 - let new_data: Ptr = realloc(data, new_capacity * 8) + let new_data: Ptr = c.realloc(data, new_capacity * 8) _builtin_set64(xs, new_data) _builtin_set64(xs+8, new_capacity) data = new_data @@ -193,185 +193,185 @@ func Array.push[xs: Array, x: I64] : Void _builtin_set64(data+size*8, x) _builtin_set64(xs+16, size + 1) -func Array.size[xs: Array] : I64 +func array.size[xs: Array] : I64 return _builtin_deref64(xs+16) -func Array.free[xs: Array] : Void - free(_builtin_deref64(xs)) - free(xs) +func array.free[xs: Array] : Void + c.free(_builtin_deref64(xs)) + c.free(xs) -func OS.time[] : I64 - let tv: Ptr = malloc(16) - gettimeofday(tv, 0) +func os.time[] : I64 + let tv: Ptr = c.malloc(16) + c.gettimeofday(tv, 0) let seconds: I64 = _builtin_deref64(tv) let microseconds: I64 = _builtin_deref64(tv+8) - free(tv) + c.free(tv) return seconds * 1000 + microseconds / 1000 -func OS.listdir[path: String] : Array - let dir: Ptr = opendir(path) +func os.listdir[path: String] : Array + let dir: Ptr = c.opendir(path) let files: Array = [] while true - let entry: Ptr = readdir(dir) + let entry: Ptr = c.readdir(dir) if entry == 0 break let skip: Bool = false - if String.nth(entry, 19) == '.' - if String.nth(entry, 20) == 0 + if str.nth(entry, 19) == '.' + if str.nth(entry, 20) == 0 skip = true - else if String.nth(entry, 20) == '.' - if String.nth(entry, 21) == 0 + else if str.nth(entry, 20) == '.' + if str.nth(entry, 21) == 0 skip = true if !skip - Array.push(files, strdup(entry + 19)) - closedir(dir) + array.push(files, c.strdup(entry + 19)) + c.closedir(dir) return files -func Bit.lshift[a: I64, b: I64] : I64 +func bit.lshift[a: I64, b: I64] : I64 return _builtin_lshift(a, b) -func Bit.rshift[a: I64, b: I64] : I64 +func bit.rshift[a: I64, b: I64] : I64 return _builtin_rshift(a, b) -func Crypto.hex_encode[s: String] : String +func crypto.hex_encode[s: String] : String let hex_chars: String = "0123456789abcdef" - let s_len: I64 = strlen(s) + let s_len: I64 = c.strlen(s) let j: I64 = 0 - let out: String = malloc(s_len*2+1) + let out: String = c.malloc(s_len*2+1) for i in 0..s_len - let high: U8 = Bit.rshift(String.nth(s, i), 4) && 15 - let low: U8 = String.nth(s, i) && 15 - String.set(out, j, String.nth(hex_chars, high)) - String.set(out, j+1, String.nth(hex_chars, low)) + let high: U8 = bit.rshift(str.nth(s, i), 4) && 15 + let low: U8 = str.nth(s, i) && 15 + str.set(out, j, str.nth(hex_chars, high)) + str.set(out, j+1, str.nth(hex_chars, low)) j = j + 2 - String.set(out, j, 0) + str.set(out, j, 0) return out -func Crypto.from_hex_digit[d: U8] : I64 +func crypto.from_hex_digit[d: U8] : I64 if d >= 'a' && d <= 'f' return d - 'a' + 10 if d >= 'A' && d <= 'F' return d - 'A' + 10 return d - '0' -func Crypto.hex_decode[s: String] : String - let s_len: I64 = strlen(s) +func crypto.hex_decode[s: String] : String + let s_len: I64 = c.strlen(s) let i: I64 = 0 let j: I64 = 0 - let out: String = malloc(s_len/2+1) + let out: String = c.malloc(s_len/2+1) while i < s_len - String.set(out, j, Crypto.from_hex_digit(String.nth(s, i)) * 16 + Crypto.from_hex_digit(String.nth(s, i+1))) + str.set(out, j, crypto.from_hex_digit(str.nth(s, i)) * 16 + crypto.from_hex_digit(str.nth(s, i+1))) i = i + 2 j = j + 1 - String.set(out, j, 0) + str.set(out, j, 0) return out -func Crypto.rc4[key: String, plaintext: String]: String - let S: String = malloc(256) +func crypto.rc4[key: String, plaintext: String]: String + let S: String = c.malloc(256) for i in 0..256 - String.set(S, i, i) + str.set(S, i, i) let j: I64 = 0 - let key_len: I64 = strlen(key) + let key_len: I64 = c.strlen(key) for i in 0..256 - j = (j + String.nth(S, i) + String.nth(key, i % key_len)) % 256 - let tmp: U8 = String.nth(S, i) - String.set(S, i, String.nth(S, j)) - String.set(S, j, tmp) + j = (j + str.nth(S, i) + str.nth(key, i % key_len)) % 256 + let tmp: U8 = str.nth(S, i) + str.set(S, i, str.nth(S, j)) + str.set(S, j, tmp) let i: I64 = 0 j = 0 - let plaintext_len: I64 = strlen(plaintext) - let ciphertext: String = malloc(plaintext_len+1) + let plaintext_len: I64 = c.strlen(plaintext) + let ciphertext: String = c.malloc(plaintext_len+1) for n in 0..plaintext_len i = (i + 1) % 256 - j = (j + String.nth(S, i)) % 256 + j = (j + str.nth(S, i)) % 256 - let tmp: U8 = String.nth(S, i) - String.set(S, i, String.nth(S, j)) - String.set(S, j, tmp) + let tmp: U8 = str.nth(S, i) + str.set(S, i, str.nth(S, j)) + str.set(S, j, tmp) - let r: I64 = String.nth(S, (String.nth(S, i) + String.nth(S, j)) % 256) - String.set(ciphertext, n, r ^ String.nth(plaintext, n)) + let r: I64 = str.nth(S, (str.nth(S, i) + str.nth(S, j)) % 256) + str.set(ciphertext, n, r ^ str.nth(plaintext, n)) - String.set(ciphertext, plaintext_len, 0) - free(S) + str.set(ciphertext, plaintext_len, 0) + c.free(S) return ciphertext -func Crypto.base64_encode[s: String] : String +func crypto.base64_encode[s: String] : String let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - let s_len: I64 = strlen(s) - let out: String = malloc(s_len*2) + let s_len: I64 = c.strlen(s) + let out: String = c.malloc(s_len*2) let i: I64 = 0 let j: I64 = 0 while i < s_len - let b1: U8 = String.nth(s, i) + let b1: U8 = str.nth(s, i) let b2: U8 = 0 if i + 1 < s_len - b2 = String.nth(s, i+1) + b2 = str.nth(s, i+1) let b3: U8 = 0 if i + 2 < s_len - b3 = String.nth(s, i+2) + b3 = str.nth(s, i+2) i = i + 3 - let triple: I64 = Bit.lshift(b1, 16) || Bit.lshift(b2, 8) || b3 - String.set(out, j, String.nth(chars, Bit.rshift(triple, 18) && 63)) - String.set(out, j+1, String.nth(chars, Bit.rshift(triple, 12) && 63)) - String.set(out, j+2, String.nth(chars, Bit.rshift(triple, 6) && 63)) - String.set(out, j+3, String.nth(chars, triple && 63)) + let triple: I64 = bit.lshift(b1, 16) || bit.lshift(b2, 8) || b3 + str.set(out, j, str.nth(chars, bit.rshift(triple, 18) && 63)) + str.set(out, j+1, str.nth(chars, bit.rshift(triple, 12) && 63)) + str.set(out, j+2, str.nth(chars, bit.rshift(triple, 6) && 63)) + str.set(out, j+3, str.nth(chars, triple && 63)) j = j + 4 let padding: I64 = s_len % 3 if padding == 1 - String.set(out, j-2, '=') - String.set(out, j-1, '=') + str.set(out, j-2, '=') + str.set(out, j-1, '=') else if padding == 2 - String.set(out, j-1, '=') + str.set(out, j-1, '=') - String.set(out, j, 0) + str.set(out, j, 0) return out -func Crypto.base64_decode[s: String] : String +func crypto.base64_decode[s: String] : String let chars: String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - let s_len: I64 = strlen(s) - let out: String = malloc(s_len) + let s_len: I64 = c.strlen(s) + let out: String = c.malloc(s_len) let i: I64 = 0 let j: I64 = 0 - while String.nth(s, s_len-1) == '=' + while str.nth(s, s_len-1) == '=' s_len = s_len - 1 while i < s_len - let s1: U8 = String.find(chars, String.nth(s, i)) + let s1: U8 = str.find(chars, str.nth(s, i)) let s2: U8 = 0 if i + 1 < s_len - s2 = String.find(chars, String.nth(s, i+1)) + s2 = str.find(chars, str.nth(s, i+1)) let s3: U8 = 0 if i + 2 < s_len - s3 = String.find(chars, String.nth(s, i+2)) + s3 = str.find(chars, str.nth(s, i+2)) let s4: U8 = 0 if i + 3 < s_len - s4 = String.find(chars, String.nth(s, i+3)) + s4 = str.find(chars, str.nth(s, i+3)) i = i + 4 - let triple: I64 = Bit.lshift(s1, 18) || Bit.lshift(s2, 12) || Bit.lshift(s3, 6) || s4 + let triple: I64 = bit.lshift(s1, 18) || bit.lshift(s2, 12) || bit.lshift(s3, 6) || s4 - String.set(out, j, Bit.rshift(triple, 16) && 255) + str.set(out, j, bit.rshift(triple, 16) && 255) j = j + 1 if s3 != 64 - String.set(out, j, Bit.rshift(triple, 8) && 255) + str.set(out, j, bit.rshift(triple, 8) && 255) j = j + 1 if s4 != 64 - String.set(out, j, triple && 255) + str.set(out, j, triple && 255) j = j + 1 - String.set(out, j, 0) + str.set(out, j, 0) return out \ No newline at end of file diff --git a/test.zr b/test.zr index cd8e68b..ea9dbea 100644 --- a/test.zr +++ b/test.zr @@ -1,28 +1,28 @@ func run_test[x: String] : Void - printf("\033[93mBuilding %s...\033[0m", x) - let cmd: String = String.concat("./target/release/zern examples/", x) + c.printf("\033[93mBuilding %s...\033[0m", x) + let cmd: String = str.concat("./target/release/zern examples/", x) - let build_start_time: I64 = OS.time() - if system(cmd) != 0 - exit(1) - let build_end_time: I64 = OS.time() + let build_start_time: I64 = os.time() + if c.system(cmd) != 0 + c.exit(1) + let build_end_time: I64 = os.time() - free(cmd) - printf(" %ldms\n", build_end_time - build_start_time) + c.free(cmd) + c.printf(" %ldms\n", build_end_time - build_start_time) - if strcmp(x, "guess_number.zr") == 0 || strcmp(x, "tcp_server.zr") == 0 - printf("\033[93mSkipping %s...\033[0m\n", x) + if c.strcmp(x, "guess_number.zr") == 0 || c.strcmp(x, "tcp_server.zr") == 0 + c.printf("\033[93mSkipping %s...\033[0m\n", x) else - let run_start_time: I64 = OS.time() - if system("./out") != 0 - exit(1) - let run_end_time: I64 = OS.time() + let run_start_time: I64 = os.time() + if c.system("./out") != 0 + c.exit(1) + let run_end_time: I64 = os.time() - printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time) + c.printf("\033[93mRunning %s...\033[0m %ldms\n", x, run_end_time - run_start_time) func main[] : I64 - system("cargo build --release") + c.system("cargo build --release") - let files: Array = OS.listdir("examples/") - for i in 0..Array.size(files) + let files: Array = os.listdir("examples/") + for i in 0..array.size(files) run_test(files[i]) \ No newline at end of file