-
-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rename arraytable to sequence, add tests and comment its functions
- Loading branch information
Showing
15 changed files
with
265 additions
and
189 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
-- Sequence type | ||
-- | ||
-- This type is typically used as a more efficient lua table that can hold only sequences. | ||
-- Its elements starts at index 1 and go up to its length (like lua tables), | ||
-- internally it just contains a pointer, so it's passed by reference by default | ||
-- (like lua tables again). | ||
-- | ||
-- By default its use the garbage collector unless explicitly told not to do so, | ||
-- thus by default there is no need to manually reset the sequence. | ||
|
||
|
||
## unitname = 'nelua' | ||
|
||
require 'memory' | ||
|
||
## local make_sequence = generalize(function(T, allocator) | ||
## staticassert(traits.is_type(T), "invalid type '%s'", T) | ||
## local codenameprefix = 'nelua_sequence_'..T.name | ||
## if allocator then | ||
local allocator: type = #[allocator]# | ||
## codenameprefix = codenameprefix..'_'..allocator.nick | ||
## else | ||
require 'allocators.gc_allocator' | ||
local allocator: type = @gc_allocator | ||
## end | ||
|
||
local T = @#[T]# | ||
local SequenceImplT <codename #[codenameprefix..'_impl']#> = @record { | ||
size: usize, | ||
data: span(T) | ||
} | ||
local SequenceT <codename #[codenameprefix]#> = @record{ | ||
impl: SequenceImplT* | ||
} | ||
|
||
-- Resets and removes all elements from the sequence. | ||
function SequenceT:clear() | ||
if not self.impl then return end | ||
if self.impl.data.size ~= 0 then | ||
local zero: T | ||
for i:usize=0,self.impl.size do | ||
self.impl.data[i] = zero | ||
end | ||
end | ||
self.impl.size = 0 | ||
end | ||
|
||
-- Reset sequence to zeroed state, freeing all used resources. | ||
-- This is more useful free resources when not using the garbage collector. | ||
function SequenceT:reset() | ||
if not self.impl then return end | ||
self:clear() | ||
allocator.spandealloc(self.impl.data) | ||
allocator.dealloc(self.impl) | ||
self.impl = nilptr | ||
end | ||
|
||
function SequenceT:_grow() | ||
local cap: usize = 2 | ||
if likely(self.impl.data.size ~= 0) then cap = self.impl.data.size * 2 end | ||
self.impl.data = allocator.spanrealloc0(self.impl.data, cap) | ||
end | ||
|
||
-- Initializes sequence internal implementation if needed. | ||
-- This is already implicitly called by other sequence functions when needed. | ||
function SequenceT:init() <inline> | ||
if likely(self.impl) then return end | ||
self.impl = (@SequenceImplT*)(allocator.alloc0(#SequenceImplT)) | ||
end | ||
|
||
-- Reserve at least `n` elements on the sequence capacity. | ||
function SequenceT:reserve(n: usize <autocast>) | ||
self:init() | ||
local cap: usize = n + 1 | ||
if self.impl.data.size >= cap then return end | ||
self.impl.data = allocator.spanrealloc0(self.impl.data, cap) | ||
end | ||
|
||
-- Resizes the sequence so that it contains `n` elements as copies of `v`. | ||
function SequenceT:resize(n: usize <autocast>, v: T) | ||
self:init() | ||
if n <= self.impl.size then return end | ||
self:reserve(n) | ||
for i=self.impl.size+1,<n do | ||
self.impl.data[i+1] = v | ||
end | ||
self.impl.size = n | ||
end | ||
|
||
-- Adds a new element at the end of the sequence. | ||
function SequenceT:push(v: T) <inline> | ||
self:init() | ||
self.impl.size = self.impl.size + 1 | ||
if unlikely(self.impl.size + 1 >= self.impl.data.size) then | ||
self:_grow() | ||
end | ||
self.impl.data[self.impl.size] = v | ||
end | ||
|
||
-- Removes the last element in the sequence and returns its value. | ||
-- If the sequence is empty, then throws a runtime error. | ||
function SequenceT:pop(): T <inline> | ||
check(self.impl and self.impl.size > 0, 'sequence.pop: length is 0') | ||
local zero: T | ||
local ret: T = self.impl.data[self.impl.size] | ||
self.impl.data[self.impl.size] = zero | ||
self.impl.size = self.impl.size - 1 | ||
return ret | ||
end | ||
|
||
-- Return reference to element at index `i`. | ||
-- If `i` is the sequence size plus 1, then a zeroed element is added and return its reference. | ||
-- If `i` is larger then the sequence size plus 1, then throws a runtime error. | ||
function SequenceT:__atindex(i: usize <autocast>): T* <inline> | ||
self:init() | ||
if unlikely(i > self.impl.size) then | ||
check(i == self.impl.size + 1, 'sequence.at: index out of range') | ||
self.impl.size = self.impl.size + 1 | ||
end | ||
if unlikely(self.impl.size + 1 > self.impl.data.size) then | ||
self:_grow() | ||
end | ||
return &self.impl.data[i] | ||
end | ||
|
||
-- Return the number of elements in the sequence. It never counts the element at 0. | ||
function SequenceT:__len(): isize <inline> | ||
if unlikely(not self.impl) then return 0 end | ||
return (@isize)(self.impl.size) | ||
end | ||
|
||
-- Initialize a sequence elements from a fixed array. | ||
-- This allows to use sequence initialization with braces. | ||
function SequenceT.__convert(values: #[concept(function(x) | ||
if x.type:is_array_of(T) then return true end | ||
end)]#): SequenceT <inline> | ||
local self: SequenceT | ||
self:reserve(#values) | ||
self.impl.size = #values | ||
for i:usize=1,#values do | ||
self.impl.data[i] = values[i-1] | ||
end | ||
return self | ||
end | ||
##[[SequenceT.value.choose_braces_type = function(node) | ||
return types.ArrayType(nil, T, #node[1]) | ||
end]] | ||
|
||
## return SequenceT | ||
## end) | ||
|
||
global sequence = #[make_sequence]# |
Oops, something went wrong.