mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 = {};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1104,7 +1104,7 @@ opt_distinct_inline
|
||||
;
|
||||
|
||||
generic_parameters
|
||||
: bit_expr
|
||||
: additive_expr
|
||||
| type
|
||||
| generic_parameters ',' bit_expr
|
||||
| generic_parameters ',' type
|
||||
|
||||
Reference in New Issue
Block a user