summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-30 19:44:32 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-30 19:44:32 +0000
commit472434301940015365f7ed303f52d71c505ac487 (patch)
tree923a4fb8821d03c8dc88266fd08320af17f90d9a
parent0427d254207a69e394499d1abaea768f484f1cb5 (diff)
Improvements for the standard library + '@ctype'.
-rw-r--r--Makefile2
-rw-r--r--README.md1
-rw-r--r--README_ES.md1
-rw-r--r--README_ZH_CN.md1
-rw-r--r--README_ZH_TW.md1
-rw-r--r--src/ast/ast.h2
-rw-r--r--src/codegen/codegen_utils.c8
-rw-r--r--src/parser/parser.h3
-rw-r--r--src/parser/parser_decl.c6
-rw-r--r--src/parser/parser_struct.c2
-rw-r--r--src/parser/parser_utils.c53
-rw-r--r--std/core.zc6
-rw-r--r--std/cuda.zc2
-rw-r--r--std/env.zc29
-rw-r--r--std/fs.zc62
-rw-r--r--std/io.zc43
-rw-r--r--std/map.zc22
-rw-r--r--std/net.zc25
-rw-r--r--std/process.zc21
-rw-r--r--std/set.zc20
-rw-r--r--std/thread.zc5
-rw-r--r--std/time.zc3
22 files changed, 192 insertions, 126 deletions
diff --git a/Makefile b/Makefile
index d15f556..b2d8e29 100644
--- a/Makefile
+++ b/Makefile
@@ -188,7 +188,7 @@ clean:
@echo "=> Clean complete!"
# Test
-test: $(TARGET)
+test: $(TARGET) $(PLUGINS)
./tests/run_tests.sh
./tests/run_codegen_tests.sh
./tests/run_example_transpile.sh
diff --git a/README.md b/README.md
index f03f605..001e590 100644
--- a/README.md
+++ b/README.md
@@ -939,6 +939,7 @@ Decorate functions and structs to modify compiler behavior.
| `@host` | Fn | CUDA: Host function (`__host__`). |
| `@comptime` | Fn | Helper function available for compile-time execution. |
| `@derive(...)` | Struct | Auto-implement traits. Supports `Debug`, `Eq` (Smart Derive), `Copy`, `Clone`. |
+| `@ctype("type")` | Fn Param | Overrides generated C type for a parameter. |
| `@<custom>` | Any | Passes generic attributes to C (e.g. `@flatten`, `@alias("name")`). |
#### Custom Attributes
diff --git a/README_ES.md b/README_ES.md
index 9040ea8..999a7b4 100644
--- a/README_ES.md
+++ b/README_ES.md
@@ -938,6 +938,7 @@ Decora funciones y structs para modificar el comportamiento del compilador.
| `@host` | Fn | CUDA: Función de host (`__host__`). |
| `@comptime` | Fn | Función auxiliar disponible para ejecución en tiempo de compilación. |
| `@derive(...)` | Struct | Implementa traits automáticamente. Soporta `Debug`, `Eq` (Derivación Inteligente), `Copy`, `Clone`. |
+| `@ctype("tipo")` | Parámetro Fn | Sobrescribe el tipo C generado para un parámetro. |
| `@<custom>` | Cualquier | Pasa atributos genéricos a C (ej. `@flatten`, `@alias("nombre")`). |
#### Atributos Personalizados
diff --git a/README_ZH_CN.md b/README_ZH_CN.md
index 217e9ec..daa8a3d 100644
--- a/README_ZH_CN.md
+++ b/README_ZH_CN.md
@@ -938,6 +938,7 @@ let re = regex! { ^[a-z]+$ };
| `@host` | 函数 | CUDA: 主机函数 (`__host__`)。 |
| `@comptime` | 函数 | 用于编译时执行的辅助函数。 |
| `@derive(...)` | 结构体 | 自动实现 Trait。支持 `Debug`, `Eq` (智能派生), `Copy`, `Clone`。 |
+| `@ctype("type")` | 函数参数 | 覆盖参数生成的 C 类型。 |
| `@<custom>` | 任意 | 将泛型属性传递给 C (例如 `@flatten`, `@alias("name")`)。 |
#### 自定义属性
diff --git a/README_ZH_TW.md b/README_ZH_TW.md
index 8618540..2707caa 100644
--- a/README_ZH_TW.md
+++ b/README_ZH_TW.md
@@ -938,6 +938,7 @@ let re = regex! { ^[a-z]+$ };
| `@host` | 函數 | CUDA: 主機函數 (`__host__`)。 |
| `@comptime` | 函數 | 用於編譯時執行的輔助函數。 |
| `@derive(...)` | 結構體 | 自動實現 Trait。支持 `Debug`, `Eq` (智能派生), `Copy`, `Clone`。 |
+| `@ctype("type")` | 函數參數 | 覆蓋參數生成的 C 類型。 |
| `@<custom>` | 任意 | 將泛型屬性傳遞給 C (例如 `@flatten`, `@alias("name")`)。 |
#### 自定義屬性
diff --git a/src/ast/ast.h b/src/ast/ast.h
index 71d9943..4498d7c 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -229,6 +229,8 @@ struct ASTNode
int cuda_device; // @device -> __device__
int cuda_host; // @host -> __host__
+ char **c_type_overrides; // @ctype("...") per parameter
+
Attribute *attributes; // Custom attributes
} func;
diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c
index 391ebd3..0d03661 100644
--- a/src/codegen/codegen_utils.c
+++ b/src/codegen/codegen_utils.c
@@ -714,7 +714,12 @@ void emit_func_signature(FILE *out, ASTNode *func, const char *name_override)
}
char *type_str = NULL;
- if (func->func.arg_types && func->func.arg_types[i])
+ // Check for @ctype override first
+ if (func->func.c_type_overrides && func->func.c_type_overrides[i])
+ {
+ type_str = xstrdup(func->func.c_type_overrides[i]);
+ }
+ else if (func->func.arg_types && func->func.arg_types[i])
{
type_str = codegen_type_to_string(func->func.arg_types[i]);
}
@@ -724,6 +729,7 @@ void emit_func_signature(FILE *out, ASTNode *func, const char *name_override)
}
const char *name = "";
+
if (func->func.param_names && func->func.param_names[i])
{
name = func->func.param_names[i];
diff --git a/src/parser/parser.h b/src/parser/parser.h
index 262c359..23c2920 100644
--- a/src/parser/parser.h
+++ b/src/parser/parser.h
@@ -561,7 +561,8 @@ ASTNode *parse_arrow_lambda_multi(ParserContext *ctx, Lexer *l, char **param_nam
* @brief Parses and converts arguments.
*/
char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, int *count_out,
- Type ***types_out, char ***names_out, int *is_varargs_out);
+ Type ***types_out, char ***names_out, int *is_varargs_out,
+ char ***ctype_overrides_out);
/**
* @brief Checks if a file has been imported.
diff --git a/src/parser/parser_decl.c b/src/parser/parser_decl.c
index c96ca36..93a124d 100644
--- a/src/parser/parser_decl.c
+++ b/src/parser/parser_decl.c
@@ -99,10 +99,11 @@ ASTNode *parse_function(ParserContext *ctx, Lexer *l, int is_async)
int count;
Type **arg_types;
char **param_names;
+ char **ctype_overrides;
int is_varargs = 0;
- char *args =
- parse_and_convert_args(ctx, l, &defaults, &count, &arg_types, &param_names, &is_varargs);
+ char *args = parse_and_convert_args(ctx, l, &defaults, &count, &arg_types, &param_names,
+ &is_varargs, &ctype_overrides);
char *ret = "void";
Type *ret_type_obj = type_new(TYPE_VOID);
@@ -191,6 +192,7 @@ ASTNode *parse_function(ParserContext *ctx, Lexer *l, int is_async)
node->func.defaults = defaults;
node->func.ret_type_info = ret_type_obj;
node->func.is_varargs = is_varargs;
+ node->func.c_type_overrides = ctype_overrides;
if (gen_param)
{
diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c
index 82dd346..109eeee 100644
--- a/src/parser/parser_struct.c
+++ b/src/parser/parser_struct.c
@@ -100,7 +100,7 @@ ASTNode *parse_trait(ParserContext *ctx, Lexer *l)
char **param_names = NULL;
int is_varargs = 0;
char *args = parse_and_convert_args(ctx, l, &defaults, &arg_count, &arg_types, &param_names,
- &is_varargs);
+ &is_varargs, NULL);
char *ret = xstrdup("void");
if (lexer_peek(l).type == TOK_ARROW)
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c
index 48418b6..28d2c11 100644
--- a/src/parser/parser_utils.c
+++ b/src/parser/parser_utils.c
@@ -3392,7 +3392,8 @@ char *consume_and_rewrite(ParserContext *ctx, Lexer *l)
}
char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out, int *count_out,
- Type ***types_out, char ***names_out, int *is_varargs_out)
+ Type ***types_out, char ***names_out, int *is_varargs_out,
+ char ***ctype_overrides_out)
{
Token t = lexer_next(l);
if (t.type != TOK_LPAREN)
@@ -3406,18 +3407,52 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out,
char **defaults = xmalloc(sizeof(char *) * 16);
Type **types = xmalloc(sizeof(Type *) * 16);
char **names = xmalloc(sizeof(char *) * 16);
+ char **ctype_overrides = xmalloc(sizeof(char *) * 16);
for (int i = 0; i < 16; i++)
{
defaults[i] = NULL;
types[i] = NULL;
names[i] = NULL;
+ ctype_overrides[i] = NULL;
}
if (lexer_peek(l).type != TOK_RPAREN)
{
while (1)
{
+ // Check for @ctype("...") before parameter
+ char *ctype_override = NULL;
+ if (lexer_peek(l).type == TOK_AT)
+ {
+ lexer_next(l); // eat @
+ Token attr = lexer_next(l);
+ if (attr.type == TOK_IDENT && attr.len == 5 && strncmp(attr.start, "ctype", 5) == 0)
+ {
+ if (lexer_next(l).type != TOK_LPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ( after @ctype");
+ }
+ Token ctype_tok = lexer_next(l);
+ if (ctype_tok.type != TOK_STRING)
+ {
+ zpanic_at(ctype_tok, "@ctype requires a string argument");
+ }
+ // Extract string content (strip quotes)
+ ctype_override = xmalloc(ctype_tok.len - 1);
+ strncpy(ctype_override, ctype_tok.start + 1, ctype_tok.len - 2);
+ ctype_override[ctype_tok.len - 2] = 0;
+ if (lexer_next(l).type != TOK_RPAREN)
+ {
+ zpanic_at(lexer_peek(l), "Expected ) after @ctype string");
+ }
+ }
+ else
+ {
+ zpanic_at(attr, "Unknown parameter attribute @%.*s", attr.len, attr.start);
+ }
+ }
+
Token t = lexer_next(l);
// Handle 'self'
if (t.type == TOK_IDENT && strncmp(t.start, "self", 4) == 0 && t.len == 4)
@@ -3470,6 +3505,7 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out,
types[count] = type_new_ptr(type_new(TYPE_VOID));
add_symbol(ctx, "self", "void*", types[count]);
}
+ ctype_overrides[count] = ctype_override;
count++;
}
else
@@ -3514,11 +3550,20 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out,
}
else
{
- strcat(buf, type_str);
+ // Use @ctype override if present
+ if (ctype_override)
+ {
+ strcat(buf, ctype_override);
+ }
+ else
+ {
+ strcat(buf, type_str);
+ }
strcat(buf, " ");
strcat(buf, name);
}
+ ctype_overrides[count] = ctype_override;
count++;
if (lexer_peek(l).type == TOK_OP && is_token(lexer_peek(l), "="))
@@ -3593,6 +3638,10 @@ char *parse_and_convert_args(ParserContext *ctx, Lexer *l, char ***defaults_out,
*count_out = count;
*types_out = types;
*names_out = names;
+ if (ctype_overrides_out)
+ {
+ *ctype_overrides_out = ctype_overrides;
+ }
return buf;
}
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;
diff --git a/std/env.zc b/std/env.zc
index 959784f..c63fd3d 100644
--- a/std/env.zc
+++ b/std/env.zc
@@ -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();
}
diff --git a/std/fs.zc b/std/fs.zc
index 4547b30..a00993b 100644
--- a/std/fs.zc
+++ b/std/fs.zc
@@ -14,12 +14,20 @@ include <unistd.h>
include <stdlib.h>
include <stdio.h>
-// TODO: restructure this tomorrow (lol).
+// 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 {
typedef struct DirEntry* DirEntryPtr;
- // Wrappers for FILE* handling due to opaque pointer casting
- 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);
}
@@ -43,22 +51,8 @@ raw {
return (int64_t)ftell((FILE*)stream);
}
- // Wrappers needed because C headers declare these with 'const char*'
- // but Zen C externs generate 'char*', leading to conflicting types.
- 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);
- }
-
- // Wrappers for DIR* handling
- 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);
}
@@ -66,8 +60,8 @@ raw {
return closedir((DIR*)dir);
}
- // struct stat / struct dirent helpers
- 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;
@@ -76,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;
@@ -85,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
@@ -94,26 +90,18 @@ raw {
}
}
-// Direct externs
-extern fn malloc(size: usize) -> void*;
-extern fn free(ptr: void*);
-
-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: I64, whence: int) -> int;
extern fn _z_fs_ftell(stream: void*) -> I64;
-extern fn _z_fs_opendir(name: char*) -> void*;
+extern fn _z_fs_opendir(name: const char*) -> void*;
extern fn _z_fs_closedir(dir: void*) -> int;
-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;
-
struct File {
handle: void*;
@@ -203,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> {
@@ -230,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);
diff --git a/std/io.zc b/std/io.zc
index 2793ecf..cfb9179 100644
--- a/std/io.zc
+++ b/std/io.zc
@@ -2,28 +2,32 @@
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;
+extern fn 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); }
}
-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);
+ vsnprintf(buffer, 1024, fmt, ap);
va_end(ap);
return (char*)buffer;
}
@@ -31,7 +35,7 @@ fn format(fmt: char*, ...) -> char* {
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);
+ let ret = vsnprintf(buffer, size, fmt, ap);
va_end(ap);
return ret;
}
@@ -42,7 +46,7 @@ fn format_new(fmt: char*, ...) -> char* {
let ap: va_list;
va_start(ap, fmt);
- _z_vsnprintf(buffer, 1024, fmt, ap);
+ vsnprintf(buffer, 1024, fmt, ap);
va_end(ap);
return buffer;
}
@@ -50,7 +54,7 @@ fn format_new(fmt: char*, ...) -> char* {
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 +62,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 +76,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 +96,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/map.zc b/std/map.zc
index 70d6ad2..8376da2 100644
--- a/std/map.zc
+++ b/std/map.zc
@@ -3,16 +3,20 @@ 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> {
diff --git a/std/net.zc b/std/net.zc
index dd10642..d410a4d 100644
--- a/std/net.zc
+++ b/std/net.zc
@@ -13,8 +13,17 @@ 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);
@@ -28,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);
@@ -42,19 +51,15 @@ raw {
return accept(fd, NULL, NULL);
}
- 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 read(fd: int, buf: void*, count: usize) -> isize;
-
-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_write(fd: int, buf: char*, n: usize) -> isize;
+extern fn _z_net_write(fd: int, buf: const char*, n: usize) -> isize;
struct TcpStream {
diff --git a/std/process.zc b/std/process.zc
index d0b09a9..3ce43b6 100644
--- a/std/process.zc
+++ b/std/process.zc
@@ -5,8 +5,16 @@ import "./mem.zc";
import "./string.zc";
import "./option.zc";
-raw {
- void *_z_popen(char *command, char *type) {
+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);
}
@@ -17,16 +25,11 @@ raw {
char *_z_fgets(char *s, int size, void *stream) {
return fgets(s, size, (FILE *)stream);
}
-
- int _z_system(char *command) {
- return system(command);
- }
}
-extern fn _z_popen(command: char*, type: char*) -> void*;
+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*;
-extern fn _z_system(command: char*) -> int;
struct Output {
stdout: String;
@@ -105,7 +108,7 @@ impl Command {
fn status(self) -> int {
let cmd_str = self._build_cmd();
- let code = _z_system(cmd_str.c_str());
+ let code = system(cmd_str.c_str());
cmd_str.free();
return code;
}
diff --git a/std/set.zc b/std/set.zc
index ba6c93f..e1faab3 100644
--- a/std/set.zc
+++ b/std/set.zc
@@ -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/thread.zc b/std/thread.zc
index 98f080e..16f3ca1 100644
--- a/std/thread.zc
+++ b/std/thread.zc
@@ -7,6 +7,11 @@ 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*);
diff --git a/std/time.zc b/std/time.zc
index 865dd6d..fa764ed 100644
--- a/std/time.zc
+++ b/std/time.zc
@@ -5,6 +5,9 @@ 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 {
static uint64_t _time_now_impl(void) {
struct timeval tv;