mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
0.5.4: Hash variables accept designated initializers. @safemacro overrides the need for @ in macro names. Fixes to macro context evaluation. Updated allocator api. Removed install_win_reqs.bat. Deterministic @init for MacOS. Fixed temp memory issue with formatter. Support LLVM 19. Add support to compare bitstructs using == and !=. Support Windows .def files. Removed invalid grammar from grammar.y. Support compile time folding of &|^~ for bitstructs. output project setting now respected. Fix issue where constants were not properly constant folded. Add temp_push/pop. Aliased declarations caused errors when used in initializers. Fix export output. Fix of const ternary #1118. Fix of $$MODULE in nested macros #1117. Fix debug info on globals. out now correctly detects subscript[] use #1116. Lateral implicit imports removed. Default to '.' if no libdir is specified. Improved error messages for --lib. Fix raylib snake example. Overzealous local escape check corrected #1127. Improved yacc grammar #1128. --linker argument #1067. Fixes to the matrix operations #1130. Added GenericList.
This commit is contained in:
committed by
Christoffer Lerno
parent
c673101bbb
commit
748c737e8f
@@ -86,7 +86,7 @@ struct GrowableBitSet
|
||||
* @param initial_capacity
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap())
|
||||
fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
self.data.new_init(initial_capacity, allocator);
|
||||
return self;
|
||||
@@ -96,14 +96,14 @@ fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allo
|
||||
* @param initial_capacity
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init")
|
||||
fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init")
|
||||
{
|
||||
return self.new_init(initial_capacity, allocator) @inline;
|
||||
}
|
||||
|
||||
fn GrowableBitSet* GrowableBitSet.temp_init(&self, usz initial_capacity = 1)
|
||||
{
|
||||
return self.new_init(initial_capacity, mem::temp()) @inline;
|
||||
return self.new_init(initial_capacity, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn GrowableBitSet* GrowableBitSet.init_temp(&self, usz initial_capacity = 1) @deprecated("Replaced by temp_init")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module std::collections::enummap(<Enum, ValueType>);
|
||||
|
||||
import std::io;
|
||||
struct EnumMap (Printable)
|
||||
{
|
||||
ValueType[Enum.len] values;
|
||||
@@ -25,7 +25,7 @@ fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic
|
||||
return n;
|
||||
}
|
||||
|
||||
fn String EnumMap.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String EnumMap.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("%s", *self, .allocator = allocator);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Copyright (c) 2021-2024 Christoffer Lerno. All rights reserved.
|
||||
// Use of self source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
* @require Enum.kindof == TypeKind.ENUM : "Only enums maybe be used with an enumset"
|
||||
**/
|
||||
module std::collections::enumset(<Enum>);
|
||||
import std::io;
|
||||
|
||||
def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private ;
|
||||
def EnumSetType = $typefrom(private::type_for_enum_elements(Enum.elements)) @private;
|
||||
|
||||
const IS_CHAR_ARRAY = Enum.elements > 128;
|
||||
distinct EnumSet (Printable) = EnumSetType;
|
||||
@@ -140,7 +141,7 @@ fn usz! EnumSet.to_format(&set, Formatter* formatter) @dynamic
|
||||
return n;
|
||||
}
|
||||
|
||||
fn String EnumSet.to_new_string(&set, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String EnumSet.to_new_string(&set, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("%s", *set, .allocator = allocator);
|
||||
}
|
||||
|
||||
467
lib/std/collections/generic_list.c3
Normal file
467
lib/std/collections/generic_list.c3
Normal file
@@ -0,0 +1,467 @@
|
||||
// Copyright (c) 2024 Christoffer Lerno. All rights reserved.
|
||||
// Use of self source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::collections::generic_list;
|
||||
import std::io,std::math;
|
||||
|
||||
def GenericPredicate = fn bool(any* value);
|
||||
def GenericTest = fn bool(any* type, any* context);
|
||||
|
||||
struct GenericList (Printable)
|
||||
{
|
||||
usz size;
|
||||
usz capacity;
|
||||
Allocator* allocator;
|
||||
any** entries;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param initial_capacity "The initial capacity to reserve"
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn GenericList* GenericList.new_init(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
self.allocator = allocator;
|
||||
self.size = 0;
|
||||
if (initial_capacity > 0)
|
||||
{
|
||||
initial_capacity = math::next_power_of_2(initial_capacity);
|
||||
self.entries = allocator::alloc_array(allocator, any*, initial_capacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
self.entries = null;
|
||||
}
|
||||
self.capacity = initial_capacity;
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param initial_capacity "The initial capacity to reserve"
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn GenericList* GenericList.init_new(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init")
|
||||
{
|
||||
return self.new_init(initial_capacity, allocator) @inline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the list using the temp allocator.
|
||||
*
|
||||
* @param initial_capacity "The initial capacity to reserve"
|
||||
**/
|
||||
fn GenericList* GenericList.temp_init(&self, usz initial_capacity = 16)
|
||||
{
|
||||
return self.new_init(initial_capacity, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn usz! GenericList.to_format(&self, Formatter* formatter) @dynamic
|
||||
{
|
||||
switch (self.size)
|
||||
{
|
||||
case 0:
|
||||
return formatter.print("[]")!;
|
||||
case 1:
|
||||
return formatter.printf("[%s]", self.entries[0])!;
|
||||
default:
|
||||
usz n = formatter.print("[")!;
|
||||
foreach (i, element : self.entries[:self.size])
|
||||
{
|
||||
if (i != 0) formatter.print(", ")!;
|
||||
n += formatter.printf("%s", element)!;
|
||||
}
|
||||
n += formatter.print("]")!;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
fn String GenericList.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("%s", *self, .allocator = allocator);
|
||||
}
|
||||
|
||||
fn String GenericList.to_tstring(&self)
|
||||
{
|
||||
return string::tformat("%s", *self);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an element on the list by cloning it.
|
||||
**/
|
||||
macro void GenericList.push(&self, element)
|
||||
{
|
||||
if (!self.allocator) self.allocator = allocator::heap();
|
||||
self.append_internal(allocator::clone(self.allocator, element));
|
||||
}
|
||||
|
||||
fn void GenericList.append_internal(&self, any* element) @local
|
||||
{
|
||||
self.ensure_capacity();
|
||||
self.entries[self.size++] = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free a retained element removed using *_retained.
|
||||
**/
|
||||
fn void GenericList.free_element(&self, any* element) @inline
|
||||
{
|
||||
allocator::free(self.allocator, element.ptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop a value who's type is known. If the type is incorrect, this
|
||||
* will still pop the element.
|
||||
*
|
||||
* @return! CastResult.TYPE_MISMATCH, IteratorResult.NO_MORE_ELEMENT
|
||||
**/
|
||||
macro GenericList.pop(&self, $Type)
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
defer self.free_element(self.entries[self.size]);
|
||||
return *anycast(self.entries[--self.size], $Type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the last value and allocate the copy using the given allocator.
|
||||
* @return! IteratorResult.NO_MORE_ELEMENT
|
||||
**/
|
||||
fn any*! GenericList.new_pop(&self, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
defer self.free_element(self.entries[self.size]);
|
||||
return allocator::clone_any(allocator, self.entries[--self.size]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the last value and allocate the copy using the temp allocator
|
||||
* @return! IteratorResult.NO_MORE_ELEMENT
|
||||
**/
|
||||
fn any*! GenericList.temp_pop(&self) => self.new_pop(allocator::temp());
|
||||
|
||||
/**
|
||||
* Pop the last value. It must later be released using list.free_element()
|
||||
* @return! IteratorResult.NO_MORE_ELEMENT
|
||||
**/
|
||||
fn any*! GenericList.pop_retained(&self)
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
return self.entries[--self.size];
|
||||
}
|
||||
|
||||
fn void GenericList.clear(&self)
|
||||
{
|
||||
for (usz i = 0; i < self.size; i++)
|
||||
{
|
||||
self.free_element(self.entries[i]);
|
||||
}
|
||||
self.size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as pop() but pops the first value instead.
|
||||
**/
|
||||
macro GenericList.pop_first(&self, $Type)
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
defer self.remove_at(0);
|
||||
return *anycast(self.entries[0], $Type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as pop_retained() but pops the first value instead.
|
||||
**/
|
||||
fn any*! GenericList.pop_first_retained(&self)
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
defer self.remove_at(0);
|
||||
return self.entries[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as new_pop() but pops the first value instead.
|
||||
**/
|
||||
fn any*! GenericList.new_pop_first(&self, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
if (!self.size) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
defer self.free_element(self.entries[self.size]);
|
||||
defer self.remove_at(0);
|
||||
return allocator::clone_any(allocator, self.entries[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as temp_pop() but pops the first value instead.
|
||||
**/
|
||||
fn any*! GenericList.temp_pop_first(&self) => self.new_pop_first(allocator::temp());
|
||||
|
||||
/**
|
||||
* @require index < self.size
|
||||
**/
|
||||
fn void GenericList.remove_at(&self, usz index)
|
||||
{
|
||||
if (!--self.size || index == self.size) return;
|
||||
self.free_element(self.entries[index]);
|
||||
self.entries[index .. self.size - 1] = self.entries[index + 1 .. self.size];
|
||||
}
|
||||
|
||||
fn void GenericList.add_all(&self, GenericList* other_list)
|
||||
{
|
||||
if (!other_list.size) return;
|
||||
self.reserve(other_list.size);
|
||||
foreach (value : other_list)
|
||||
{
|
||||
self.entries[self.size++] = allocator::clone_any(self.allocator, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the elements in a list.
|
||||
**/
|
||||
fn void GenericList.reverse(&self)
|
||||
{
|
||||
if (self.size < 2) return;
|
||||
usz half = self.size / 2U;
|
||||
usz end = self.size - 1;
|
||||
for (usz i = 0; i < half; i++)
|
||||
{
|
||||
self.swap(i, end - i);
|
||||
}
|
||||
}
|
||||
|
||||
fn any*[] GenericList.array_view(&self)
|
||||
{
|
||||
return self.entries[:self.size];
|
||||
}
|
||||
|
||||
/**
|
||||
* Push an element to the front of the list.
|
||||
**/
|
||||
macro void GenericList.push_front(&self, type)
|
||||
{
|
||||
self.insert_at(0, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index < self.size
|
||||
**/
|
||||
macro void GenericList.insert_at(&self, usz index, type) @local
|
||||
{
|
||||
any* value = allocator::copy(self.allocator, type);
|
||||
self.insert_at_internal(self, index, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index < self.size
|
||||
**/
|
||||
fn void GenericList.insert_at_internal(&self, usz index, any* value) @local
|
||||
{
|
||||
self.ensure_capacity();
|
||||
for (usz i = self.size; i > index; i--)
|
||||
{
|
||||
self.entries[i] = self.entries[i - 1];
|
||||
}
|
||||
self.size++;
|
||||
self.entries[index] = value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @require self.size > 0
|
||||
**/
|
||||
fn void GenericList.remove_last(&self)
|
||||
{
|
||||
self.free_element(self.entries[--self.size]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require self.size > 0
|
||||
**/
|
||||
fn void GenericList.remove_first(&self)
|
||||
{
|
||||
self.remove_at(0);
|
||||
}
|
||||
|
||||
macro GenericList.first(&self, $Type)
|
||||
{
|
||||
return *anycast(self.first_any(), $Type);
|
||||
}
|
||||
|
||||
fn any*! GenericList.first_any(&self) @inline
|
||||
{
|
||||
return self.size ? self.entries[0] : IteratorResult.NO_MORE_ELEMENT?;
|
||||
}
|
||||
|
||||
macro GenericList.last(&self, $Type)
|
||||
{
|
||||
return *anycast(self.last_any(), $Type);
|
||||
}
|
||||
|
||||
fn any*! GenericList.last_any(&self) @inline
|
||||
{
|
||||
return self.size ? self.entries[self.size - 1] : IteratorResult.NO_MORE_ELEMENT?;
|
||||
}
|
||||
|
||||
fn bool GenericList.is_empty(&self) @inline
|
||||
{
|
||||
return !self.size;
|
||||
}
|
||||
|
||||
fn usz GenericList.len(&self) @operator(len) @inline
|
||||
{
|
||||
return self.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index < self.size "Index out of range"
|
||||
**/
|
||||
macro GenericList.get(&self, usz index, $Type)
|
||||
{
|
||||
return *anycast(self.entries[index], $Type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index < self.size "Index out of range"
|
||||
**/
|
||||
fn any* GenericList.get_any(&self, usz index) @inline
|
||||
{
|
||||
return self.entries[index];
|
||||
}
|
||||
|
||||
fn void GenericList.free(&self)
|
||||
{
|
||||
if (!self.allocator) return;
|
||||
self.clear();
|
||||
allocator::free(self.allocator, self.entries);
|
||||
self.capacity = 0;
|
||||
self.entries = null;
|
||||
}
|
||||
|
||||
fn void GenericList.swap(&self, usz i, usz j)
|
||||
{
|
||||
any* temp = self.entries[i];
|
||||
self.entries[i] = self.entries[j];
|
||||
self.entries[j] = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param filter "The function to determine if it should be removed or not"
|
||||
* @return "the number of deleted elements"
|
||||
**/
|
||||
fn usz GenericList.remove_if(&self, GenericPredicate filter)
|
||||
{
|
||||
return self._remove_if(filter, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selection "The function to determine if it should be kept or not"
|
||||
* @return "the number of deleted elements"
|
||||
**/
|
||||
fn usz GenericList.retain_if(&self, GenericPredicate selection)
|
||||
{
|
||||
return self._remove_if(selection, true);
|
||||
}
|
||||
|
||||
macro usz GenericList._remove_if(&self, GenericPredicate filter, bool $invert) @local
|
||||
{
|
||||
usz size = self.size;
|
||||
for (usz i = size, usz k = size; k > 0; k = i)
|
||||
{
|
||||
// Find last index of item to be deleted.
|
||||
$if $invert:
|
||||
while (i > 0 && !filter(&self.entries[i - 1])) i--;
|
||||
$else
|
||||
while (i > 0 && filter(&self.entries[i - 1])) i--;
|
||||
$endif
|
||||
// Remove the items from this index up to the one not to be deleted.
|
||||
usz n = self.size - k;
|
||||
for (usz j = i; j < k; j++) self.free_element(self.entries[j]);
|
||||
self.entries[i:n] = self.entries[k:n];
|
||||
self.size -= k - i;
|
||||
// Find last index of item not to be deleted.
|
||||
$if $invert:
|
||||
while (i > 0 && filter(&self.entries[i - 1])) i--;
|
||||
$else
|
||||
while (i > 0 && !filter(&self.entries[i - 1])) i--;
|
||||
$endif
|
||||
}
|
||||
return size - self.size;
|
||||
}
|
||||
|
||||
fn usz GenericList.remove_using_test(&self, GenericTest filter, any* context)
|
||||
{
|
||||
return self._remove_using_test(filter, false, context);
|
||||
}
|
||||
|
||||
fn usz GenericList.retain_using_test(&self, GenericTest filter, any* context)
|
||||
{
|
||||
return self._remove_using_test(filter, true, context);
|
||||
}
|
||||
|
||||
macro usz GenericList._remove_using_test(&self, GenericTest filter, bool $invert, ctx) @local
|
||||
{
|
||||
usz size = self.size;
|
||||
for (usz i = size, usz k = size; k > 0; k = i)
|
||||
{
|
||||
// Find last index of item to be deleted.
|
||||
$if $invert:
|
||||
while (i > 0 && !filter(&self.entries[i - 1], ctx)) i--;
|
||||
$else
|
||||
while (i > 0 && filter(&self.entries[i - 1], ctx)) i--;
|
||||
$endif
|
||||
// Remove the items from this index up to the one not to be deleted.
|
||||
usz n = self.size - k;
|
||||
for (usz j = i; j < k; j++) self.free_element(self.entries[j]);
|
||||
self.entries[i:n] = self.entries[k:n];
|
||||
self.size -= k - i;
|
||||
// Find last index of item not to be deleted.
|
||||
$if $invert:
|
||||
while (i > 0 && filter(&self.entries[i - 1], ctx)) i--;
|
||||
$else
|
||||
while (i > 0 && !filter(&self.entries[i - 1], ctx)) i--;
|
||||
$endif
|
||||
}
|
||||
return size - self.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve at least min_capacity
|
||||
**/
|
||||
fn void GenericList.reserve(&self, usz min_capacity)
|
||||
{
|
||||
if (!min_capacity) return;
|
||||
if (self.capacity >= min_capacity) return;
|
||||
if (!self.allocator) self.allocator = allocator::heap();
|
||||
min_capacity = math::next_power_of_2(min_capacity);
|
||||
self.entries = allocator::realloc(self.allocator, self.entries, any*.sizeof * min_capacity);
|
||||
self.capacity = min_capacity;
|
||||
}
|
||||
|
||||
macro any* GenericList.@item_at(&self, usz index) @operator([])
|
||||
{
|
||||
return self.entries[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* @require index <= self.size "Index out of range"
|
||||
**/
|
||||
macro void GenericList.set(&self, usz index, value)
|
||||
{
|
||||
if (index == self.size)
|
||||
{
|
||||
self.push(value);
|
||||
return;
|
||||
}
|
||||
self.free_element(self.entries[index]);
|
||||
self.entries[index] = allocator::copy(self.allocator, value);
|
||||
}
|
||||
|
||||
fn void GenericList.ensure_capacity(&self, usz added = 1) @inline @private
|
||||
{
|
||||
usz new_size = self.size + added;
|
||||
if (self.capacity >= new_size) return;
|
||||
|
||||
assert(new_size < usz.max / 2U);
|
||||
usz new_capacity = self.capacity ? 2U * self.capacity : 16U;
|
||||
while (new_capacity < new_size) new_capacity *= 2U;
|
||||
self.reserve(new_capacity);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Copyright (c) 2021-2024 Christoffer Lerno. All rights reserved.
|
||||
// Use of self source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::collections::linkedlist(<Type>);
|
||||
@@ -32,7 +32,7 @@ fn void LinkedList.push_last(&self, Type value)
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
* @return "the initialized list"
|
||||
**/
|
||||
fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = mem::heap())
|
||||
fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
*self = { .allocator = allocator };
|
||||
return self;
|
||||
@@ -42,14 +42,14 @@ fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = mem::heap())
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
* @return "the initialized list"
|
||||
**/
|
||||
fn LinkedList* LinkedList.init_new(&self, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init")
|
||||
fn LinkedList* LinkedList.init_new(&self, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init")
|
||||
{
|
||||
return self.new_init(allocator);
|
||||
}
|
||||
|
||||
fn LinkedList* LinkedList.temp_init(&self)
|
||||
{
|
||||
return self.new_init(mem::temp()) @inline;
|
||||
return self.new_init(allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn LinkedList* LinkedList.init_temp(&self) @deprecated("Replaced by temp_init")
|
||||
@@ -62,12 +62,13 @@ fn LinkedList* LinkedList.init_temp(&self) @deprecated("Replaced by temp_init")
|
||||
**/
|
||||
macro void LinkedList.free_node(&self, Node* node) @private
|
||||
{
|
||||
self.allocator.free(node);
|
||||
allocator::free(self.allocator, node);
|
||||
}
|
||||
|
||||
macro Node* LinkedList.alloc_node(&self) @private
|
||||
{
|
||||
if (!self.allocator) self.allocator = mem::heap();
|
||||
return self.allocator.new(Node);
|
||||
if (!self.allocator) self.allocator = allocator::heap();
|
||||
return allocator::alloc(self.allocator, Node);
|
||||
}
|
||||
|
||||
fn void LinkedList.link_first(&self, Type value) @private
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// Copyright (c) 2021 Christoffer Lerno. All rights reserved.
|
||||
// Copyright (c) 2021-2024 Christoffer Lerno. All rights reserved.
|
||||
// Use of self source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::collections::list(<Type>);
|
||||
import std::io;
|
||||
import std::math;
|
||||
import std::io,std::math;
|
||||
|
||||
def ElementPredicate = fn bool(Type *type);
|
||||
def ElementTest = fn bool(Type *type, any* context);
|
||||
@@ -23,14 +22,14 @@ struct List (Printable)
|
||||
* @param initial_capacity "The initial capacity to reserve"
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap())
|
||||
fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
self.allocator = allocator;
|
||||
self.size = 0;
|
||||
if (initial_capacity > 0)
|
||||
{
|
||||
initial_capacity = math::next_power_of_2(initial_capacity);
|
||||
self.entries = allocator.alloc_aligned(Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!;
|
||||
self.entries = allocator::malloc_aligned(allocator, Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -44,7 +43,7 @@ fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator =
|
||||
* @param initial_capacity "The initial capacity to reserve"
|
||||
* @param [&inout] allocator "The allocator to use, defaults to the heap allocator"
|
||||
**/
|
||||
fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init")
|
||||
fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init")
|
||||
{
|
||||
return self.new_init(initial_capacity, allocator) @inline;
|
||||
}
|
||||
@@ -56,7 +55,7 @@ fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator =
|
||||
**/
|
||||
fn List* List.temp_init(&self, usz initial_capacity = 16)
|
||||
{
|
||||
return self.new_init(initial_capacity, mem::temp()) @inline;
|
||||
return self.new_init(initial_capacity, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +71,7 @@ fn List* List.init_temp(&self, usz initial_capacity = 16) @deprecated("Replaced
|
||||
/**
|
||||
* @require self.size == 0 "The List must be empty"
|
||||
**/
|
||||
fn void List.init_wrapping_array(&self, Type[] types, Allocator* allocator = mem::heap())
|
||||
fn void List.init_wrapping_array(&self, Type[] types, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
self.allocator = allocator;
|
||||
self.size = types.len;
|
||||
@@ -100,7 +99,7 @@ fn usz! List.to_format(&self, Formatter* formatter) @dynamic
|
||||
}
|
||||
}
|
||||
|
||||
fn String List.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String List.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("%s", *self, .allocator = allocator);
|
||||
}
|
||||
@@ -164,17 +163,17 @@ fn void List.add_all(&self, List* other_list)
|
||||
}
|
||||
|
||||
|
||||
fn Type[] List.to_new_array(&self, Allocator* allocator = mem::heap())
|
||||
fn Type[] List.to_new_array(&self, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
if (!self.size) return Type[] {};
|
||||
Type[] result = allocator.new_array(Type, self.size);
|
||||
Type[] result = allocator::alloc_array(allocator, Type, self.size);
|
||||
result[..] = self.entries[:self.size];
|
||||
return result;
|
||||
}
|
||||
|
||||
fn Type[] List.to_tarray(&self)
|
||||
{
|
||||
return self.to_new_array(mem::temp());
|
||||
return self.to_new_array(allocator::temp());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +263,11 @@ fn bool List.is_empty(&self) @inline
|
||||
return !self.size;
|
||||
}
|
||||
|
||||
fn usz List.byte_size(&self) @inline
|
||||
{
|
||||
return Type.sizeof * self.size;
|
||||
}
|
||||
|
||||
fn usz List.len(&self) @operator(len) @inline
|
||||
{
|
||||
return self.size;
|
||||
@@ -277,7 +281,7 @@ fn Type List.get(&self, usz index) @inline
|
||||
fn void List.free(&self)
|
||||
{
|
||||
if (!self.allocator) return;
|
||||
self.allocator.free_aligned(self.entries);
|
||||
allocator::free_aligned(self.allocator, self.entries);
|
||||
self.capacity = 0;
|
||||
self.size = 0;
|
||||
self.entries = null;
|
||||
@@ -373,9 +377,9 @@ fn void List.reserve(&self, usz min_capacity)
|
||||
{
|
||||
if (!min_capacity) return;
|
||||
if (self.capacity >= min_capacity) return;
|
||||
if (!self.allocator) self.allocator = mem::heap();
|
||||
if (!self.allocator) self.allocator = allocator::heap();
|
||||
min_capacity = math::next_power_of_2(min_capacity);
|
||||
self.entries = self.allocator.realloc_aligned(self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof) ?? null;
|
||||
self.entries = allocator::realloc_aligned(self.allocator, self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof) ?? null;
|
||||
self.capacity = min_capacity;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,13 +26,13 @@ struct HashMap
|
||||
* @require !self.allocator "Map was already initialized"
|
||||
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
**/
|
||||
fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap())
|
||||
fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
capacity = math::next_power_of_2(capacity);
|
||||
self.allocator = allocator;
|
||||
self.load_factor = load_factor;
|
||||
self.threshold = (uint)(capacity * load_factor);
|
||||
self.table = allocator.new_zero_array(Entry*, capacity);
|
||||
self.table = allocator::new_array(allocator, Entry*, capacity);
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, fl
|
||||
* @require !map.allocator "Map was already initialized"
|
||||
* @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
|
||||
**/
|
||||
fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init")
|
||||
fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init")
|
||||
{
|
||||
return map.new_init(capacity, load_factor, allocator);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, flo
|
||||
**/
|
||||
fn HashMap* HashMap.temp_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
|
||||
{
|
||||
return self.new_init(capacity, load_factor, mem::temp()) @inline;
|
||||
return self.new_init(capacity, load_factor, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +85,7 @@ fn bool HashMap.is_initialized(&map)
|
||||
* @param [&inout] allocator "The allocator to use"
|
||||
* @param [&in] other_map "The map to copy from."
|
||||
**/
|
||||
fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap())
|
||||
fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
self.new_init(other_map.table.len, other_map.load_factor, allocator);
|
||||
self.put_all_for_create(other_map);
|
||||
@@ -96,7 +96,7 @@ fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allo
|
||||
* @param [&inout] allocator "The allocator to use"
|
||||
* @param [&in] other_map "The map to copy from."
|
||||
**/
|
||||
fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init_from_map")
|
||||
fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init_from_map")
|
||||
|
||||
{
|
||||
return self.new_init_from_map(other_map, allocator) @inline;
|
||||
@@ -107,7 +107,7 @@ fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allo
|
||||
**/
|
||||
fn HashMap* HashMap.temp_init_from_map(&map, HashMap* other_map)
|
||||
{
|
||||
return map.new_init_from_map(other_map, mem::temp()) @inline;
|
||||
return map.new_init_from_map(other_map, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,6 +153,7 @@ fn Entry*! HashMap.get_entry(&map, Key key)
|
||||
|
||||
/**
|
||||
* Get the value or update and
|
||||
* @require $assignable(#expr, Value)
|
||||
**/
|
||||
macro Value HashMap.@get_or_set(&map, Key key, Value #expr)
|
||||
{
|
||||
@@ -239,14 +240,14 @@ fn void HashMap.free(&map)
|
||||
|
||||
fn Key[] HashMap.key_tlist(&map)
|
||||
{
|
||||
return map.key_new_list(mem::temp()) @inline;
|
||||
return map.key_new_list(allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn Key[] HashMap.key_new_list(&map, Allocator* allocator = mem::heap())
|
||||
fn Key[] HashMap.key_new_list(&map, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
if (!map.count) return {};
|
||||
|
||||
Key[] list = allocator.new_array(Key, map.count);
|
||||
Key[] list = allocator::alloc_array(allocator, Key, map.count);
|
||||
usz index = 0;
|
||||
foreach (Entry* entry : map.table)
|
||||
{
|
||||
@@ -283,13 +284,13 @@ macro HashMap.@each_entry(map; @body(entry))
|
||||
|
||||
fn Value[] HashMap.value_tlist(&map)
|
||||
{
|
||||
return map.value_new_list(mem::temp()) @inline;
|
||||
return map.value_new_list(allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn Value[] HashMap.value_new_list(&map, Allocator* allocator = mem::heap())
|
||||
fn Value[] HashMap.value_new_list(&map, Allocator* allocator = allocator::heap())
|
||||
{
|
||||
if (!map.count) return {};
|
||||
Value[] list = allocator.new_array(Value, map.count);
|
||||
Value[] list = allocator::alloc_array(allocator, Value, map.count);
|
||||
usz index = 0;
|
||||
foreach (Entry* entry : map.table)
|
||||
{
|
||||
@@ -320,11 +321,10 @@ fn bool HashMap.has_value(&map, Value v) @if(VALUE_IS_EQUATABLE)
|
||||
|
||||
fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private
|
||||
{
|
||||
Entry* entry = map.allocator.new(Entry);
|
||||
$if COPY_KEYS:
|
||||
key = key.copy(map.allocator);
|
||||
$endif
|
||||
*entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] };
|
||||
Entry* entry = allocator::new(map.allocator, Entry, { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] });
|
||||
map.table[bucket_index] = entry;
|
||||
if (map.count++ >= map.threshold)
|
||||
{
|
||||
@@ -341,7 +341,7 @@ fn void HashMap.resize(&map, uint new_capacity) @private
|
||||
map.threshold = uint.max;
|
||||
return;
|
||||
}
|
||||
Entry*[] new_table = map.allocator.new_zero_array(Entry*, new_capacity);
|
||||
Entry*[] new_table = allocator::new_array(map.allocator, Entry*, new_capacity);
|
||||
map.transfer(new_table);
|
||||
map.table = new_table;
|
||||
map.free_internal(old_table.ptr);
|
||||
@@ -405,7 +405,7 @@ fn void HashMap.put_for_create(&map, Key key, Value value) @private
|
||||
|
||||
fn void HashMap.free_internal(&map, void* ptr) @inline @private
|
||||
{
|
||||
map.allocator.free(ptr);
|
||||
allocator::free(map.allocator, ptr);
|
||||
}
|
||||
|
||||
fn bool HashMap.remove_entry_for_key(&map, Key key) @private
|
||||
@@ -440,11 +440,10 @@ fn bool HashMap.remove_entry_for_key(&map, Key key) @private
|
||||
fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private
|
||||
{
|
||||
Entry *e = map.table[bucket_index];
|
||||
Entry* entry = map.allocator.new(Entry);
|
||||
$if COPY_KEYS:
|
||||
key = key.copy(map.allocator);
|
||||
$endif
|
||||
*entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] };
|
||||
Entry* entry = allocator::new(map.allocator, Entry, { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] });
|
||||
map.table[bucket_index] = entry;
|
||||
map.count++;
|
||||
}
|
||||
@@ -452,7 +451,7 @@ fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_i
|
||||
fn void HashMap.free_entry(&self, Entry *entry) @local
|
||||
{
|
||||
$if COPY_KEYS:
|
||||
self.allocator.free(entry.key);
|
||||
allocator::free(self.allocator, entry.key);
|
||||
$endif
|
||||
self.free_internal(entry);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
// Use of this source code is governed by the MIT license
|
||||
// a copy of which can be found in the LICENSE_STDLIB file.
|
||||
module std::collections::object;
|
||||
import std::collections::map;
|
||||
import std::collections::list;
|
||||
import std::io;
|
||||
import std::collections::map, std::collections::list, std::io;
|
||||
|
||||
const Object TRUE_OBJECT = { .b = true, .type = bool.typeid };
|
||||
const Object FALSE_OBJECT = { .b = false, .type = bool.typeid };
|
||||
@@ -80,9 +78,7 @@ fn usz! Object.to_format(&self, Formatter* formatter) @dynamic
|
||||
|
||||
fn Object* new_obj(Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .allocator = allocator, .type = void.typeid };
|
||||
return o;
|
||||
return allocator::new(allocator, Object, { .allocator = allocator, .type = void.typeid });
|
||||
}
|
||||
|
||||
fn Object* new_null()
|
||||
@@ -92,30 +88,22 @@ fn Object* new_null()
|
||||
|
||||
fn Object* new_int(int128 i, Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .i = i, .allocator = allocator, .type = int128.typeid };
|
||||
return o;
|
||||
return allocator::new(allocator, Object, { .i = i, .allocator = allocator, .type = int128.typeid });
|
||||
}
|
||||
|
||||
macro Object* new_enum(e, Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .i = (int128)e, .allocator = allocator, .type = @typeid(e) };
|
||||
return o;
|
||||
return allocator::new(allocator, Object, { .i = (int128)e, .allocator = allocator, .type = @typeid(e) });
|
||||
}
|
||||
|
||||
fn Object* new_float(double f, Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .f = f, .allocator = allocator, .type = double.typeid };
|
||||
return o;
|
||||
return allocator::new(allocator, Object, { .f = f, .allocator = allocator, .type = double.typeid });
|
||||
}
|
||||
|
||||
fn Object* new_string(String s, Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .s = s.copy(allocator), .allocator = allocator, .type = String.typeid };
|
||||
return o;
|
||||
return allocator::new(allocator, Object, { .s = s.copy(allocator), .allocator = allocator, .type = String.typeid });
|
||||
}
|
||||
|
||||
|
||||
@@ -131,7 +119,7 @@ fn void Object.free(&self)
|
||||
case void:
|
||||
break;
|
||||
case String:
|
||||
self.allocator.free(self.s);
|
||||
allocator::free(self.allocator, self.s);
|
||||
case ObjectInternalList:
|
||||
foreach (ol : self.array)
|
||||
{
|
||||
@@ -140,13 +128,13 @@ fn void Object.free(&self)
|
||||
self.array.free();
|
||||
case ObjectInternalMap:
|
||||
self.map.@each_entry(; ObjectInternalMapEntry* entry) {
|
||||
self.allocator.free(entry.key);
|
||||
allocator::free(self.allocator, entry.key);
|
||||
entry.value.free();
|
||||
};
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (self.allocator) self.allocator.free(self);
|
||||
if (self.allocator) allocator::free(self.allocator, self);
|
||||
}
|
||||
|
||||
fn bool Object.is_null(&self) @inline => self == &NULL_OBJECT;
|
||||
@@ -193,7 +181,7 @@ fn void Object.set_object(&self, String key, Object* new_object) @private
|
||||
ObjectInternalMapEntry*! entry = self.map.get_entry(key);
|
||||
defer
|
||||
{
|
||||
(void)self.allocator.free(entry.key);
|
||||
(void)allocator::free(self.allocator, entry.key);
|
||||
(void)entry.value.free();
|
||||
}
|
||||
self.map.set(key.copy(self.map.allocator), new_object);
|
||||
|
||||
@@ -27,7 +27,7 @@ distinct PriorityQueue = inline PrivatePriorityQueue(<Type, false>);
|
||||
distinct PriorityQueueMax = inline PrivatePriorityQueue(<Type, true>);
|
||||
|
||||
module std::collections::priorityqueue::private(<Type, MAX>);
|
||||
import std::collections::list;
|
||||
import std::collections::list, std::io;
|
||||
|
||||
def Heap = List(<Type>);
|
||||
|
||||
@@ -36,19 +36,19 @@ struct PrivatePriorityQueue (Printable)
|
||||
Heap heap;
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline @deprecated("Replaced by new_init")
|
||||
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @inline @deprecated("Replaced by new_init")
|
||||
{
|
||||
return self.new_init(initial_capacity, allocator);
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.new_init(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline
|
||||
fn void PrivatePriorityQueue.new_init(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @inline
|
||||
{
|
||||
self.heap.new_init(initial_capacity, allocator);
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.temp_init(&self, usz initial_capacity = 16) @inline
|
||||
{
|
||||
self.heap.new_init(initial_capacity, mem::temp()) @inline;
|
||||
self.heap.new_init(initial_capacity, allocator::temp()) @inline;
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.init_temp(&self, usz initial_capacity = 16) @inline @deprecated("Replaced by temp_init")
|
||||
@@ -151,7 +151,7 @@ fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter) @dynamic
|
||||
return self.heap.to_format(formatter);
|
||||
}
|
||||
|
||||
fn String PrivatePriorityQueue.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String PrivatePriorityQueue.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return self.heap.to_new_string(allocator);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* @require Type.is_ordered : "The type must be ordered"
|
||||
**/
|
||||
module std::collections::range(<Type>);
|
||||
import std::io;
|
||||
|
||||
struct Range (Printable)
|
||||
{
|
||||
@@ -28,14 +29,14 @@ fn Type Range.get(&self, usz index) @operator([])
|
||||
return (Type)(self.start + (usz)index);
|
||||
}
|
||||
|
||||
fn String Range.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String Range.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("[%s..%s]", self.start, self.end, .allocator = allocator);
|
||||
}
|
||||
|
||||
fn String Range.to_tstring(&self)
|
||||
{
|
||||
return self.to_new_string(mem::temp());
|
||||
return self.to_new_string(allocator::temp());
|
||||
}
|
||||
|
||||
fn usz! Range.to_format(&self, Formatter* formatter) @dynamic
|
||||
@@ -65,14 +66,14 @@ fn usz! ExclusiveRange.to_format(&self, Formatter* formatter) @dynamic
|
||||
return formatter.printf("[%s..<%s]", self.start, self.end)!;
|
||||
}
|
||||
|
||||
fn String ExclusiveRange.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic
|
||||
fn String ExclusiveRange.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic
|
||||
{
|
||||
return string::new_format("[%s..<%s]", self.start, self.end, .allocator = allocator);
|
||||
}
|
||||
|
||||
fn String ExclusiveRange.to_tstring(&self)
|
||||
{
|
||||
return self.to_new_string(mem::temp());
|
||||
return self.to_new_string(allocator::temp());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user