Updated to use the new implicit type for method calls in some libraries. Made the grammar a little more liberal.

This commit is contained in:
Christoffer Lerno
2023-07-02 10:55:25 +02:00
parent 21d8a8b6da
commit 50784d4df6
9 changed files with 338 additions and 352 deletions

View File

@@ -27,21 +27,21 @@ struct Object
}
fn void! Object.to_format(Object* o, Formatter* formatter) @dynamic
fn void! Object.to_format(&self, Formatter* formatter) @dynamic
{
switch (o.type)
switch (self.type)
{
case void:
formatter.printf("{}")!;
case void*:
formatter.printf("null")!;
case String:
formatter.printf(`"%s"`, o.s)!;
formatter.printf(`"%s"`, self.s)!;
case bool:
formatter.printf(o.b ? "true" : "false")!;
formatter.printf(self.b ? "true" : "false")!;
case ObjectInternalList:
formatter.printf("[")!;
foreach (i, ol : o.array)
foreach (i, ol : self.array)
{
formatter.printf(i == 0 ? " " : ", ")!;
ol.to_format(formatter)!;
@@ -51,25 +51,25 @@ fn void! Object.to_format(Object* o, Formatter* formatter) @dynamic
formatter.printf("{")!;
@pool()
{
foreach (i, key : o.map.key_tlist())
foreach (i, key : self.map.key_tlist())
{
formatter.printf(i == 0 ? " " : ", ")!;
formatter.printf(`"%s": `, key)!;
o.map.get(key).to_format(formatter)!;
self.map.get(key).to_format(formatter)!;
}
};
formatter.printf(" }")!;
default:
switch (o.type.kindof)
switch (self.type.kindof)
{
case SIGNED_INT:
formatter.printf("%d", o.i)!;
formatter.printf("%d", self.i)!;
case UNSIGNED_INT:
formatter.printf("%d", (uint128)o.i)!;
formatter.printf("%d", (uint128)self.i)!;
case FLOAT:
formatter.printf("%d", o.f)!;
formatter.printf("%d", self.f)!;
case ENUM:
formatter.printf("%d", o.i)!;
formatter.printf("%d", self.i)!;
default:
formatter.printf("<>")!;
}
@@ -122,87 +122,84 @@ fn Object* new_bool(bool b)
return b ? &TRUE_OBJECT : &FALSE_OBJECT;
}
/**
* @param [&inout] o
**/
fn void Object.free(Object* o)
fn void Object.free(&self)
{
switch (o.type)
switch (self.type)
{
case void:
break;
case String:
free(o.s, .using = o.allocator);
free(self.s, .using = self.allocator);
case ObjectInternalList:
foreach (ol : o.array)
foreach (ol : self.array)
{
ol.free();
}
o.array.free();
self.array.free();
case ObjectInternalMap:
@pool()
{
foreach (key : o.map.key_tlist())
foreach (key : self.map.key_tlist())
{
o.map.get(key).free();
free(key, .using = o.allocator);
self.map.get(key).free();
free(key, .using = self.allocator);
}
o.map.free();
self.map.free();
};
default:
break;
}
if (o.allocator) free(o, .using = o.allocator);
if (self.allocator) free(self, .using = self.allocator);
}
fn bool Object.is_null(Object* this) @inline => this == &NULL_OBJECT;
fn bool Object.is_empty(Object* this) @inline => this.type == void.typeid;
fn bool Object.is_map(Object* this) @inline => this.type == ObjectInternalMap.typeid;
fn bool Object.is_array(Object* this) @inline => this.type == ObjectInternalList.typeid;
fn bool Object.is_bool(Object* this) @inline => this.type == bool.typeid;
fn bool Object.is_string(Object* this) @inline => this.type == String.typeid;
fn bool Object.is_float(Object* this) @inline => this.type == double.typeid;
fn bool Object.is_int(Object* this) @inline => this.type == int128.typeid;
fn bool Object.is_keyable(Object* this) => this.is_empty() || this.is_map();
fn bool Object.is_indexable(Object* this) => this.is_empty() || this.is_array();
fn bool Object.is_null(&self) @inline => self == &NULL_OBJECT;
fn bool Object.is_empty(&self) @inline => self.type == void.typeid;
fn bool Object.is_map(&self) @inline => self.type == ObjectInternalMap.typeid;
fn bool Object.is_array(&self) @inline => self.type == ObjectInternalList.typeid;
fn bool Object.is_bool(&self) @inline => self.type == bool.typeid;
fn bool Object.is_string(&self) @inline => self.type == String.typeid;
fn bool Object.is_float(&self) @inline => self.type == double.typeid;
fn bool Object.is_int(&self) @inline => self.type == int128.typeid;
fn bool Object.is_keyable(&self) => self.is_empty() || self.is_map();
fn bool Object.is_indexable(&self) => self.is_empty() || self.is_array();
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn void Object.init_map_if_needed(Object* o) @private
fn void Object.init_map_if_needed(&self) @private
{
if (o.is_empty())
if (self.is_empty())
{
o.type = ObjectInternalMap.typeid;
o.map.init(.using = o.allocator);
self.type = ObjectInternalMap.typeid;
self.map.init(.using = self.allocator);
}
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn void Object.init_array_if_needed(Object* o) @private
fn void Object.init_array_if_needed(&self) @private
{
if (o.is_empty())
if (self.is_empty())
{
o.type = ObjectInternalList.typeid;
o.array.init(.using = o.allocator);
self.type = ObjectInternalList.typeid;
self.array.init(.using = self.allocator);
}
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn void Object.set_object(Object* o, String key, Object* new_object) @private
fn void Object.set_object(&self, String key, Object* new_object) @private
{
o.init_map_if_needed();
ObjectInternalMapEntry*! entry = o.map.get_entry(key);
self.init_map_if_needed();
ObjectInternalMapEntry*! entry = self.map.get_entry(key);
defer
{
(void)free(entry.key, .using = o.allocator);
(void)free(entry.key, .using = self.allocator);
entry.value.free();
}
o.map.set(key.copy(o.map.allocator), new_object);
self.map.set(key.copy(self.map.allocator), new_object);
}
macro Object* object_from_value(value) @private
@@ -231,76 +228,76 @@ macro Object* object_from_value(value) @private
}
macro Object* Object.set(Object* o, String key, value)
macro Object* Object.set(&self, String key, value)
{
Object* val = object_from_value(value);
o.set_object(key, val);
self.set_object(key, val);
return val;
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
macro Object* Object.set_at(Object* o, usz index, String key, value)
macro Object* Object.set_at(&self, usz index, String key, value)
{
Object* val = object_from_value(value);
o.set_object_at(key, index, val);
self.set_object_at(key, index, val);
return val;
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
* @ensure return != null
**/
macro Object* Object.append(Object* o, value)
macro Object* Object.append(&self, value)
{
Object* val = object_from_value(value);
o.append_object(val);
self.append_object(val);
return val;
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn Object*! Object.get(Object* o, String key) => o.is_empty() ? SearchResult.MISSING? : o.map.get(key);
fn Object*! Object.get(&self, String key) => self.is_empty() ? SearchResult.MISSING? : self.map.get(key);
fn bool Object.has_key(Object* o, String key) => o.is_map() && o.map.has_key(key);
fn bool Object.has_key(&self, String key) => self.is_map() && self.map.has_key(key);
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn Object* Object.get_at(Object* o, usz index)
fn Object* Object.get_at(&self, usz index)
{
return o.array.get(index);
return self.array.get(index);
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn void Object.append_object(Object* o, Object* to_append)
fn void Object.append_object(&self, Object* to_append)
{
o.init_array_if_needed();
o.array.append(to_append);
self.init_array_if_needed();
self.array.append(to_append);
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn void Object.set_object_at(Object* o, usz index, Object* to_set)
fn void Object.set_object_at(&self, usz index, Object* to_set)
{
o.init_array_if_needed();
while (o.array.len() < index)
self.init_array_if_needed();
while (self.array.len() < index)
{
o.array.append(&NULL_OBJECT);
self.array.append(&NULL_OBJECT);
}
if (o.array.len() == index)
if (self.array.len() == index)
{
o.array.append(to_set);
self.array.append(to_set);
return;
}
o.array.get(index).free();
o.array.set_at(index, to_set);
self.array.get(index).free();
self.array.set_at(index, to_set);
}
macro get_integer_value(Object* value, $Type)
@@ -322,112 +319,112 @@ macro get_integer_value(Object* value, $Type)
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
macro Object.get_integer_at(Object* o, $Type, usz index) @private
macro Object.get_integer_at(&self, $Type, usz index) @private
{
return get_integer_value(o.get_at(index), $Type);
return get_integer_value(self.get_at(index), $Type);
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
macro Object.get_integer(Object* o, $Type, String key) @private
macro Object.get_integer(&self, $Type, String key) @private
{
return get_integer_value(o.get(key), $Type);
return get_integer_value(self.get(key), $Type);
}
fn ichar! Object.get_ichar(Object* o, String key) => o.get_integer(ichar, key);
fn short! Object.get_short(Object* o, String key) => o.get_integer(short, key);
fn int! Object.get_int(Object* o, String key) => o.get_integer(int, key);
fn long! Object.get_long(Object* o, String key) => o.get_integer(long, key);
fn int128! Object.get_int128(Object* o, String key) => o.get_integer(int128, key);
fn ichar! Object.get_ichar(&self, String key) => self.get_integer(ichar, key);
fn short! Object.get_short(&self, String key) => self.get_integer(short, key);
fn int! Object.get_int(&self, String key) => self.get_integer(int, key);
fn long! Object.get_long(&self, String key) => self.get_integer(long, key);
fn int128! Object.get_int128(&self, String key) => self.get_integer(int128, key);
fn ichar! Object.get_ichar_at(Object* o, usz index) => o.get_integer_at(ichar, index);
fn short! Object.get_short_at(Object* o, usz index) => o.get_integer_at(short, index);
fn int! Object.get_int_at(Object* o, usz index) => o.get_integer_at(int, index);
fn long! Object.get_long_at(Object* o, usz index) => o.get_integer_at(long, index);
fn int128! Object.get_int128_at(Object* o, usz index) => o.get_integer_at(int128, index);
fn ichar! Object.get_ichar_at(&self, usz index) => self.get_integer_at(ichar, index);
fn short! Object.get_short_at(&self, usz index) => self.get_integer_at(short, index);
fn int! Object.get_int_at(&self, usz index) => self.get_integer_at(int, index);
fn long! Object.get_long_at(&self, usz index) => self.get_integer_at(long, index);
fn int128! Object.get_int128_at(&self, usz index) => self.get_integer_at(int128, index);
fn char! Object.get_char(Object* o, String key) => o.get_integer(ichar, key);
fn short! Object.get_ushort(Object* o, String key) => o.get_integer(ushort, key);
fn uint! Object.get_uint(Object* o, String key) => o.get_integer(uint, key);
fn ulong! Object.get_ulong(Object* o, String key) => o.get_integer(ulong, key);
fn uint128! Object.get_uint128(Object* o, String key) => o.get_integer(uint128, key);
fn char! Object.get_char(&self, String key) => self.get_integer(ichar, key);
fn short! Object.get_ushort(&self, String key) => self.get_integer(ushort, key);
fn uint! Object.get_uint(&self, String key) => self.get_integer(uint, key);
fn ulong! Object.get_ulong(&self, String key) => self.get_integer(ulong, key);
fn uint128! Object.get_uint128(&self, String key) => self.get_integer(uint128, key);
fn char! Object.get_char_at(Object* o, usz index) => o.get_integer_at(char, index);
fn ushort! Object.get_ushort_at(Object* o, usz index) => o.get_integer_at(ushort, index);
fn uint! Object.get_uint_at(Object* o, usz index) => o.get_integer_at(uint, index);
fn ulong! Object.get_ulong_at(Object* o, usz index) => o.get_integer_at(ulong, index);
fn uint128! Object.get_uint128_at(Object* o, usz index) => o.get_integer_at(uint128, index);
fn char! Object.get_char_at(&self, usz index) => self.get_integer_at(char, index);
fn ushort! Object.get_ushort_at(&self, usz index) => self.get_integer_at(ushort, index);
fn uint! Object.get_uint_at(&self, usz index) => self.get_integer_at(uint, index);
fn ulong! Object.get_ulong_at(&self, usz index) => self.get_integer_at(ulong, index);
fn uint128! Object.get_uint128_at(&self, usz index) => self.get_integer_at(uint128, index);
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn String! Object.get_string(Object* o, String key)
fn String! Object.get_string(&self, String key)
{
Object* value = o.get(key)!;
Object* value = self.get(key)!;
assert(value.is_string());
return value.s;
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn String Object.get_string_at(Object* o, usz index)
fn String Object.get_string_at(&self, usz index)
{
Object* value = o.get_at(index);
Object* value = self.get_at(index);
assert(value.is_string());
return value.s;
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
macro String! Object.get_enum(Object* o, $EnumType, String key)
macro String! Object.get_enum(&self, $EnumType, String key)
{
Object value = o.get(key)!;
Object value = self.get(key)!;
assert($EnumType.typeid == value.type);
return ($EnumType)value.i;
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
macro String Object.get_enum_at(Object* o, $EnumType, usz index)
macro String Object.get_enum_at(&self, $EnumType, usz index)
{
Object value = o.get_at(index);
Object value = self.get_at(index);
assert($EnumType.typeid == value.type);
return ($EnumType)value.i;
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn bool! Object.get_bool(Object* o, String key)
fn bool! Object.get_bool(&self, String key)
{
Object* value = o.get(key)!;
Object* value = self.get(key)!;
assert(value.is_bool());
return value.b;
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn bool Object.get_bool_at(Object* o, usz index)
fn bool Object.get_bool_at(&self, usz index)
{
Object* value = o.get_at(index);
Object* value = self.get_at(index);
assert(value.is_bool());
return value.b;
}
/**
* @require o.is_keyable()
* @require self.is_keyable()
**/
fn double! Object.get_float(Object* o, String key)
fn double! Object.get_float(&self, String key)
{
Object* value = o.get(key)!;
Object* value = self.get(key)!;
switch (value.type.kindof)
{
case SIGNED_INT:
@@ -442,11 +439,11 @@ fn double! Object.get_float(Object* o, String key)
}
/**
* @require o.is_indexable()
* @require self.is_indexable()
**/
fn double Object.get_float_at(Object* o, usz index)
fn double Object.get_float_at(&self, usz index)
{
Object* value = o.get_at(index);
Object* value = self.get_at(index);
switch (value.type.kindof)
{
case SIGNED_INT:
@@ -460,11 +457,11 @@ fn double Object.get_float_at(Object* o, usz index)
}
}
fn Object* Object.get_or_create_obj(Object* o, String key)
fn Object* Object.get_or_create_obj(&self, String key)
{
if (try obj = o.get(key) && !obj.is_null()) return obj;
if (try obj = self.get(key) && !obj.is_null()) return obj;
Object* container = new_obj();
o.set(key, container);
self.set(key, container);
return container;
}

View File

@@ -31,16 +31,16 @@ struct PriorityQueue
bool max; // true if max-heap, false if min-heap
}
fn void PriorityQueue.push(PriorityQueue* pq, Type element)
fn void PriorityQueue.push(&self, Type element)
{
pq.heap.push(element);
usz i = pq.heap.len() - 1;
self.heap.push(element);
usz i = self.heap.len() - 1;
while (i > 0)
{
usz parent = (i - 1) / 2;
if ((pq.max && greater(pq.heap.get(i), pq.heap.get(parent))) || (!pq.max && less(pq.heap.get(i), pq.heap.get(parent))))
if ((self.max && greater(self.heap.get(i), self.heap.get(parent))) || (!self.max && less(self.heap.get(i), self.heap.get(parent))))
{
pq.heap.swap(i, parent);
self.heap.swap(i, parent);
i = parent;
continue;
}
@@ -49,75 +49,66 @@ fn void PriorityQueue.push(PriorityQueue* pq, Type element)
}
/**
* @require pq != null
* @require self != null
*/
fn Type! PriorityQueue.pop(PriorityQueue* pq)
fn Type! PriorityQueue.pop(&self)
{
usz i = 0;
usz len = pq.heap.len() @inline;
usz len = self.heap.len() @inline;
if (!len) return IteratorResult.NO_MORE_ELEMENT?;
usz newCount = len - 1;
pq.heap.swap(0, newCount);
self.heap.swap(0, newCount);
while ((2 * i + 1) < newCount)
{
usz j = 2 * i + 1;
if (((j + 1) < newCount) &&
((pq.max && greater(pq.heap.get(j + 1), pq.heap[j]))
|| (!pq.max && less(pq.heap.get(j + 1), pq.heap.get(j)))))
((self.max && greater(self.heap.get(j + 1), self.heap[j]))
|| (!self.max && less(self.heap.get(j + 1), self.heap.get(j)))))
{
j++;
}
if ((pq.max && less(pq.heap.get(i), pq.heap.get(j))) || (!pq.max && greater(pq.heap.get(i), pq.heap.get(j))))
if ((self.max && less(self.heap.get(i), self.heap.get(j))) || (!self.max && greater(self.heap.get(i), self.heap.get(j))))
{
pq.heap.swap(i, j);
self.heap.swap(i, j);
i = j;
continue;
}
break;
}
return pq.heap.pop();
return self.heap.pop();
}
fn Type! PriorityQueue.peek(&self)
{
if (!self.len()) return IteratorResult.NO_MORE_ELEMENT?;
return self.heap.get(0);
}
fn void PriorityQueue.free(&self)
{
self.heap.free();
}
fn usz PriorityQueue.len(&self) @operator(len)
{
return self.heap.len();
}
/**
* @require pq != null
* @require index < self.len()
*/
fn Type! PriorityQueue.peek(PriorityQueue* pq)
fn Type PriorityQueue.peek_at(&self, usz index) @operator([])
{
if (!pq.len()) return IteratorResult.NO_MORE_ELEMENT?;
return pq.heap.get(0);
return self.heap[index];
}
/**
* @require pq != null
*/
fn void PriorityQueue.free(PriorityQueue* pq)
fn void! PriorityQueue.to_format(&self, Formatter* formatter) @dynamic
{
pq.heap.free();
return self.heap.to_format(formatter);
}
/**
* @require pq != null
*/
fn usz PriorityQueue.len(PriorityQueue* pq) @operator(len)
fn String PriorityQueue.to_string(&self, Allocator* using = mem::heap()) @dynamic
{
return pq.heap.len();
}
/**
* @require pq != null, index < pq.len()
*/
fn Type PriorityQueue.peek_at(PriorityQueue* pq, usz index) @operator([])
{
return pq.heap[index];
}
fn void! PriorityQueue.to_format(PriorityQueue* list, Formatter* formatter) @dynamic
{
return list.heap.to_format(formatter);
}
fn String PriorityQueue.to_string(PriorityQueue* list, Allocator* using = mem::heap()) @dynamic
{
return list.heap.to_string(using);
return self.heap.to_string(using);
}

View File

@@ -10,28 +10,28 @@ struct Range
Type end;
}
fn usz Range.len(Range* range) @operator(len)
fn usz Range.len(&self) @operator(len)
{
if (range.end < range.start) return 0;
return (usz)(range.end - range.start + (Type)1);
if (self.end < self.start) return 0;
return (usz)(self.end - self.start + (Type)1);
}
/**
* @require index < range.len() : "Can't index into an empty range"
* @require index < self.len() : "Can't index into an empty range"
**/
fn Type Range.get(Range* range, usz index) @operator([])
fn Type Range.get(&self, usz index) @operator([])
{
return range.start + (Type)index;
return self.start + (Type)index;
}
fn String Range.to_string(Range* list, Allocator* using = mem::heap()) @dynamic
fn String Range.to_string(&self, Allocator* using = mem::heap()) @dynamic
{
return string::printf("[%s..%s]", list.start, list.end);
return string::printf("[%s..%s]", self.start, self.end);
}
fn void! Range.to_format(Range* list, Formatter* formatter) @dynamic
fn void! Range.to_format(&self, Formatter* formatter) @dynamic
{
formatter.printf("[%s..%s]", list.start, list.end)!;
formatter.printf("[%s..%s]", self.start, self.end)!;
}
struct ExclusiveRange
@@ -40,26 +40,26 @@ struct ExclusiveRange
Type end;
}
fn usz ExclusiveRange.len(ExclusiveRange* range) @operator(len)
fn usz ExclusiveRange.len(&self) @operator(len)
{
if (range.end < range.start) return 0;
return (usz)(range.end - range.start);
if (self.end < self.start) return 0;
return (usz)(self.end - self.start);
}
fn void! ExclusiveRange.to_format(ExclusiveRange* list, Formatter* formatter) @dynamic
fn void! ExclusiveRange.to_format(&self, Formatter* formatter) @dynamic
{
formatter.printf("[%s..<%s]", list.start, list.end)!;
formatter.printf("[%s..<%s]", self.start, self.end)!;
}
fn String ExclusiveRange.to_string(ExclusiveRange* list, Allocator* using = mem::heap()) @dynamic
fn String ExclusiveRange.to_string(&self, Allocator* using = mem::heap()) @dynamic
{
return string::printf("[%s..<%s]", list.start, list.end);
return string::printf("[%s..<%s]", self.start, self.end);
}
/**
* @require index < range.len() : "Can't index into an empty range"
* @require index < self.len() : "Can't index into an empty range"
**/
fn Type ExclusiveRange.get(ExclusiveRange* range, usz index) @operator([])
fn Type ExclusiveRange.get(&self, usz index) @operator([])
{
return range.start + (Type)index;
return self.start + (Type)index;
}

View File

@@ -12,36 +12,34 @@ struct Rc4
/**
* Initialize the RC4 state.
*
* @param [inout] this "The RC4 state"
* @param [in] key "The key to use"
* @require key.len > 0 "The key must be at least 1 byte long"
**/
fn void Rc4.init(Rc4* this, char[] key)
fn void Rc4.init(&self, char[] key)
{
// Init the state matrix
foreach (char i, &c : this.state) *c = i;
foreach (char i, &c : self.state) *c = i;
for (int i = 0, int j = 0; i < 256; i++)
{
j = (j + this.state[i] + key[i % key.len]) & 0xFF;
@swap(this.state[i], this.state[j]);
j = (j + self.state[i] + key[i % key.len]) & 0xFF;
@swap(self.state[i], self.state[j]);
}
this.i = 0;
this.j = 0;
self.i = 0;
self.j = 0;
}
/**
* Encrypt or decrypt a sequence of bytes.
*
* @param [inout] this "The RC4 State"
* @param [in] in "The input"
* @param [out] out "The output"
* @require in.len <= out.len "Output would overflow"
**/
fn void Rc4.crypt(Rc4* this, char[] in, char[] out)
fn void Rc4.crypt(&self, char[] in, char[] out)
{
uint i = this.i;
uint j = this.j;
char* state = &this.state;
uint i = self.i;
uint j = self.j;
char* state = &self.state;
isz len = in.len;
foreach (idx, c : in)
{
@@ -50,16 +48,16 @@ fn void Rc4.crypt(Rc4* this, char[] in, char[] out)
@swap(state[i], state[j]);
out[idx] = in[idx] ^ state[(state[i] + state[j]) & 0xFF];
}
this.i = i;
this.j = j;
self.i = i;
self.j = j;
}
/**
* Clear the rc4 state.
*
* @param [out] this "The RC4 State"
* @param [&out] self "The RC4 State"
**/
fn void Rc4.destroy(Rc4* this)
fn void Rc4.destroy(&self)
{
*this = {};
*self = {};
}

View File

@@ -32,10 +32,10 @@ fault Base64Error
* @require padding < 256
* @return! Base64Error.DUPLICATE_IN_ALPHABET, Base64Error.PADDING_IN_ALPHABET
**/
fn void! Base64Encoder.init(Base64Encoder* b, String alphabet, int padding = '=')
fn void! Base64Encoder.init(&self, String alphabet, int padding = '=')
{
check_alphabet(alphabet, padding)!;
*b = { .padding = padding, .alphabet = alphabet };
*self = { .padding = padding, .alphabet = alphabet };
}
/**
@@ -43,9 +43,9 @@ fn void! Base64Encoder.init(Base64Encoder* b, String alphabet, int padding = '='
* @param n "Size of the input to be encoded."
* @return "The size of the input once encoded."
**/
fn usz Base64Encoder.encode_len(Base64Encoder *b, usz n)
fn usz Base64Encoder.encode_len(&self, usz n)
{
if (b.padding >= 0) return (n + 2) / 3 * 4;
if (self.padding >= 0) return (n + 2) / 3 * 4;
usz trailing = n % 3;
return n / 3 * 4 + (trailing * 4 + 2) / 3;
}
@@ -57,10 +57,10 @@ fn usz Base64Encoder.encode_len(Base64Encoder *b, usz n)
* @return "The encoded size."
* @return! Base64Error.DESTINATION_TOO_SMALL
**/
fn usz! Base64Encoder.encode(Base64Encoder *b, char[] src, char[] dst)
fn usz! Base64Encoder.encode(&self, char[] src, char[] dst)
{
if (src.len == 0) return 0;
usz dn = b.encode_len(src.len);
usz dn = self.encode_len(src.len);
if (dst.len < dn) return Base64Error.DESTINATION_TOO_SMALL?;
usz trailing = src.len % 3;
char[] src3 = src[:^trailing];
@@ -68,10 +68,10 @@ fn usz! Base64Encoder.encode(Base64Encoder *b, char[] src, char[] dst)
while (src3.len > 0)
{
uint group = (uint)src3[0] << 16 | (uint)src3[1] << 8 | (uint)src3[2];
dst[0] = b.alphabet[group >> 18 & MASK];
dst[1] = b.alphabet[group >> 12 & MASK];
dst[2] = b.alphabet[group >> 6 & MASK];
dst[3] = b.alphabet[group & MASK];
dst[0] = self.alphabet[group >> 18 & MASK];
dst[1] = self.alphabet[group >> 12 & MASK];
dst[2] = self.alphabet[group >> 6 & MASK];
dst[3] = self.alphabet[group & MASK];
dst = dst[4..];
src3 = src3[3..];
}
@@ -82,22 +82,22 @@ fn usz! Base64Encoder.encode(Base64Encoder *b, char[] src, char[] dst)
{
case 1:
uint group = (uint)src[^1] << 16;
dst[0] = b.alphabet[group >> 18 & MASK];
dst[1] = b.alphabet[group >> 12 & MASK];
if (b.padding >= 0)
dst[0] = self.alphabet[group >> 18 & MASK];
dst[1] = self.alphabet[group >> 12 & MASK];
if (self.padding >= 0)
{
char pad = (char)b.padding;
char pad = (char)self.padding;
dst[2] = pad;
dst[3] = pad;
}
case 2:
uint group = (uint)src[^2] << 16 | (uint)src[^1] << 8;
dst[0] = b.alphabet[group >> 18 & MASK];
dst[1] = b.alphabet[group >> 12 & MASK];
dst[2] = b.alphabet[group >> 6 & MASK];
if (b.padding >= 0)
dst[0] = self.alphabet[group >> 18 & MASK];
dst[1] = self.alphabet[group >> 12 & MASK];
dst[2] = self.alphabet[group >> 6 & MASK];
if (self.padding >= 0)
{
char pad = (char)b.padding;
char pad = (char)self.padding;
dst[3] = pad;
}
}
@@ -119,20 +119,20 @@ struct Base64Decoder
* @require padding < 256
* @return! Base64Error.DUPLICATE_IN_ALPHABET, Base64Error.PADDING_IN_ALPHABET
**/
fn void! Base64Decoder.init(Base64Decoder* b, String alphabet, int padding = '=')
fn void! Base64Decoder.init(&self, String alphabet, int padding = '=')
{
check_alphabet(alphabet, padding)!;
*b = { .padding = padding, .alphabet = alphabet };
*self = { .padding = padding, .alphabet = alphabet };
bool[256] checked;
foreach (i, c : alphabet)
{
checked[c] = true;
b.reverse[c] = (char)i;
self.reverse[c] = (char)i;
}
if (padding < 0)
{
b.invalid = 255;
self.invalid = 255;
return;
}
// Find a character for invalid neither in the alphabet nor equal to the padding.
@@ -141,7 +141,7 @@ fn void! Base64Decoder.init(Base64Decoder* b, String alphabet, int padding = '='
{
if (!ok && (char)i != pad)
{
b.invalid = (char)i;
self.invalid = (char)i;
break;
}
}
@@ -153,11 +153,11 @@ fn void! Base64Decoder.init(Base64Decoder* b, String alphabet, int padding = '='
* @return "The size of the input once decoded."
* @return! Base64Error.INVALID_PADDING
**/
fn usz! Base64Decoder.decode_len(Base64Decoder *b, usz n)
fn usz! Base64Decoder.decode_len(&self, usz n)
{
usz dn = n / 4 * 3;
usz trailing = n % 4;
if (b.padding >= 0)
if (self.padding >= 0)
{
if (trailing != 0) return Base64Error.INVALID_PADDING?;
// source size is multiple of 4
@@ -177,32 +177,32 @@ fn usz! Base64Decoder.decode_len(Base64Decoder *b, usz n)
* @return "The decoded size."
* @return! Base64Error.DESTINATION_TOO_SMALL, Base64Error.INVALID_PADDING, Base64Error.INVALID_CHARACTER
**/
fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
fn usz! Base64Decoder.decode(&self, char[] src, char[] dst)
{
if (src.len == 0) return 0;
usz dn = b.decode_len(src.len)!;
usz dn = self.decode_len(src.len)!;
if (dst.len < dn) return Base64Error.DESTINATION_TOO_SMALL?;
usz trailing = src.len % 4;
char[] src4 = src;
switch
{
case b.padding < 0:
case self.padding < 0:
src4 = src[:^trailing];
default:
// If there is padding, keep the last 4 bytes for later.
// NB. src.len >= 4 as decode_len passed
trailing = 4;
char pad = (char)b.padding;
char pad = (char)self.padding;
if (src[^1] == pad) src4 = src[:^4];
}
while (src4.len > 0)
{
char c0 = b.reverse[src4[0]];
char c1 = b.reverse[src4[1]];
char c2 = b.reverse[src4[2]];
char c3 = b.reverse[src4[3]];
switch (b.invalid)
char c0 = self.reverse[src4[0]];
char c1 = self.reverse[src4[1]];
char c2 = self.reverse[src4[2]];
char c3 = self.reverse[src4[3]];
switch (self.invalid)
{
case c0:
case c1:
@@ -221,10 +221,10 @@ fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
if (trailing == 0) return dn;
src = src[^trailing:];
char c0 = b.reverse[src[0]];
char c1 = b.reverse[src[1]];
if (c0 == b.invalid || c1 == b.invalid) return Base64Error.INVALID_PADDING?;
if (b.padding < 0)
char c0 = self.reverse[src[0]];
char c1 = self.reverse[src[1]];
if (c0 == self.invalid || c1 == self.invalid) return Base64Error.INVALID_PADDING?;
if (self.padding < 0)
{
switch (src.len)
{
@@ -232,8 +232,8 @@ fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
uint group = (uint)c0 << 18 | (uint)c1 << 12;
dst[0] = (char)(group >> 16);
case 3:
char c2 = b.reverse[src[2]];
if (c2 == b.invalid) return Base64Error.INVALID_CHARACTER?;
char c2 = self.reverse[src[2]];
if (c2 == self.invalid) return Base64Error.INVALID_CHARACTER?;
uint group = (uint)c0 << 18 | (uint)c1 << 12 | (uint)c2 << 6;
dst[0] = (char)(group >> 16);
dst[1] = (char)(group >> 8);
@@ -244,7 +244,7 @@ fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
// Valid paddings are:
// 2: xx==
// 1: xxx=
char pad = (char)b.padding;
char pad = (char)self.padding;
switch (pad)
{
case src[2]:
@@ -253,8 +253,8 @@ fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
dst[0] = (char)(group >> 16);
dn -= 2;
case src[3]:
char c2 = b.reverse[src[2]];
if (c2 == b.invalid) return Base64Error.INVALID_CHARACTER?;
char c2 = self.reverse[src[2]];
if (c2 == self.invalid) return Base64Error.INVALID_CHARACTER?;
uint group = (uint)c0 << 18 | (uint)c1 << 12 | (uint)c2 << 6;
dst[0] = (char)(group >> 16);
dst[1] = (char)(group >> 8);
@@ -266,7 +266,7 @@ fn usz! Base64Decoder.decode(Base64Decoder *b, char[] src, char[] dst)
// Make sure that all bytes in the alphabet are unique and
// the padding is not present in the alphabet.
fn void! check_alphabet(String alphabet, int padding)
fn void! check_alphabet(String alphabet, int padding) @local
{
bool[256] checked;
if (padding < 0)

View File

@@ -7,43 +7,43 @@ struct CsvReader
String separator;
}
fn void CsvReader.init_file(CsvReader* csv, File* file, String separator = ",")
fn void CsvReader.init_file(&self, File* file, String separator = ",")
{
csv.stream = file.as_stream();
csv.separator = separator;
self.stream = file.as_stream();
self.separator = separator;
}
fn void CsvReader.init(CsvReader* csv, Stream stream, String separator = ",")
fn void CsvReader.init(&self, Stream stream, String separator = ",")
{
csv.stream = stream;
csv.separator = separator;
self.stream = stream;
self.separator = separator;
}
fn String[]! CsvReader.read_row(CsvReader csv, Allocator* using = mem::heap())
fn String[]! CsvReader.read_row(self, Allocator* using = mem::heap())
{
@stack_mem(512; Allocator* mem)
{
return csv.stream.readline(mem).split(csv.separator, .using = using);
return self.stream.readline(mem).split(self.separator, .using = using);
};
}
fn String[]! CsvReader.tread_row(CsvReader csv)
fn String[]! CsvReader.tread_row(self)
{
return csv.read_row(mem::temp()) @inline;
return self.read_row(mem::temp()) @inline;
}
fn void! CsvReader.skip_row(CsvReader csv) @maydiscard
fn void! CsvReader.skip_row(self) @maydiscard
{
@pool()
{
csv.stream.readline(mem::temp())!;
self.stream.readline(mem::temp())!;
};
}
macro CsvReader.@each_row(CsvReader csv, int rows = int.max; @body(String[] row))
macro CsvReader.@each_row(self, int rows = int.max; @body(String[] row))
{
Stream stream = csv.stream;
String sep = csv.separator;
Stream stream = self.stream;
String sep = self.separator;
while (rows--)
{
@stack_mem(512; Allocator* mem)

View File

@@ -46,24 +46,24 @@ fault JsonParsingError
INVALID_NUMBER,
}
fn void JsonParser.init(JsonParser* parser, Stream s, Allocator* using = mem::heap())
fn void JsonParser.init(&self, Stream s, Allocator* using = mem::heap())
{
*parser = { .last_string = dstring::new_with_capacity(64, using), .stream = s, .allocator = using };
*self = { .last_string = dstring::new_with_capacity(64, using), .stream = s, .allocator = using };
}
fn Object*! JsonParser.parse_from_token(JsonParser* this, JsonTokenType token)
fn Object*! JsonParser.parse_from_token(&self, JsonTokenType token)
{
switch (token)
{
case NO_TOKEN: unreachable();
case LBRACE: return this.parse_map();
case LBRACKET: return this.parse_array();
case LBRACE: return self.parse_map();
case LBRACKET: return self.parse_array();
case COMMA:
case RBRACE:
case RBRACKET:
case COLON: return JsonParsingError.UNEXPECTED_CHARACTER?;
case STRING: return object::new_string(this.last_string.str(), this.allocator);
case NUMBER: return object::new_float(this.last_number, this.allocator);
case STRING: return object::new_string(self.last_string.str(), self.allocator);
case NUMBER: return object::new_float(self.last_number, self.allocator);
case TRUE: return object::new_bool(true);
case FALSE: return object::new_bool(false);
case NULL: return object::new_null();
@@ -71,12 +71,12 @@ fn Object*! JsonParser.parse_from_token(JsonParser* this, JsonTokenType token)
}
unreachable();
}
fn Object*! JsonParser.parse_any(JsonParser* this)
fn Object*! JsonParser.parse_any(&self)
{
return this.parse_from_token(this.advance());
return self.parse_from_token(self.advance());
}
fn JsonTokenType! JsonParser.lex_number(JsonParser* this, char c)
fn JsonTokenType! JsonParser.lex_number(&self, char c)
{
@pool()
{
@@ -85,17 +85,17 @@ fn JsonTokenType! JsonParser.lex_number(JsonParser* this, char c)
if (negate)
{
t.append(c);
c = this.read_next()!;
c = self.read_next()!;
}
while (c >= '0' && c <= '9')
{
t.append(c);
c = this.read_next()!;
c = self.read_next()!;
}
if (c == '.')
{
t.append(c);
while (c = this.read_next()!, c >= '0' && c <= '9')
while (c = self.read_next()!, c >= '0' && c <= '9')
{
t.append(c);
}
@@ -103,52 +103,52 @@ fn JsonTokenType! JsonParser.lex_number(JsonParser* this, char c)
if ((c | 32) == 'e')
{
t.append(c);
c = this.read_next()!;
c = self.read_next()!;
switch (c)
{
case '-':
case '+':
t.append(c);
c = this.read_next()!;
c = self.read_next()!;
}
if (c < '0' || c > '9') return JsonParsingError.INVALID_NUMBER?;
while (c >= '0' && c <= '9')
{
t.append(c);
c = this.read_next()!;
c = self.read_next()!;
}
}
this.pushback();
self.pushback();
double! d = t.str().to_double() ?? JsonParsingError.INVALID_NUMBER?;
this.last_number = d!;
self.last_number = d!;
return NUMBER;
};
}
fn Object*! JsonParser.parse_map(JsonParser* this)
fn Object*! JsonParser.parse_map(&self)
{
Object* map = object::new_obj(this.allocator);
JsonTokenType token = this.advance()!;
Object* map = object::new_obj(self.allocator);
JsonTokenType token = self.advance()!;
defer catch map.free();
DString temp_key = dstring::new_with_capacity(32, this.allocator);
DString temp_key = dstring::new_with_capacity(32, self.allocator);
defer temp_key.free();
while (token != JsonTokenType.RBRACE)
{
if (token != JsonTokenType.STRING) return JsonParsingError.UNEXPECTED_CHARACTER?;
DString string = this.last_string;
DString string = self.last_string;
if (map.has_key(string.str())) return JsonParsingError.DUPLICATE_MEMBERS?;
// Copy the key to our temp holder. We do this to work around the issue
// if the temp allocator should be used as the default allocator.
temp_key.clear();
temp_key.append(string);
this.parse_expected(COLON)!;
Object* element = this.parse_any()!;
self.parse_expected(COLON)!;
Object* element = self.parse_any()!;
map.set(temp_key.str(), element);
token = this.advance()!;
token = self.advance()!;
if (token == JsonTokenType.COMMA)
{
token = this.advance()!;
token = self.advance()!;
continue;
}
if (token != JsonTokenType.RBRACE) return JsonParsingError.UNEXPECTED_CHARACTER?;
@@ -156,19 +156,19 @@ fn Object*! JsonParser.parse_map(JsonParser* this)
return map;
}
fn Object*! JsonParser.parse_array(JsonParser* this)
fn Object*! JsonParser.parse_array(&self)
{
Object* list = object::new_obj(this.allocator);
Object* list = object::new_obj(self.allocator);
defer catch list.free();
JsonTokenType token = this.advance()!;
JsonTokenType token = self.advance()!;
while (token != JsonTokenType.RBRACKET)
{
Object* element = this.parse_from_token(token)!;
Object* element = self.parse_from_token(token)!;
list.append(element);
token = this.advance()!;
token = self.advance()!;
if (token == JsonTokenType.COMMA)
{
token = this.advance()!;
token = self.advance()!;
continue;
}
if (token != JsonTokenType.RBRACKET) return JsonParsingError.UNEXPECTED_CHARACTER?;
@@ -176,40 +176,40 @@ fn Object*! JsonParser.parse_array(JsonParser* this)
return list;
}
fn void JsonParser.pushback(JsonParser* this)
fn void JsonParser.pushback(&self)
{
if (!this.reached_end) this.stream.pushback_byte()!!;
if (!self.reached_end) self.stream.pushback_byte()!!;
}
fn char! JsonParser.read_next(JsonParser* this)
fn char! JsonParser.read_next(&self)
{
if (this.reached_end) return '\0';
char! c = this.stream.read_byte();
if (self.reached_end) return '\0';
char! c = self.stream.read_byte();
if (catch err = c)
{
case IoError.EOF:
this.reached_end = true;
self.reached_end = true;
return '\0';
default:
return err?;
}
if (c == 0)
{
this.reached_end = true;
self.reached_end = true;
}
return c;
}
fn JsonTokenType! JsonParser.advance(JsonParser* this)
fn JsonTokenType! JsonParser.advance(&self)
{
char c;
// Skip whitespace
while WS: (c = this.read_next()!)
while WS: (c = self.read_next()!)
{
switch (c)
{
case '\n':
this.line++;
self.line++;
nextcase;
case ' ':
case '\t':
@@ -217,24 +217,24 @@ fn JsonTokenType! JsonParser.advance(JsonParser* this)
case '\v':
continue;
case '/':
if (!this.skip_comments) break;
c = this.read_next()!;
if (!self.skip_comments) break;
c = self.read_next()!;
if (c != '*')
{
this.pushback();
self.pushback();
break WS;
}
while COMMENT: (1)
{
// Skip to */
while (c = this.read_next()!)
while (c = self.read_next()!)
{
if (c == '\n') this.line++;
if (c == '\n') self.line++;
if (c != '*') continue;
// Skip through all the '*'
while (c = this.read_next()!)
while (c = self.read_next()!)
{
if (c == '\n') this.line++;
if (c == '\n') self.line++;
if (c != '*') break;
}
if (c == '/') break COMMENT;
@@ -262,44 +262,44 @@ fn JsonTokenType! JsonParser.advance(JsonParser* this)
case ',':
return COMMA;
case '"':
return this.lex_string();
return self.lex_string();
case '-':
case '0'..'9':
return this.lex_number(c);
return self.lex_number(c);
case 't':
this.match("rue")!;
self.match("rue")!;
return TRUE;
case 'f':
this.match("alse")!;
self.match("alse")!;
return FALSE;
case 'n':
this.match("ull")!;
self.match("ull")!;
return NULL;
default:
return JsonParsingError.UNEXPECTED_CHARACTER?;
}
}
fn void! JsonParser.match(JsonParser* this, String str)
fn void! JsonParser.match(&self, String str)
{
foreach (c : str)
{
char l = this.read_next()!;
char l = self.read_next()!;
if (l != c) return JsonParsingError.UNEXPECTED_CHARACTER?;
}
}
fn void! JsonParser.parse_expected(JsonParser* this, JsonTokenType token) @local
fn void! JsonParser.parse_expected(&self, JsonTokenType token) @local
{
if (this.advance()! != token) return JsonParsingError.UNEXPECTED_CHARACTER?;
if (self.advance()! != token) return JsonParsingError.UNEXPECTED_CHARACTER?;
}
fn JsonTokenType! JsonParser.lex_string(JsonParser *this)
fn JsonTokenType! JsonParser.lex_string(&self)
{
this.last_string.clear();
self.last_string.clear();
while LOOP: (1)
{
char c = this.read_next()!;
char c = self.read_next()!;
switch (c)
{
case '\0':
@@ -311,10 +311,10 @@ fn JsonTokenType! JsonParser.lex_string(JsonParser *this)
case '\\':
break;
default:
this.last_string.append(c);
self.last_string.append(c);
continue;
}
c = this.read_next()!;
c = self.read_next()!;
switch (c)
{
case '\0':
@@ -339,11 +339,11 @@ fn JsonTokenType! JsonParser.lex_string(JsonParser *this)
uint val;
for (int i = 0; i < 4; i++)
{
c = this.read_next()!;
c = self.read_next()!;
if (!c.is_xdigit()) return JsonParsingError.INVALID_ESCAPE_SEQUENCE?;
val = val << 4 + (c > '9' ? (c | 32) - 'a' + 10 : c - '0');
}
this.last_string.append_char32(val);
self.last_string.append_char32(val);
continue;
default:
return JsonParsingError.INVALID_ESCAPE_SEQUENCE?;

View File

@@ -12,32 +12,32 @@ struct Adler32
uint b;
}
fn void Adler32.init(Adler32 *this)
fn void Adler32.init(&self)
{
*this = { 1, 0 };
*self = { 1, 0 };
}
fn void Adler32.updatec(Adler32* this, char c)
fn void Adler32.updatec(&self, char c)
{
this.a = (this.a + c) % ADLER_CONST;
this.b = (this.b + this.a) % ADLER_CONST;
self.a = (self.a + c) % ADLER_CONST;
self.b = (self.b + self.a) % ADLER_CONST;
}
fn void Adler32.update(Adler32* this, char[] data)
fn void Adler32.update(&self, char[] data)
{
uint a = this.a;
uint b = this.b;
uint a = self.a;
uint b = self.b;
foreach (char x : data)
{
a = (a + x) % ADLER_CONST;
b = (b + a) % ADLER_CONST;
}
*this = { a, b };
*self = { a, b };
}
fn uint Adler32.final(Adler32* this)
fn uint Adler32.final(&self)
{
return (this.b << 16) | this.a;
return (self.b << 16) | self.a;
}
fn uint encode(char[] data)

View File

@@ -1104,7 +1104,7 @@ opt_distinct_inline
;
generic_parameters
: bit_expr
: additive_expr
| type
| generic_parameters ',' bit_expr
| generic_parameters ',' type