From ae5fee63f160643a397d18e9e0658275606bc4d4 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Tue, 7 Mar 2023 02:18:26 +0200 Subject: initial commit --- examples/alloc.ct | 18 ++++++++++ examples/arc.ct | 53 +++++++++++++++++++++++++++++ examples/example.ct | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++ examples/numeral.ct | 35 +++++++++++++++++++ examples/option.ct | 6 ++++ examples/std.ct | 35 +++++++++++++++++++ examples/v.ct | 12 +++++++ examples/vec.ct | 62 ++++++++++++++++++++++++++++++++++ 8 files changed, 318 insertions(+) create mode 100644 examples/alloc.ct create mode 100644 examples/arc.ct create mode 100644 examples/example.ct create mode 100644 examples/numeral.ct create mode 100644 examples/option.ct create mode 100644 examples/std.ct create mode 100644 examples/v.ct create mode 100644 examples/vec.ct (limited to 'examples') diff --git a/examples/alloc.ct b/examples/alloc.ct new file mode 100644 index 0000000..5f11bb7 --- /dev/null +++ b/examples/alloc.ct @@ -0,0 +1,18 @@ +/* from c bindings */ + +pub alloc(s usize) *void +{ + p *u8 = malloc(s); + assert(p, "memory allocation failed\n"); + return p; +} + +pub dealloc(p *void) +{ + free(p); +} + +pub realloc(p *, s usize) *void +{ + realloc(p, s); +} diff --git a/examples/arc.ct b/examples/arc.ct new file mode 100644 index 0000000..8869b42 --- /dev/null +++ b/examples/arc.ct @@ -0,0 +1,53 @@ +/* could be non-null instead of raw pointer? */ +typedef atomic_rc [t any] { + count *usize; + data *t; +} + +/* macros must be 'called' with () */ +pub define arc(t) { struct (atomic_rc[t]) }; + +pub dereference(a *arc) *#a.data +{ + return a.t; +} + +pub init(mut a *arc, e #a.data) +{ + new(a.count, 0); + a.data = e; +} + +pub init(mut a *arc, b *arc<#a.data>) +{ + copy(a, b); +} + +pub deinit(mut a *arc) +{ + if atomic_fetch_add(a.count, -1) == 1 { + dealloc(a.data); + dealloc(a.count); + } + + a.count = null; + a.data = null; +} + +pub copy(mut a *arc, b *arc<#a.data>) +{ + deinit(a); + a.count = b.count; + a.data = b.data; + atomic_fetch_add(b.count, 1); +} + +pub move(mut a *arc, mut b *arc<#a.data>) +{ + deinit(a); + a.count = b.count; + a.data = b.data; + /* reference count stays the same */ + b.count = null; + a.count = null; +} diff --git a/examples/example.ct b/examples/example.ct new file mode 100644 index 0000000..ce3e4e7 --- /dev/null +++ b/examples/example.ct @@ -0,0 +1,97 @@ +/* String example */ + +pub struct string { + len usize; + buf *u8; +} + +pub init(mut s *string) +{ + s.len = 0; + s.buf = null; +} + +pub deinit(mut s *string) +{ + dealloc(s.buf); +} + +pub init(mut s *string, u *u8) +{ + len usize = 0; + r any = u; + while r++ {len++;} + + s.len = len; + s.buf = alloc(s.len); + memcpy(s.buf, u); +} + +pub copy(mut r *string, s *string) *string +{ + dealloc(r.buf); + r.len = s.len; + r.buf = alloc(r.len); + memcpy(r.buf, s.buf); +} + +pub move(mut r *string, mut s *string) *string +{ + dealloc(r.buf); + r.len = s.len; + r.buf = s.buf; + s.buf = null; + s.len = 0; +} + +pub length(s *string) usize +{ + return s.len; +} + +pub index(s *string, i usize) u8 +{ + assert(i < len, "index %zu out of bounds\n", i); + return s.buf[i]; +} + +pub add(r *string, a *string, b *string) +{ + len any = length(a) + length(b); + buf any = alloc(l); + + if r.buf == a.buf { + dealloc(a.buf); + } else if r.buf == b.buf { + dealloc(b.buf); + } + + r.buf = buf; + r.len = len; +} + +pub define new(x ...args) +{ + x = alloc(sizeof(x)); + init(@ ...args); +} + +pub define ctx(x ...args) +{ + init(&x ...args); + defer(deinit(@)); +} + +main(argc i32, argv [argc] * u8) +{ + something = argv[10]; // run type bounds checking for ranged array? + // will not be automatically freed + new(a *string); + new(b *string, "hello"); + c string; // undefined state + // will be automatically 'freed' + ctx(c string); + ctx(v vec); + append(v, a); + append(v, c); +} diff --git a/examples/numeral.ct b/examples/numeral.ct new file mode 100644 index 0000000..38936e9 --- /dev/null +++ b/examples/numeral.ct @@ -0,0 +1,35 @@ +/* good optimisation target: make these built in */ +type numeral { + u8; + u16; + u32; + u64; + i8; + i16; + i32; + i64; + isize; + usize; + float; + double; +} + +pub init(mut a *numeral) +{ + *a = 0; +} + +pub deinit(mut a *numeral) +{ + *a = 0; +} + +pub copy(mut a *numeral, b *numeral) +{ + *a = *b; +} + +pub move(mut a *numeral, mut b *numeral) +{ + *a = *b; +} diff --git a/examples/option.ct b/examples/option.ct new file mode 100644 index 0000000..483a9ee --- /dev/null +++ b/examples/option.ct @@ -0,0 +1,6 @@ +type t {any}; + +struct option { + u8 res; + t val; +}; diff --git a/examples/std.ct b/examples/std.ct new file mode 100644 index 0000000..339459f --- /dev/null +++ b/examples/std.ct @@ -0,0 +1,35 @@ +type std { + init(mut * any); + deinit(mut * any); + copy(mut * any, * any); + move(mut * any, mut * any); +} + +/* these as well could be way optimized for builtin types */ +type comparable { + equal(* any, * any) bool; + less_than(* any, * any) bool; +} + +/* I'm imagining that if someone provides a specific function for these, it will + * be used rather than these ones, but that the minimum to implement comparable + * is as small as possible this should be fine */ +pub not_equal(a * comparable, b * comparable) bool +{ + return !equal(a, b); +} + +pub greater_than(a * comparable. b * comparable) bool +{ + return !equal(a, b) && !less_than(a, b); +} + +pub less_or_equal(a * comparable, b * comparable) bool +{ + return !greater_than(a, b); +} + +pub greater_or_equal(a * comparable, b * comparable) bool +{ + return !less_than(a, b); +} diff --git a/examples/v.ct b/examples/v.ct new file mode 100644 index 0000000..2026d55 --- /dev/null +++ b/examples/v.ct @@ -0,0 +1,12 @@ +main(argc u32, argv[argc] *u8) i32 +{ + ctx(vec(u32) a); + // equivalent to + ctx(struct (vec[u32]) a); + + // All entities defined with struct [vector] are seen as the same + // structure, i.e. mangled the same. Something like vector_u32 + // If someone adds a name, i.e. structure lol [vector(u32)] the mangling + // is lol_vector_u32 and considered a different type. All identical + // definitions of structs are considered the same struct, in short. +} diff --git a/examples/vec.ct b/examples/vec.ct new file mode 100644 index 0000000..f44fec0 --- /dev/null +++ b/examples/vec.ct @@ -0,0 +1,62 @@ +typedef vectorable { + std; + /* this would be needed for comparisons like find() or something */ + comparable; +} + +typedef vec (t vectorable) { + void std_vector; + len usize; + buf *t; +} + +pub define vec(t) { struct (vector[t]) } + +pub init(mut v *vector) +{ + v.len = 0; + v.buf = null; +} + +pub length(v *vec) usize { return v.len; } + +pub index(v *vec, i usize) *#(v.buf) +{ + assert(i < v.len, "index %zu out of bounds\n", i); + return &v.buf[i]; +} + +pub index(v *vec, i isize) *#v.buf +{ + if i < 0 { + assert(-i < v.len, "reverse index %zi out of bounds\n", i); + return &v.buf[v.len + i]; + } + + assert(i < v.len, "index %zi out of bounds\n", i); + return &v.buf[i]; +} + +pub prepend(mut *vec, e *#v.buf) { insert(v, e, 0uz); } +pub append(mut v *vec, e *#v.buf) { insert(v, e, v.len) } + +pub preplace(mut v *vec, e *#v.buf) { place(v, e, 0uz); } +pub applace(mut v *vec, e *#v.buf) { place(v, e, v.len - 1); } + +pub place(mut v *vec, e *#v.buf, i usize) +{ +} + +pub insert(mut v *vec, e *#v.buf, i usize) +{ +} + +pub deinit(mut v *vec) +{ + for i usize : v { + deinit(v[i]); + v[i] = null; + } + + dealloc(v.buf); +} -- cgit v1.3