diff options
Diffstat (limited to 'std')
| -rw-r--r-- | std/core.zc | 6 | ||||
| -rw-r--r-- | std/cuda.zc | 2 | ||||
| -rw-r--r-- | std/env.zc | 29 | ||||
| -rw-r--r-- | std/fs.zc | 90 | ||||
| -rw-r--r-- | std/io.zc | 49 | ||||
| -rw-r--r-- | std/json.zc | 72 | ||||
| -rw-r--r-- | std/map.zc | 29 | ||||
| -rw-r--r-- | std/mem.zc | 23 | ||||
| -rw-r--r-- | std/net.zc | 46 | ||||
| -rw-r--r-- | std/process.zc | 136 | ||||
| -rw-r--r-- | std/set.zc | 20 | ||||
| -rw-r--r-- | std/slice.zc | 40 | ||||
| -rw-r--r-- | std/string.zc | 22 | ||||
| -rw-r--r-- | std/thread.zc | 14 | ||||
| -rw-r--r-- | std/time.zc | 29 |
15 files changed, 450 insertions, 157 deletions
diff --git a/std/core.zc b/std/core.zc index f450517..7379db4 100644 --- a/std/core.zc +++ b/std/core.zc @@ -7,11 +7,11 @@ include <stdarg.h> let __zen_hash_seed: usize = 14695981039346656037; -raw { -void _zen_panic(const char* file, int line, const char* func, const char* msg) { +extern fn exit(code: int); + +fn _zen_panic(file: const char*, line: int, func: const char*, msg: const char*) { fprintf(stderr, "%s:%d (%s): Panic: %s\n", file, line, func, msg); exit(1); } -} #define panic(msg) _zen_panic(__FILE__, __LINE__, __func__, msg)
\ No newline at end of file diff --git a/std/cuda.zc b/std/cuda.zc index c6a9403..8fc6545 100644 --- a/std/cuda.zc +++ b/std/cuda.zc @@ -101,6 +101,8 @@ fn cuda_ok() -> bool { } +// Minimal raw block: required for cudaDeviceProp struct field access +// The cudaDeviceProp struct cannot be declared in Zen-C without type conflicts raw { void _z_cuda_get_props(int dev, char* name, size_t* total_mem, int* sm_count, int* major, int* minor, int* max_threads, int* warp_size) { struct cudaDeviceProp prop; @@ -2,23 +2,12 @@ import "./core.zc" import "./option.zc" import "./string.zc" -raw { - char *_z_env_get(char *name) { - return getenv(name); - } - - int _z_env_set(char *name, char *value, int overwrite) { - return setenv(name, value, overwrite); - } - - int _z_env_unset(char *name) { - return unsetenv(name); - } -} +include <stdlib.h> -extern fn _z_env_get(name: char*) -> char*; -extern fn _z_env_set(name: char*, value: char*, overwrite: int) -> int; -extern fn _z_env_unset(name: char*) -> int; +// Direct externs with const char* to match C stdlib declarations +extern fn getenv(name: const char*) -> char*; +extern fn setenv(name: const char*, value: const char*, overwrite: int) -> int; +extern fn unsetenv(name: const char*) -> int; @derive(Eq) enum EnvRes { @@ -30,7 +19,7 @@ struct Env {} impl Env { fn get(name: string) -> Option<string> { - let value: string = _z_env_get(name); + let value: string = getenv(name); if (value == NULL) { return Option<string>::None(); } @@ -39,7 +28,7 @@ impl Env { } fn get_dup(name: string) -> Option<String> { - let value: string = _z_env_get(name); + let value: string = getenv(name); if (value == NULL) { return Option<String>::None(); } @@ -52,13 +41,13 @@ impl Env { } fn set(name: string, value: string) -> EnvRes { - let ret: int = _z_env_set(name, value, 1); + let ret: int = setenv(name, value, 1); return (ret == 0) ? EnvRes::OK() : EnvRes::ERR(); } fn unset(name: string) -> EnvRes { - let ret: int = _z_env_unset(name); + let ret: int = unsetenv(name); return (ret == 0) ? EnvRes::OK() : EnvRes::ERR(); } @@ -2,22 +2,32 @@ import "./core.zc" import "./result.zc" import "./string.zc" import "./vec.zc" +import "./mem.zc" def Z_SEEK_SET = 0; def Z_SEEK_END = 2; def Z_F_OK = 0; - -// TODO: restructure this tomorrow. +include <dirent.h> +include <sys/stat.h> +include <unistd.h> +include <stdlib.h> +include <stdio.h> + +// Direct externs for simple functions with const char* parameters +extern fn access(pathname: const char*, mode: int) -> int; +extern fn unlink(pathname: const char*) -> int; +extern fn rmdir(pathname: const char*) -> int; +extern fn malloc(size: usize) -> void*; +extern fn free(ptr: void*); + +// Minimal raw block: required for opaque FILE*/DIR* types and C struct access +// These cannot be expressed in Zen-C extern declarations without type conflicts raw { - #include <dirent.h> - #include <sys/stat.h> - #include <unistd.h> - - // typedef needed for Vec<DirEntry*> generation if inferred typedef struct DirEntry* DirEntryPtr; - void* _z_fs_fopen(char* path, char* mode) { + // FILE* wrappers - fopen/fclose/etc use FILE* which conflicts with void* + void* _z_fs_fopen(const char* path, const char* mode) { return fopen(path, mode); } @@ -40,20 +50,9 @@ raw { int64_t _z_fs_ftell(void* stream) { return (int64_t)ftell((FILE*)stream); } - - int _z_fs_access(char* pathname, int mode) { - return access(pathname, mode); - } - - int _z_fs_unlink(char* pathname) { - return unlink(pathname); - } - - int _z_fs_rmdir(char* pathname) { - return rmdir(pathname); - } - - void* _z_fs_opendir(char* name) { + + // DIR* wrappers - opendir/closedir/readdir use DIR* which conflicts with void* + void* _z_fs_opendir(const char* name) { return opendir(name); } @@ -61,15 +60,8 @@ raw { return closedir((DIR*)dir); } - void* _z_fs_malloc(size_t size) { - return malloc(size); - } - - void _z_fs_free(void* ptr) { - free(ptr); - } - - int _z_fs_get_metadata(char* path, uint64_t* size, int* is_dir, int* is_file) { + // struct stat access - cannot define matching Zen-C struct for stat + int _z_fs_get_metadata(const char* path, uint64_t* size, int* is_dir, int* is_file) { struct stat st; if (stat(path, &st) != 0) return -1; *size = st.st_size; @@ -78,6 +70,7 @@ raw { return 0; } + // struct dirent access - readdir returns struct dirent* int _z_fs_read_entry(void* dir, char* out_name, int buf_size, int* is_dir) { struct dirent* ent = readdir((DIR*)dir); if (!ent) return 0; @@ -87,7 +80,8 @@ raw { return 1; } - int _z_fs_mkdir(char* path) { + // mkdir has different signatures on Windows vs POSIX + int _z_fs_mkdir(const char* path) { #ifdef _WIN32 return mkdir(path); #else @@ -96,22 +90,18 @@ raw { } } -extern fn _z_fs_mkdir(path: char*) -> int; -extern fn _z_fs_get_metadata(path: char*, size: U64*, is_dir: int*, is_file: int*) -> int; +extern fn _z_fs_mkdir(path: const char*) -> int; +extern fn _z_fs_get_metadata(path: const char*, size: U64*, is_dir: int*, is_file: int*) -> int; extern fn _z_fs_read_entry(dir: void*, out_name: char*, buf_size: int, is_dir: int*) -> int; -extern fn _z_fs_fopen(path: char*, mode: char*) -> void*; +extern fn _z_fs_fopen(path: const char*, mode: const char*) -> void*; extern fn _z_fs_fclose(stream: void*) -> int; extern fn _z_fs_fread(ptr: void*, size: usize, nmemb: usize, stream: void*) -> usize; extern fn _z_fs_fwrite(ptr: void*, size: usize, nmemb: usize, stream: void*) -> usize; -extern fn _z_fs_fseek(stream: void*, offset: long, whence: int) -> int; -extern fn _z_fs_ftell(stream: void*) -> long; -extern fn _z_fs_access(pathname: char*, mode: int) -> int; -extern fn _z_fs_unlink(pathname: char*) -> int; -extern fn _z_fs_rmdir(pathname: char*) -> int; -extern fn _z_fs_opendir(name: char*) -> void*; +extern fn _z_fs_fseek(stream: void*, offset: I64, whence: int) -> int; +extern fn _z_fs_ftell(stream: void*) -> I64; +extern fn _z_fs_opendir(name: const char*) -> void*; extern fn _z_fs_closedir(dir: void*) -> int; -extern fn _z_fs_malloc(size: usize) -> void*; -extern fn _z_fs_free(ptr: void*); + struct File { handle: void*; @@ -153,7 +143,7 @@ impl File { let size = _z_fs_ftell(self.handle); _z_fs_fseek(self.handle, 0, Z_SEEK_SET); - let buffer: char* = _z_fs_malloc((usize)size + 1); + let buffer: char* = malloc((usize)size + 1); if (buffer == NULL) { return Result<String>::Err("Out of memory"); } @@ -162,7 +152,7 @@ impl File { buffer[read] = 0; let s = String::new(buffer); - _z_fs_free(buffer); + free(buffer); let res = Result<String>::Ok(s); s.forget(); @@ -201,7 +191,7 @@ impl File { } fn exists(path: char*) -> bool { - return _z_fs_access(path, Z_F_OK) == 0; + return access(path, Z_F_OK) == 0; } fn metadata(path: char*) -> Result<Metadata> { @@ -228,14 +218,14 @@ impl File { } fn remove_file(path: char*) -> Result<bool> { - if (_z_fs_unlink(path) != 0) { + if (unlink(path) != 0) { return Result<bool>::Err("Failed to remove file"); } return Result<bool>::Ok(true); } fn remove_dir(path: char*) -> Result<bool> { - if (_z_fs_rmdir(path) != 0) { + if (rmdir(path) != 0) { return Result<bool>::Err("Failed to remove directory"); } return Result<bool>::Ok(true); @@ -248,7 +238,7 @@ impl File { } let entries = Vec<DirEntry>::new(); - let name_buf: char* = _z_fs_malloc(256); + let name_buf: char* = malloc(256); if (name_buf == NULL) { _z_fs_closedir(dir); @@ -277,7 +267,7 @@ impl File { ent.name.forget(); } - _z_fs_free(name_buf); + free(name_buf); _z_fs_closedir(dir); let res = Result< Vec<DirEntry> >::Ok(entries); @@ -2,37 +2,51 @@ import "./core.zc" import "./string.zc" -raw { - int _z_vprintf(char* fmt, va_list ap) { - return vprintf((const char*)fmt, ap); - } - - int _z_vsnprintf(char* str, size_t size, char* fmt, va_list ap) { - return vsnprintf(str, size, (const char*)fmt, ap); - } +include <stdio.h> +include <stdarg.h> - void* _z_get_stdin() { return stdin; } - int _z_get_eof() { return EOF; } +// These work directly with const char* in extern declarations +extern fn vprintf(fmt: const char*, ap: va_list) -> int; + +// vsnprintf is problematic on macOS because it's a macro that expands to a builtin with a different signature +// so we wrap it in a C function to avoid the conflict +extern fn _z_vsnprintf(str: char*, size: usize, fmt: const char*, ap: va_list) -> int; + +// EOF is typically -1, but we define it for portability +def Z_EOF = -1; + +// Minimal raw block: only for truly opaque FILE* types that can't be +// represented in Zen-C extern declarations without type conflicts. +// These wrappers use void* to avoid FILE* declaration conflicts. +raw { + void* _z_get_stdin(void) { return stdin; } int _z_fgetc(void* stream) { return fgetc((FILE*)stream); } + int _z_vsnprintf(char* str, size_t size, const char* fmt, va_list ap) { + return vsnprintf(str, size, fmt, ap); + } } -extern fn _z_vprintf(fmt: char*, ap: va_list) -> int; -extern fn _z_vsnprintf(str: char*, size: usize, fmt: char*, ap: va_list) -> int; +extern fn _z_get_stdin() -> void*; +extern fn _z_fgetc(stream: void*) -> int; fn format(fmt: char*, ...) -> char* { static let buffer: char[1024]; let ap: va_list; va_start(ap, fmt); + _z_vsnprintf(buffer, 1024, fmt, ap); va_end(ap); + return (char*)buffer; } fn format_into(buffer: char*, size: usize, fmt: char*, ...) -> int { let ap: va_list; va_start(ap, fmt); + let ret = _z_vsnprintf(buffer, size, fmt, ap); va_end(ap); + return ret; } @@ -42,15 +56,17 @@ fn format_new(fmt: char*, ...) -> char* { let ap: va_list; va_start(ap, fmt); + _z_vsnprintf(buffer, 1024, fmt, ap); va_end(ap); + return buffer; } fn print(fmt: char*, ...) -> int { let ap: va_list; va_start(ap, fmt); - let ret = _z_vprintf(fmt, ap); + let ret = vprintf(fmt, ap); va_end(ap); return ret; } @@ -58,7 +74,7 @@ fn print(fmt: char*, ...) -> int { fn println(fmt: char*, ...) -> int { let ap: va_list; va_start(ap, fmt); - let ret = _z_vprintf(fmt, ap); + let ret = vprintf(fmt, ap); va_end(ap); puts(""); return ret + 1; @@ -72,11 +88,10 @@ fn readln() -> char* { let c: int; let std_in = _z_get_stdin(); - let eof_val = _z_get_eof(); while (true) { c = _z_fgetc(std_in); - if (c == eof_val) break; + if (c == Z_EOF) break; if (c == 10) break; // '\n' if (len + 1 >= cap) { @@ -93,7 +108,7 @@ fn readln() -> char* { len = len + 1; } - if (len == 0 && c == eof_val) { + if (len == 0 && c == Z_EOF) { free(line); return NULL; } diff --git a/std/json.zc b/std/json.zc index e6a15cd..9f5cf73 100644 --- a/std/json.zc +++ b/std/json.zc @@ -5,6 +5,7 @@ import "./map.zc" import "./string.zc" import "./result.zc" import "./option.zc" +import "./mem.zc" @derive(Eq) enum JsonType { @@ -450,3 +451,74 @@ impl JsonValue { } } } + +impl Drop for JsonValue { + fn drop(self) { + self.free(); + } +} + +impl JsonValue { + fn to_string(self) -> String { + let s = String::new(""); + self.stringify(&s); + return s; + } + + fn stringify(self, buf: String*) { + if (self.kind.tag == JsonType::JSON_NULL().tag) { + buf.append_c_ptr("null"); + } else if (self.kind.tag == JsonType::JSON_BOOL().tag) { + if (self.bool_val) { buf.append_c_ptr("true"); } else { buf.append_c_ptr("false"); } + } else if (self.kind.tag == JsonType::JSON_NUMBER().tag) { + let tmp: char[64]; + sprintf((char*)tmp, "%.15g", self.number_val); // Use %.15g for precision + buf.append_c_ptr((char*)tmp); + } else if (self.kind.tag == JsonType::JSON_STRING().tag) { + buf.append_c_ptr("\""); + let p = self.string_val; + let len = strlen(p); + for (let i = 0; i < len; i = i + 1) { + let c = p[i]; + if (c == '"') buf.append_c_ptr("\\\""); + else if (c == '\\') buf.append_c_ptr("\\\\"); + else if (c == '\n') buf.append_c_ptr("\\n"); + else if (c == '\t') buf.append_c_ptr("\\t"); + else if (c == '\r') buf.append_c_ptr("\\r"); + else if (c == '\b') buf.append_c_ptr("\\b"); + else if (c == '\f') buf.append_c_ptr("\\f"); + else { + let tmp: char[2]; tmp[0] = c; tmp[1] = 0; + buf.append_c_ptr((char*)tmp); + } + } + buf.append_c_ptr("\""); + } else if (self.kind.tag == JsonType::JSON_ARRAY().tag) { + buf.append_c_ptr("["); + let v = self.array_val; + for (let i: usize = 0; i < v.length(); i = i + 1) { + if (i > 0) buf.append_c_ptr(","); + let item = v.get(i); + (*item).stringify(buf); + } + buf.append_c_ptr("]"); + } else if (self.kind.tag == JsonType::JSON_OBJECT().tag) { + buf.append_c_ptr("{{"); + let m = self.object_val; + let first = true; + for (let i: usize = 0; i < m.capacity(); i = i + 1) { + if (m.is_slot_occupied(i)) { + if (!first) buf.append_c_ptr(","); + first = false; + let key = m.key_at(i); + buf.append_c_ptr("\""); + buf.append_c_ptr(key); // Assuming keys are simple for now, but really should escape them too + buf.append_c_ptr("\":"); + let val = m.val_at(i); + val.stringify(buf); + } + } + buf.append_c_ptr("}"); + } + } +} @@ -1,17 +1,22 @@ import "./core.zc" import "./option.zc" +import "./mem.zc" -raw { - extern size_t __zen_hash_seed; - size_t _map_hash_str(const char* str) { - size_t hash = __zen_hash_seed; - while (*str) { - hash ^= (unsigned char)*str++; - hash *= 1099511628211UL; - } - return hash; +// Pure Zen-C string hash using FNV-1a algorithm +fn _map_hash_str(str: const char*) -> usize { + let hash = __zen_hash_seed; + let i: usize = 0; + + while (str[i] != 0) { + // Cast char to U8 for unsigned byte value + let b: U8 = (U8)str[i]; + hash = hash ^ (usize)b; + hash = hash * (usize)1099511628211; + i = i + 1; } + + return hash; } struct Map<V> { @@ -248,3 +253,9 @@ impl Map<V> { }; } } + +impl Drop for Map<V> { + fn drop(self) { + self.free(); + } +} @@ -49,28 +49,7 @@ impl Box<T> { } } -struct Slice<T> { - data: T*; - len: usize; -} - -impl Slice<T> { - fn new(data: T*, len: usize) -> Self { - return Self { data: data, len: len }; - } - - fn get(self, i: usize) -> T { - return self.data[i]; - } - - fn set(self, i: usize, val: T) { - self.data[i] = val; - } - - fn is_empty(self) -> bool { - return self.len == 0; - } -} +// Note: Slice<T> is defined in std/slice.zc with iteration support fn mem_zero<T>(ptr: T*, count: usize) { memset(ptr, 0, sizeof(T) * count); @@ -8,12 +8,22 @@ include <errno.h> import "./core.zc" import "./result.zc" import "./string.zc" +import "./mem.zc" def Z_AF_INET = 2; def Z_SOCK_STREAM = 1; +// Direct externs for simple socket functions +extern fn socket(domain: int, type: int, proto: int) -> int; +extern fn close(fd: int) -> int; +extern fn read(fd: int, buf: void*, count: usize) -> isize; + +// Minimal raw block: required for struct sockaddr_in usage +// These functions encapsulate sockaddr_in setup because the struct layout +// cannot be declared in Zen-C without type conflicts with C headers. +// Also includes inet_pton, htons, bind, connect, listen, accept wrappers. raw { - static int _z_net_bind(int fd, char *host, int port) { + static int _z_net_bind(int fd, const char *host, int port) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); @@ -27,7 +37,7 @@ raw { return 0; } - static int _z_net_connect(int fd, char *host, int port) { + static int _z_net_connect(int fd, const char *host, int port) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); @@ -36,28 +46,20 @@ raw { if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) return -2; return 0; } - + static int _z_net_accept(int fd) { return accept(fd, NULL, NULL); } - static ssize_t _z_net_read(int fd, char* buf, size_t n) { - return read(fd, (void*)buf, n); - } - - static ssize_t _z_net_write(int fd, char* buf, size_t n) { + static ssize_t _z_net_write(int fd, const char* buf, size_t n) { return write(fd, (const void*)buf, n); } } -extern fn socket(domain: int, type: int, proto: int) -> int; -extern fn close(fd: int) -> int; - -extern fn _z_net_bind(fd: int, host: char*, port: int) -> int; -extern fn _z_net_connect(fd: int, host: char*, port: int) -> int; +extern fn _z_net_bind(fd: int, host: const char*, port: int) -> int; +extern fn _z_net_connect(fd: int, host: const char*, port: int) -> int; extern fn _z_net_accept(fd: int) -> int; -extern fn _z_net_read(fd: int, buf: char*, n: usize) -> isize; -extern fn _z_net_write(fd: int, buf: char*, n: usize) -> isize; +extern fn _z_net_write(fd: int, buf: const char*, n: usize) -> isize; struct TcpStream { @@ -66,7 +68,7 @@ struct TcpStream { impl TcpStream { fn read(self, buf: char*, len: usize) -> Result<usize> { - let n = _z_net_read(self.fd, buf, len); + let n = read(self.fd, (void*)buf, len); if (n < 0) return Result<usize>::Err("Read failed"); return Result<usize>::Ok((usize)n); } @@ -96,6 +98,12 @@ impl TcpStream { } } +impl Drop for TcpStream { + fn drop(self) { + self.close(); + } +} + struct TcpListener { fd: int; } @@ -126,3 +134,9 @@ impl TcpListener { } } } + +impl Drop for TcpListener { + fn drop(self) { + self.close(); + } +} diff --git a/std/process.zc b/std/process.zc new file mode 100644 index 0000000..3ce43b6 --- /dev/null +++ b/std/process.zc @@ -0,0 +1,136 @@ + +import "./core.zc"; +import "./vec.zc"; +import "./mem.zc"; +import "./string.zc"; +import "./option.zc"; + +include <stdio.h> +include <stdlib.h> + +// system() can be externed directly with const char* +extern fn system(command: const char*) -> int; + +// Minimal raw block: only for opaque FILE* types +// popen/pclose/fgets use FILE* which conflicts with void* +raw { + void *_z_popen(const char *command, const char *type) { + return (void *)popen(command, type); + } + + int _z_pclose(void *stream) { + return pclose((FILE *)stream); + } + + char *_z_fgets(char *s, int size, void *stream) { + return fgets(s, size, (FILE *)stream); + } +} + +extern fn _z_popen(command: const char*, type: const char*) -> void*; +extern fn _z_pclose(stream: void*) -> int; +extern fn _z_fgets(s: char*, size: int, stream: void*) -> char*; + +struct Output { + stdout: String; + exit_code: int; +} + +struct Command { + program: String; + args: Vec<String>; +} + +impl Command { + fn new(program: char*) -> Command { + return Command { + program: String::from(program), + args: Vec<String>::new() + }; + } + + fn arg(self, arg: char*) -> Command* { + self.args.push(String::from(arg)); + return self; + } + + fn _build_cmd(self) -> String { + let cmd_str = self.program.substring(0, self.program.length()); + + for arg in &self.args { + let space = String::from(" "); + cmd_str.append(&space); + space.free(); + + cmd_str.append(arg); + } + + return cmd_str; + } + + fn output(self) -> Output { + let cmd_str = self._build_cmd(); + let cmd_c = cmd_str.c_str(); + + let fp = _z_popen(cmd_c, "r"); + + if (fp == 0) { + cmd_str.free(); + // TODO: Better error handling... + return Output { + stdout: String::from(""), + exit_code: -1 + }; + } + + let out = String::from(""); + let buf_size: usize = 1024; + let buf = (char*)malloc(buf_size); + + while (true) { + let res = _z_fgets(buf, (int)buf_size, fp); + if (res == 0) break; + + let chunk = String::from(buf); + out.append(&chunk); + chunk.free(); + } + + let code = _z_pclose(fp); + free(buf); + cmd_str.free(); + + return Output { + stdout: out, + exit_code: code + }; + } + + fn status(self) -> int { + let cmd_str = self._build_cmd(); + let code = system(cmd_str.c_str()); + cmd_str.free(); + return code; + } + + fn free(self) { + self.program.free(); + + for s in &self.args { + s.free(); + } + self.args.free(); + } +} + +impl Drop for Command { + fn drop(self) { + self.free(); + } +} + +impl Drop for Output { + fn drop(self) { + self.stdout.free(); + } +} @@ -2,17 +2,17 @@ import "./core.zc" import "./option.zc" -raw { - extern size_t __zen_hash_seed; - size_t _set_hash(const void* data, size_t len) { - size_t hash = __zen_hash_seed; - const unsigned char* bytes = (const unsigned char*)data; - for (size_t i = 0; i < len; i++) { - hash ^= bytes[i]; - hash *= 1099511628211UL; - } - return hash; +// Pure Zen-C generic hash using FNV-1a algorithm +fn _set_hash(data: const void*, len: usize) -> usize { + let hash = __zen_hash_seed; + let bytes: U8* = (U8*)data; + + for (let i: usize = 0; i < len; i = i + 1) { + hash = hash ^ (usize)bytes[i]; + hash = hash * (usize)1099511628211; } + + return hash; } struct Set<T> { diff --git a/std/slice.zc b/std/slice.zc index 778c6ed..c757fbd 100644 --- a/std/slice.zc +++ b/std/slice.zc @@ -1,10 +1,50 @@ +import "./option.zc" + struct Slice<T> { data: T*; len: usize; } +struct SliceIter<T> { + data: T*; + count: usize; + idx: usize; +} + +impl SliceIter<T> { + fn next(self) -> Option<T> { + if (self.idx < self.count) { + let item = self.data[self.idx]; + self.idx = self.idx + 1; + return Option<T>::Some(item); + } + return Option<T>::None(); + } + + fn iterator(self) -> SliceIter<T> { + return *self; + } +} + impl Slice<T> { + fn from_array(ptr: T*, len: usize) -> Slice<T> { + return Slice<T> { data: ptr, len: len }; + } + + // Alias for backwards compatibility with std/mem.zc + fn new(data: T*, len: usize) -> Slice<T> { + return Slice<T> { data: data, len: len }; + } + + fn iterator(self) -> SliceIter<T> { + return SliceIter<T> { + data: self.data, + count: self.len, + idx: 0 + }; + } + fn length(self) -> usize { return self.len; } diff --git a/std/string.zc b/std/string.zc index fe5b0ad..0bc9539 100644 --- a/std/string.zc +++ b/std/string.zc @@ -55,6 +55,28 @@ impl String { } } + fn append_c(self, s: char*) { + if (self.vec.len > 0) { + self.vec.len = self.vec.len - 1; + } + let len = strlen(s); + for (let i = 0; i < len; i = i + 1) { + self.vec.push(s[i]); + } + self.vec.push(0); + } + + fn append_c_ptr(ptr: String*, s: char*) { + if (ptr.vec.len > 0) { + ptr.vec.len = ptr.vec.len - 1; + } + let len = strlen(s); + for (let i = 0; i < len; i = i + 1) { + ptr.vec.push(s[i]); + } + ptr.vec.push(0); + } + fn add(self, other: String*) -> String { let new_s = String::from(self.c_str()); new_s.append(other); diff --git a/std/thread.zc b/std/thread.zc index e90943b..16f3ca1 100644 --- a/std/thread.zc +++ b/std/thread.zc @@ -5,7 +5,13 @@ include <unistd.h> import "./core.zc" import "./result.zc" +import "./mem.zc" +// Essential raw block: required for pthread operations and closure trampolining +// This block cannot be eliminated because: +// 1. z_closure_T is an internal compiler type for Zen-C closures +// 2. pthread_t, pthread_mutex_t are opaque types that can't be extern'd with void* +// 3. The trampoline function needs to cast and execute Zen-C closures raw { typedef void (*ZenThreadFunc)(void*); @@ -120,11 +126,17 @@ impl Mutex { if (self.handle) { _z_mutex_destroy(self.handle); free(self.handle); + self.handle = NULL; } } } +impl Drop for Mutex { + fn drop(self) { + self.free(); + } +} + fn sleep_ms(ms: int) { _z_usleep(ms * 1000); } - diff --git a/std/time.zc b/std/time.zc index 1191821..fa764ed 100644 --- a/std/time.zc +++ b/std/time.zc @@ -1,18 +1,31 @@ - import "./core.zc" +include <time.h> +include <unistd.h> +include <sys/time.h> +include <stdlib.h> + +// Minimal raw block: required because gettimeofday() uses struct timeval +// which can't be declared in Zen-C without type conflicts, and time() +// has conflicting type signature (time_t* vs void*) raw { - #include <time.h> - #include <unistd.h> - #include <sys/time.h> - static uint64_t _time_now_impl(void) { struct timeval tv; gettimeofday(&tv, NULL); return (uint64_t)(tv.tv_sec) * 1000 + (uint64_t)(tv.tv_usec) / 1000; } + + static int64_t _z_time_time(void) { + return (int64_t)time(NULL); + } } +extern fn srand(seed: U32); +extern fn rand() -> int; +extern fn usleep(micros: U32) -> int; +extern fn _time_now_impl() -> U64; +extern fn _z_time_time() -> I64; + struct Duration { millis: U64; } @@ -33,10 +46,8 @@ extern size_t __zen_hash_seed; impl Time { fn randomize_hash() { - raw { - srand(time(NULL)); - __zen_hash_seed ^= (size_t)rand(); - } + srand((U32)_z_time_time()); + __zen_hash_seed ^= (size_t)rand(); } fn now() -> U64 { |
