Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions std/POLICY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Wave STD Policy

This document defines non-negotiable rules for the Wave standard library (`std/`).

## 1) Layering Rules

- `std/libc/**` is the only directory allowed to declare `extern(c)`.
- Outside `std/libc/**`, modules must use Wave code and/or `std/sys/**` raw syscall wrappers.
- High-level modules (`std/io`, `std/fs`, `std/net`, `std/process`, `std/mem`, etc.) must not import `std::libc::*`.

## 2) Syntax Rules

- `var` declarations are banned in `std/**`.
- Use `let` for immutable values.
- Use `let mut` for mutable values.

## 3) Runtime Contract Rules

- `std/sys/**` should preserve raw syscall style: success `>= 0`, errors as negative `-errno`.
- High-level `std/**` modules may define additional library-level error codes when needed.

## 4) Compatibility Rules

- All `std/` code must remain compatible with the `v0.1.8-pre-beta` compiler baseline.
- Avoid patterns known to break older codegen paths (for example, complex index expressions in single brackets).

## 5) Automated Check

Run:

```bash
./tools/check_std_policy.sh
```

The checker validates:

- `extern(c)` appears only under `std/libc/**`
- no `std::libc::*` import outside `std/libc/**`
- no `var` usage in `std/**`
4 changes: 4 additions & 0 deletions std/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ This is Wave's standard library. This standard library operates independently of
- `std::path`: allocation-free path utilities.
- `std::mem`: manual memory utilities for non-GC code.
- `std::buffer`: growable byte buffer built on `std::mem`.
- `std::io`: fd-level read/write/seek/copy helpers.
- `std::fs`: basic open/read/write/copy/metadata helpers.
- `std::bytes`: endian swap/load/store helpers.
- `std::process`: fork/exec/wait and stdio redirection helpers.

## Layout

Expand Down
32 changes: 16 additions & 16 deletions std/buffer/alloc.wave
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import("std::mem::ops");
import("std::buffer::types");

