Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use the construct operator to replace new_init() in the stdlib #1860

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 118 additions & 30 deletions lib/std/collections/hashmap.c3
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,35 @@ struct HashMap
float load_factor;
}

<*
@param [&inout] allocator "The allocator to use"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
fn HashMap HashMap.new(uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap()) @operator(construct)
{
HashMap new;
capacity = math::next_power_of_2(capacity);
new.allocator = allocator;
new.load_factor = load_factor;
new.threshold = (uint)(capacity * load_factor);
new.table = allocator::new_array(allocator, Entry*, capacity);
return new;
}

<*
@param [&inout] allocator "The allocator to use"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.new"
*>
fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = null)
{
return self.init(allocator ?: allocator::heap(), capacity, load_factor);
*self = HashMap.new(capacity, load_factor, allocator ?: allocator::heap());
return self;
}

<*
Expand All @@ -34,42 +53,62 @@ fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, fl
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.new"
*>
fn HashMap* HashMap.init(&self, Allocator allocator, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
{
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_array(allocator, Entry*, capacity);
return self;
*self = HashMap.new(capacity, load_factor, allocator);
return self;
}

<*
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
fn HashMap HashMap.temp(uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) @operator(construct) => HashMap.new(capacity, load_factor, allocator::temp()) @inline;

<*
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.temp"
*>
fn HashMap* HashMap.temp_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
{
return self.init(allocator::temp(), capacity, load_factor) @inline;
*self = HashMap.temp(capacity, load_factor);
return self;
}

<*
@param [&inout] allocator "The allocator to use"
@require $vacount % 2 == 0 "There must be an even number of arguments provided for keys and values"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
macro HashMap* HashMap.new_init_with_key_values(&self, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap())
macro HashMap HashMap.new_with_key_values(..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap()) @operator(construct)
{
self.new_init(capacity, load_factor, allocator);
HashMap new = HashMap.new(capacity, load_factor, allocator);
$for (var $i = 0; $i < $vacount; $i += 2)
self.set($vaarg[$i], $vaarg[$i+1]);
new.set($vaarg[$i], $vaarg[$i+1]);
$endfor
return new;
}

<*
@param [&inout] allocator "The allocator to use"
@require $vacount % 2 == 0 "There must be an even number of arguments provided for keys and values"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.new_with_key_values"
*>
macro HashMap* HashMap.new_init_with_key_values(&self, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap())
{
*self = HashMap.new_with_key_values($vasplat, capacity, load_factor, allocator);
return self;
}

Expand All @@ -80,17 +119,33 @@ macro HashMap* HashMap.new_init_with_key_values(&self, ..., uint capacity = DEFA
@require keys.len == values.len "Both keys and values arrays must be the same length"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
fn HashMap* HashMap.new_init_from_keys_and_values(&self, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap())
fn HashMap HashMap.new_from_keys_and_values(Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap()) @operator(construct)
{
HashMap new = HashMap.new(capacity, load_factor, allocator);
assert(keys.len == values.len);
self.new_init(capacity, load_factor, allocator);
for (usz i = 0; i < keys.len; i++)
{
self.set(keys[i], values[i]);
new.set(keys[i], values[i]);
}
return new;
}

<*
@param [in] keys "The keys for the HashMap entries"
@param [in] values "The values for the HashMap entries"
@param [&inout] allocator "The allocator to use"
@require keys.len == values.len "Both keys and values arrays must be the same length"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.new_from_keys_and_values"
*>
fn HashMap* HashMap.new_init_from_keys_and_values(&self, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap())
{
*self = HashMap.new_from_keys_and_values(keys, values, capacity, load_factor, allocator);
return self;
}

Expand All @@ -101,15 +156,32 @@ fn HashMap* HashMap.new_init_from_keys_and_values(&self, Key[] keys, Value[] val
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
macro HashMap HashMap.temp_with_key_values(..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) @operator(construct) => HashMap.new_with_key_values($vasplat, capacity, load_factor, allocator::temp());

<*
@require $vacount % 2 == 0 "There must be an even number of arguments provided for keys and values"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.temp_with_key_values"
*>
macro HashMap* HashMap.temp_init_with_key_values(&self, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR)
{
self.temp_init(capacity, load_factor);
$for (var $i = 0; $i < $vacount; $i += 2)
self.set($vaarg[$i], $vaarg[$i+1]);
$endfor
*self = HashMap.temp_with_key_values($vasplat, capacity, load_factor);
return self;
}

<*
@param [in] keys "The keys for the HashMap entries"
@param [in] values "The values for the HashMap entries"
@require keys.len == values.len "Both keys and values arrays must be the same length"
@require capacity > 0 "The capacity must be 1 or higher"
@require load_factor > 0.0 "The load factor must be higher than 0"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
*>
fn HashMap HashMap.temp_from_keys_and_values(Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) @operator(construct) => HashMap.new_from_keys_and_values(keys, values, capacity, load_factor, allocator::temp());

<*
@param [in] keys "The keys for the HashMap entries"
@param [in] values "The values for the HashMap entries"
Expand All @@ -119,15 +191,11 @@ macro HashMap* HashMap.temp_init_with_key_values(&self, ..., uint capacity = DEF
@require load_factor > 0.0 "The load factor must be higher than 0"
@require !self.allocator "Map was already initialized"
@require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum"
@deprecated "Use HashMap.temp_from_keys_and_values"
*>
fn HashMap* HashMap.temp_init_from_keys_and_values(&self, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator allocator = allocator::heap())
{
assert(keys.len == values.len);
self.temp_init(capacity, load_factor);
for (usz i = 0; i < keys.len; i++)
{
self.set(keys[i], values[i]);
}
*self = HashMap.temp_from_keys_and_values(keys, values, capacity, load_factor);
return self;
}

Expand All @@ -144,29 +212,49 @@ fn bool HashMap.is_initialized(&map)

<*
@param [&in] other_map "The map to copy from."
@deprecated "Use HashMap.new_from_map"
*>
fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map)
{
return self.init_from_map(other_map, allocator::heap()) @inline;
*self = HashMap.new_from_map(other_map, allocator::heap());
return self;
}

<*
@param [&inout] allocator "The allocator to use"
@param [&in] other_map "The map to copy from."
*>
fn HashMap HashMap.new_from_map(HashMap* other_map, Allocator allocator = allocator::heap()) @operator(construct)
{
HashMap new = HashMap.new(other_map.table.len, other_map.load_factor, allocator);
new.put_all_for_create(other_map);
return new;
}

<*
@param [&inout] allocator "The allocator to use"
@param [&in] other_map "The map to copy from."
@deprecated "Use HashMap.new_from_map"
*>
fn HashMap* HashMap.init_from_map(&self, HashMap* other_map, Allocator allocator)
{
self.new_init(other_map.table.len, other_map.load_factor, allocator);
self.put_all_for_create(other_map);
*self = HashMap.new_from_map(other_map, allocator);
return self;
}

<*
@param [&in] other_map "The map to copy from."
*>
fn HashMap HashMap.temp_from_map(HashMap* other_map) => HashMap.new_from_map(other_map, allocator::temp()) @inline;

<*
@param [&in] other_map "The map to copy from."
@deprecated "HashMap.temp_from_map"
*>
fn HashMap* HashMap.temp_init_from_map(&map, HashMap* other_map)
{
return map.init_from_map(other_map, allocator::temp()) @inline;
*map = HashMap.temp_from_map(other_map);
return map;
}

fn bool HashMap.is_empty(&map) @inline
Expand Down
80 changes: 63 additions & 17 deletions lib/std/collections/list.c3
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,21 @@ 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(usz initial_capacity = 16, Allocator allocator = allocator::heap()) @operator(construct)
{
List new = { .allocator = allocator };
new.reserve(initial_capacity);
return new;
}

<*
@param initial_capacity "The initial capacity to reserve"
@param [&inout] allocator "The allocator to use, defaults to the heap allocator"
@deprecated "Use List.new"
*>
fn List* List.new_init(&self, usz initial_capacity = 16, Allocator allocator = allocator::heap())
{
self.allocator = allocator;
self.size = 0;
self.capacity = 0;
self.entries = null;
self.reserve(initial_capacity);
*self = List.new();
return self;
}

Expand All @@ -38,48 +46,86 @@ fn List* List.new_init(&self, usz initial_capacity = 16, Allocator allocator = a

@param initial_capacity "The initial capacity to reserve"
*>
fn List* List.temp_init(&self, usz initial_capacity = 16)
fn List List.temp(usz initial_capacity = 16) @operator(construct) => List.new(initial_capacity, allocator::temp()) @inline;

<*
Initialize the list using the temp allocator.

@param initial_capacity "The initial capacity to reserve"
@deprecated "Use List.temp"
*>
fn List* List.temp_init(&self, usz initial_capacity = 16)
{
*self = List.temp();
return self;
}

<*
Initialize a new list with an array.

@param [in] values `The values to initialize the list with.`
*>
fn List List.new_with_array(Type[] values, Allocator allocator = allocator::heap()) @operator(construct)
{
return self.new_init(initial_capacity, allocator::temp()) @inline;
List new = List.new(values.len, allocator);
new.add_array(values);
return new;
}

<*
Initialize a new list with an array.

@param [in] values `The values to initialize the list with.`
@require self.size == 0 "The List must be empty"
@deprecated "Use List.init_with_array"
*>
fn List* List.new_init_with_array(&self, Type[] values, Allocator allocator = allocator::heap())
{
self.new_init(values.len, allocator) @inline;
self.add_array(values) @inline;
*self = List.new_with_array(values, allocator);
return self;
}

<*
Initialize a temporary list with an array.

@param [in] values `The values to initialize the list with.`
*>
fn List List.temp_with_array(Type[] values) @operator(construct)
{
List new = List.temp(values.len);
new.add_array(values);
return new;
}

<*
Initialize a temporary list with an array.

@param [in] values `The values to initialize the list with.`
@require self.size == 0 "The List must be empty"
@deprecated "Use List.temp_with_array"
*>
fn List* List.temp_init_with_array(&self, Type[] values)
{
self.temp_init(values.len) @inline;
self.add_array(values) @inline;
*self = List.temp_with_array(values) @inline;
return self;
}

<*
@require self.capacity == 0 "The List must not be allocated"
Initialize a list wrapping an array
*>
fn void List.init_wrapping_array(&self, Type[] types, Allocator allocator = allocator::heap())
fn List List.new_wrapping_array(Type[] types, Allocator allocator = allocator::heap()) @operator(construct)
{
self.allocator = allocator;
self.capacity = types.len;
self.entries = types.ptr;
self.set_size(types.len);
List new = { .allocator = allocator, .capacity = types.len, .entries = types.ptr };
new.set_size(types.len);
return new;
}

<*
@require self.capacity == 0 "The List must not be allocated"
@deprecated "Use List.new_wrapping_array"
*>
fn void List.init_wrapping_array(&self, Type[] types, Allocator allocator = allocator::heap()) => *self = List.new_wrapping_array(types, allocator);

fn usz! List.to_format(&self, Formatter* formatter) @dynamic
{
switch (self.size)
Expand Down
Loading
Loading