const true = 1; const false = 0; // This should really be a constant, but we only allow integers... let null: void*; // Zero initialized by default. /////////////////////////////////////////////////////////////////////////////// // Syscalls fn write(fd: int, s: void*, n: int): int { return syscall3(SYS_write, fd, s, n); } fn exit(status: int): int { return syscall1(SYS_exit, status); } fn read(fd: int, s: void*, n: int): int { return syscall3(SYS_read, fd, s, n); } fn open(path: char*, flags: int, mode: int): int { return syscall3(SYS_open, path, flags, mode); } fn close(fd: int): int { return syscall1(SYS_close, fd); } fn openat(fd: int, path: char*, flags: int, mode: int): int { return syscall4(SYS_openat, fd, path, flags, mode); } fn fork(): int { return syscall0(SYS_fork); } fn wait(status: int*): int { return syscall4(SYS_wait4, -1, status, 0, 0); } fn lseek(fd: int, offset: int, whence: int): int { return syscall3(SYS_lseek, fd, offset, whence); } fn mmap(addr: void*, len: int, prot: int, flags: int, fd: int, offset: int): void* { return syscall6(SYS_mmap, addr, len, prot, flags, fd, offset); } /////////////////////////////////////////////////////////////////////////////// // Strings fn strlen(s: char *): int { let count: int = 0; while (*s != 0) { count = count + 1; s = s + 1; } return count; } fn strcpy(dst: char *, src: char *) { while (*src != 0) { *dst = *src; dst = dst + 1; src = src + 1; } *dst = '\0'; } fn strcat(dst: char *, src: char *) { while (*dst != 0) { dst = dst + 1; } while (*src != 0) { *dst = *src; dst = dst + 1; src = src + 1; } *dst = '\0'; } fn streq(s1: char *, s2: char *): int { while (*s1 != 0 && *s2 != 0) { if (*s1 != *s2) return 0; s1 = s1 + 1; s2 = s2 + 1; } return *s1 == *s2; } fn strrev(s: char *) { let len: int = strlen(s); let i: int = 0; let j: int = len - 1; while (i < j) { let tmp: char = s[i]; s[i] = s[j]; s[j] = tmp; i = i + 1; j = j - 1; } } fn atoi_end(s: char *, end: char**): int { let i: int = 0; let sign: int = 1; if (*s == '-') { sign = -1; s = s + 1; } while (*s >= '0' && *s <= '9') { i = i * 10 + (*s - '0'); s = s + 1; } *end = s; return i * sign; } fn atoi(s: char *): int { let tmp: char*; return atoi_end(s, &tmp); } /////////////////////////////////////////////////////////////////////////////// // I/O const stdin = 0; const stdout = 1; const stderr = 2; fn putc(c: char) { write(0, &c, 1); } fn puts(c: char *) { let len: int = strlen(c); write(1, c, len); } fn putsln(c: char *) { puts(c); putc('\n'); } fn putu_buffer(n: int, buf: char*): int { let i: int = 0; while (n > 0) { buf[i] = (n % 10) + '0'; n = n / 10; i = i + 1; } if (i == 0) { buf[i] = '0'; i = i + 1; } else if (i > 1) { buf[i] = 0; strrev(buf); } return i; } fn putu(n: int) { let buf: char[32]; let len = putu_buffer(n, buf); write(stdout, buf, len); } fn die(msg: char *) { putsln(msg); exit(1); } fn die2(msg1: char *, msg2: char *) { puts(msg1); putsln(msg2); exit(1); } // TODO: file/line numbers would be helpful fn assert(cond: int) { if (!cond) die("assertion failed"); } /////////////////////////////////////////////////////////////////////////////// // Math fn min(a: int, b: int): int { return a < b ? a : b; } fn max(a: int, b: int): int { return a > b ? a : b; } fn sign(a: int): int { return a > 0 ? 1 : a == 0 ? 0 : -1; } fn abs(a: int): int { return a * sign(a); } fn factorial(n: int): int { let res: int = 1; for (;n > 0; n = n - 1) res = res * n; return res; } fn align_up(val: int, algn: int): int { return (val + algn - 1) & ~(algn - 1); } /////////////////////////////////////////////////////////////////////////////// // Memory // FIXME: This is horrible for performance. fn memcpy(dst: void *, src: void *, n: int) { let _dst: char* = dst; let _src: char* = src; for (let i: int = 0; i < n; i = i + 1) _dst[i] = _src[i]; } const __MALLOC_BUF_SIZE = 1024 * 1024 * 1024; // 1 GB let __malloc_buf: char[__MALLOC_BUF_SIZE]; let __malloc_buf_pos = 0; fn malloc(size: int): void* { if (__malloc_buf_pos + size > __MALLOC_BUF_SIZE) die("malloc: out of memory. only 1gb available"); let ptr = &__malloc_buf[__malloc_buf_pos]; __malloc_buf_pos = __malloc_buf_pos + size; return ptr; } fn free(ptr: void*) {} // Placeholder