Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
adding generic linked list and pool indirection
Browse files Browse the repository at this point in the history
lists and maps can use either tail as memory or an external pool
  • Loading branch information
aep committed Sep 7, 2020
1 parent daa4399 commit 3731c8a
Show file tree
Hide file tree
Showing 10 changed files with 334 additions and 85 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -23,7 +23,7 @@ Get the latest binary from http://bin.zetz.it

### how it looks

ZZ has strong rust aesthetics, but remains a C dialect at the core.
ZZ has some go and rust aesthetics, but remains a C dialect at the core.


```C++
Expand Down
6 changes: 6 additions & 0 deletions modules/list/.gitignore
@@ -0,0 +1,6 @@
/target
.gdb_history
vgcore.*
**/*.o
**/*.parsecache
**/*.buildcache
166 changes: 166 additions & 0 deletions modules/list/src/lib.zz
@@ -0,0 +1,166 @@
using pool;
using err;
using slice;
using mem;
using log;

/// a linked list item
export struct Item {
slice::Slice val;
Item mut * next;
}

/// a linked list
export struct List+ {
Item mut root;
usize mut count;
pool::Pool+ mut pool;
}

/// create a new list
///
/// new+1000 l = list::make();
export fn make(List+lt mut new* self) {
mem::zero(self);
self->pool.make(sizeof(Item));
}

/// create a new list with an additional pool
///
/// the extra pool is used when tail memory is full
/// you can also use no tail memory at all by setting it to 0
///
/// new+1000 p = pool::make(8);
/// new+0 l = list::make_with_pool(&p);
///
export fn make_with_pool(List+lt mut new* self, pool::Pool mut * pool) {
mem::zero(self);
self->pool.make(sizeof(Item));
self->pool.extra = pool;
}

/// append owned value
/// returns false if there is no memory left in the pool
export fn push(List mut* self, void+vt * val) bool
{
void mut * m = self->pool.malloc(unsafe<usize>(sizeof(Item)) + vt);
if m == 0 {
return false;
}

Item mut *item = (Item mut *)m;
u8 mut * owned_val = unsafe<u8 mut*>(m + unsafe<usize>(sizeof(Item)));

static_attest(safe(item));
static_attest(safe(owned_val));
static_attest(len(owned_val) == vt);
mem::copy(val, owned_val, vt);

item->val = slice::slice::Slice {
mem: owned_val,
size: vt,
};

Item mut * mut search = &self->root;
while search->next != 0 {
search = search->next;
}
search->next = item;

self->count += 1;

return true;
}

/// append borrowed value
/// the borrowed references must be valid for the lifetime of the list
/// returns false if there is no memory left in the pool
export fn push_b(List mut* self, void+vt * val) bool
{
void mut * m = self->pool.malloc(unsafe<usize>(sizeof(Item)));
if m == 0 {
return false;
}

Item mut *item = (Item mut *)m;
static_attest(safe(item));

item->val = slice::slice::Slice {
mem: val,
size: vt,
};

Item mut * mut search = &self->root;
while search->next != 0 {
search = search->next;
}
search->next = item;

self->count += 1;

return true;
}



/// delete first item
export fn pop(List mut* self) bool {
static_attest(safe(self->pool));

if self->root.next == 0 {
return false;
}
static_attest(safe(self->root.next));


let t = self->root.next;
self->root.next = self->root.next->next;


static_attest(pool::member(t, &self->pool));
self->pool.free(t);


self->count -= 1;
return true;
}



/// an Iterator over a List
export struct Iter {
Item mut * mut item;
slice::Slice val;
}

/// return an Iterator over the List
///
/// for let mut i = l.iter(); i.next(); {
/// log::info(">%.*s<", i.val.size, i.val.mem);
/// }
export fn iter(List mut* self) Iter
{
return Iter {
item: &self->root
};
}

/// iterator next
export fn next(Iter mut*self) bool
model safe(self->item)
model slice::slice::integrity(&self->val)
{
static_attest(slice::slice::integrity(&self->val));
static_attest(safe(self->item));
if self->item->next == 0 {
return false;
}
self->item = self->item->next;
static_attest(safe(self->item));

self->val = self->item->val;

static_attest(slice::slice::integrity(&self->val));
return true;
}

38 changes: 38 additions & 0 deletions modules/list/src/main.zz
@@ -0,0 +1,38 @@
using log;
using list;
using pool;

export fn main() int {

new+1000 p = pool::make(8);
new+0 l = list::make_with_pool(&p);

l.push("hello");
l.push_b("bob");

for let mut i = l.iter(); i.next(); {
log::info(">%.*s<", i.val.size, i.val.mem);
}

l.pop();

for let mut i = l.iter(); i.next(); {
log::info(">%.*s<", i.val.size, i.val.mem);
}

l.pop();

for let mut i = l.iter(); i.next(); {
log::info(">%.*s<", i.val.size, i.val.mem);
}

l.pop();

for let mut i = l.iter(); i.next(); {
log::info(">%.*s<", i.val.size, i.val.mem);
}

l.push("bob");

return 0;
}
14 changes: 14 additions & 0 deletions modules/list/zz.toml
@@ -0,0 +1,14 @@
[project]
version = "0.1.0"
name = "list"
cincludes = []
cobjects = []
pkgconfig = []
cflags = []

[dependencies]
log = "1"
mem = "1"
pool = "1"

[repos]
16 changes: 16 additions & 0 deletions modules/map/src/lib.zz
Expand Up @@ -42,6 +42,22 @@ export fn make(Map+tt mut new* self) {
err::assert_safe(self->buckets);
}

/// create a new map with an additional pool
///
/// the extra pool is used when tail memory is full
/// you can also use no tail memory at all by setting it to 0
///
/// new+1000 p = pool::make(8);
/// new+0 l = map::make_with_pool(&p);
export fn make_with_pool(Map+tt mut new* self, pool::Pool mut *extra) {
memset(self, 0, sizeof(Map));

self->p.make(sizeof(Bucket));
self->p.extra = extra;
self->buckets_reserved = tt/unsafe<usize>(sizeof(Bucket))/10;
self->buckets = self->p.malloc(unsafe<usize>(sizeof(Bucket)) * self->buckets_reserved);
err::assert_safe(self->buckets);
}

/// count number of items
export fn count(Map * self) -> usize
Expand Down

0 comments on commit 3731c8a

Please sign in to comment.