fun buffer_new(capacity: i64) -> Buffer {
var cap: i64 = capacity;
let mut cap: i64 = capacity;
if (cap <= 0) {
cap = 64;
}

var data: ptr<u8> = mem_alloc(cap);
let mut data: ptr<u8> = mem_alloc(cap);
if (data == null) {
return Buffer {
data: null,
Expand All @@ -41,7 +41,7 @@ fun buffer_new_default() -> Buffer {
}

fun buffer_free(buf: ptr<Buffer>) -> i64 {
var ret: i64 = 0;
let mut ret: i64 = 0;

if (deref buf.cap > 0) {
ret = mem_free(deref buf.data, deref buf.cap);
Expand All @@ -62,7 +62,7 @@ fun buffer_reserve(buf: ptr<Buffer>, required_cap: i64) -> i64 {
return 0;
}

var new_cap: i64 = deref buf.cap;
let mut new_cap: i64 = deref buf.cap;
if (new_cap <= 0) {
new_cap = 64;
}
Expand All @@ -71,7 +71,7 @@ fun buffer_reserve(buf: ptr<Buffer>, required_cap: i64) -> i64 {
new_cap = new_cap * 2;
}

var new_data: ptr<u8> = mem_alloc(new_cap);
let mut new_data: ptr<u8> = mem_alloc(new_cap);
if (new_data == null) {
return -1;
}
Expand All @@ -92,32 +92,32 @@ fun buffer_reserve(buf: ptr<Buffer>, required_cap: i64) -> i64 {

fun tbuffer_new<T>(elem_size: i64, initial_cap: i64) -> TypedBuffer<T> {
if (elem_size <= 0) {
var empty: TypedBuffer<T>;
let mut empty: TypedBuffer<T>;
empty.data = null;
empty.len = 0;
empty.cap_bytes = 0;
empty.elem_size = 0;
return empty;
}

var cap_elems: i64 = initial_cap;
let mut cap_elems: i64 = initial_cap;
if (cap_elems <= 0) {
cap_elems = 16;
}

var cap_bytes: i64 = cap_elems * elem_size;
var data: ptr<u8> = mem_alloc(cap_bytes);
let mut cap_bytes: i64 = cap_elems * elem_size;
let mut data: ptr<u8> = mem_alloc(cap_bytes);

if (data == null) {
var failed: TypedBuffer<T>;
let mut failed: TypedBuffer<T>;
failed.data = null;
failed.len = 0;
failed.cap_bytes = 0;
failed.elem_size = elem_size;
return failed;
}

var created: TypedBuffer<T>;
let mut created: TypedBuffer<T>;
created.data = data;
created.len = 0;
created.cap_bytes = cap_bytes;
Expand All @@ -126,7 +126,7 @@ fun tbuffer_new<T>(elem_size: i64, initial_cap: i64) -> TypedBuffer<T> {
}

fun tbuffer_free<T>(buf: ptr<TypedBuffer<T>>) -> i64 {
var ret: i64 = 0;
let mut ret: i64 = 0;

if (deref buf.cap_bytes > 0) {
ret = mem_free(deref buf.data, deref buf.cap_bytes);
Expand All @@ -152,12 +152,12 @@ fun tbuffer_reserve<T>(buf: ptr<TypedBuffer<T>>, required_len: i64) -> i64 {
return 0;
}

var required_bytes: i64 = required_len * deref buf.elem_size;
let mut required_bytes: i64 = required_len * deref buf.elem_size;
if (required_bytes <= deref buf.cap_bytes) {
return 0;
}

var new_cap_bytes: i64 = deref buf.cap_bytes;
let mut new_cap_bytes: i64 = deref buf.cap_bytes;
if (new_cap_bytes <= 0) {
new_cap_bytes = deref buf.elem_size * 16;
}
Expand All @@ -166,12 +166,12 @@ fun tbuffer_reserve<T>(buf: ptr<TypedBuffer<T>>, required_len: i64) -> i64 {
new_cap_bytes = new_cap_bytes * 2;
}

var new_data: ptr<u8> = mem_alloc(new_cap_bytes);
let mut new_data: ptr<u8> = mem_alloc(new_cap_bytes);
if (new_data == null) {
return -1;
}

var used_bytes: i64 = deref buf.len * deref buf.elem_size;
let mut used_bytes: i64 = deref buf.len * deref buf.elem_size;
if (used_bytes > 0) {
mem_copy(new_data, deref buf.data, used_bytes);
}
Expand Down
4 changes: 2 additions & 2 deletions std/buffer/read.wave
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ fun tbuffer_at<T>(buf: TypedBuffer<T>, index: i64, out_value: ptr<T>) -> bool {
return false;
}

var offset_bytes: i64 = index * buf.elem_size;
var slot: ptr<T> = (buf.data + offset_bytes) as ptr<T>;
let mut offset_bytes: i64 = index * buf.elem_size;
let mut slot: ptr<T> = (buf.data + offset_bytes) as ptr<T>;
deref out_value = deref slot;

return true;
Expand Down
36 changes: 18 additions & 18 deletions std/buffer/write.wave
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import("std::buffer::types");
import("std::buffer::alloc");

fun buffer_push(buf: ptr<Buffer>, value: u8) -> i64 {
var needed: i64 = deref buf.len + 1;
var ret: i64 = buffer_reserve(buf, needed);
let mut needed: i64 = deref buf.len + 1;
let mut ret: i64 = buffer_reserve(buf, needed);

if (ret < 0) {
return ret;
}

var p: ptr<u8> = deref buf.data;
let mut p: ptr<u8> = deref buf.data;
deref p[deref buf.len] = value;
deref buf.len = needed;

Expand All @@ -33,17 +33,17 @@ fun buffer_append(buf: ptr<Buffer>, src: ptr<u8>, size: i64) -> i64 {
return 0;
}

var base: i64 = deref buf.len;
var needed: i64 = base + size;
var ret: i64 = buffer_reserve(buf, needed);
let mut base: i64 = deref buf.len;
let mut needed: i64 = base + size;
let mut ret: i64 = buffer_reserve(buf, needed);

if (ret < 0) {
return ret;
}

var dst: ptr<u8> = deref buf.data;
var src_idx: i64 = 0;
var dst_idx: i64 = base;
let mut dst: ptr<u8> = deref buf.data;
let mut src_idx: i64 = 0;
let mut dst_idx: i64 = base;

while (src_idx < size) {
deref dst[dst_idx] = src[src_idx];
Expand All @@ -56,10 +56,10 @@ fun buffer_append(buf: ptr<Buffer>, src: ptr<u8>, size: i64) -> i64 {
}

fun buffer_append_str(buf: ptr<Buffer>, s: str) -> i64 {
var i: i64 = 0;
let mut i: i64 = 0;

while (s[i] != 0) {
var ret: i64 = buffer_push(buf, s[i]);
let mut ret: i64 = buffer_push(buf, s[i]);
if (ret < 0) {
return ret;
}
Expand All @@ -74,21 +74,21 @@ fun buffer_set(buf: ptr<Buffer>, index: i64, value: u8) -> bool {
return false;
}

var p: ptr<u8> = deref buf.data;
let mut p: ptr<u8> = deref buf.data;
deref p[index] = value;
return true;
}

fun tbuffer_push<T>(buf: ptr<TypedBuffer<T>>, value: T) -> i64 {
var needed_len: i64 = deref buf.len + 1;
var ret: i64 = tbuffer_reserve<T>(buf, needed_len);
let mut needed_len: i64 = deref buf.len + 1;
let mut ret: i64 = tbuffer_reserve<T>(buf, needed_len);

if (ret < 0) {
return ret;
}

var offset_bytes: i64 = deref buf.len * deref buf.elem_size;
var slot: ptr<T> = (deref buf.data + offset_bytes) as ptr<T>;
let mut offset_bytes: i64 = deref buf.len * deref buf.elem_size;
let mut slot: ptr<T> = (deref buf.data + offset_bytes) as ptr<T>;

deref slot = value;
deref buf.len = needed_len;
Expand All @@ -101,8 +101,8 @@ fun tbuffer_set<T>(buf: ptr<TypedBuffer<T>>, index: i64, value: T) -> bool {
return false;
}

var offset_bytes: i64 = index * deref buf.elem_size;
var slot: ptr<T> = (deref buf.data + offset_bytes) as ptr<T>;
let mut offset_bytes: i64 = index * deref buf.elem_size;
let mut slot: ptr<T> = (deref buf.data + offset_bytes) as ptr<T>;
deref slot = value;

return true;
Expand Down
Loading
Loading