Compare commits
2 Commits
a1241905ea
...
fc59af3bf3
Author | SHA1 | Date | |
---|---|---|---|
fc59af3bf3
|
|||
cd27bdf2e0
|
173
luau/src.luau
173
luau/src.luau
@ -4,85 +4,172 @@
|
|||||||
local Array = {}
|
local Array = {}
|
||||||
Array.__index = Array
|
Array.__index = Array
|
||||||
|
|
||||||
type constructor<T> = { inner: {T} }
|
type constructor<T> = { __inner: {T} }
|
||||||
export type Array<T> = typeof(setmetatable({} :: constructor<T>, Array))
|
export type Array<T> = setmetatable<constructor<T>, typeof(Array)>
|
||||||
|
|
||||||
type FnCall<T, R = T> = (T, number, Array<T>) -> R
|
type FnCall<T, R = T> = (T, number, Array<T>) -> R
|
||||||
|
|
||||||
function Array.new<T>(from: {T}?): Array<T>
|
function Array.new<T>(from: {T}?): Array<T>
|
||||||
return setmetatable({ inner = from or {} }, Array)
|
return setmetatable({ __inner = from or {} }, Array)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:table<T>(): {T}
|
function Array:into_table<T>(): {T}
|
||||||
return self.inner
|
return self.__inner
|
||||||
end
|
|
||||||
|
|
||||||
function Array:pop<T>(): T?
|
|
||||||
return table.remove(self.inner, #self.inner)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Array:concat(sep: string?, i: number?, j: number?): string
|
|
||||||
return table.concat(self.inner, sep, i, j)
|
|
||||||
end
|
|
||||||
|
|
||||||
function Array:clone<T>(): Array<T>
|
|
||||||
return Array.new(table.clone(self.inner))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:len(): number
|
function Array:len(): number
|
||||||
return #self.inner
|
return #self.__inner
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:pop<T>(): T?
|
||||||
|
return table.remove(self.__inner, self:len())
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:concat(sep: string?, i: number?, j: number?): string
|
||||||
|
return table.concat(self.__inner, sep, i, j)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:clone<T>(): Array<T>
|
||||||
|
return Array.new(table.clone(self.__inner))
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:is_empty(): boolean
|
||||||
|
return self:len() == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:type_id(): string
|
||||||
|
return type(self.__inner[1])
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:get<T, I>(index: I): T?
|
function Array:get<T, I>(index: I): T?
|
||||||
return self.inner[index]
|
return self.__inner[index]
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:get_base0<T>(index: number): T?
|
||||||
|
return self:get(index + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:join<T>(sep: T): Array<T>
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:append<T>(other: Array<T>): Array<T>
|
||||||
|
return self:append_table(other:into_table())
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:append_table<T>(t: {T}): Array<T>
|
||||||
|
table.move(t, 1, #t, self:len() + 1, self.__inner)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:slice<T>(start: number, endj: number?): Array<T>
|
||||||
|
local slice_t: {T} = {}
|
||||||
|
table.move(self.__inner, start, endj or self:len(), 1, slice_t)
|
||||||
|
return Array.new(slice_t)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:push<T>(...: T): ()
|
function Array:push<T>(...: T): ()
|
||||||
for _, val: T in {...} do
|
for _, val: T in {...} do
|
||||||
table.insert(self.inner, val)
|
table.insert(self.__inner, val)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:foreach<T>(callbackFn: FnCall<T, nil>): Array<T>
|
function Array:foreach<T>(f: FnCall<T, nil>): Array<T>
|
||||||
for ind: number, val: T in self.inner do
|
for ind: number, val: T in self.__inner do
|
||||||
callbackFn(val, ind, self)
|
f(val, ind, self)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:map<T, M>(callbackFn: FnCall<T, M>): Array<M>
|
function Array:map<T, M>(f: FnCall<T, M>): Array<M>
|
||||||
local n: {M} = {}
|
local t_map: {M} = {}
|
||||||
for ind: number, val: T in self.inner do
|
for ind: number, val: T in self.__inner do
|
||||||
table.insert(n, callbackFn(val, ind, self))
|
table.insert(t_map, f(val, ind, self))
|
||||||
end
|
end
|
||||||
return Array.new(n)
|
return Array.new(t_map)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:filter<T>(callbackFn: FnCall<T, boolean>): Array<T>
|
function Array:filter<T>(f: FnCall<T, boolean>): Array<T>
|
||||||
local n: {T} = {}
|
local t_filter: {T} = {}
|
||||||
for ind: number, val: T in self.inner do
|
for ind: number, val: T in self.__inner do
|
||||||
if callbackFn(val, ind, self) then
|
if f(val, ind, self) then
|
||||||
table.insert(n, val)
|
table.insert(t_filter, val)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return Array.new(n)
|
return Array.new(t_filter)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:binary_search<T>(x: T): T?
|
function Array:reverse<T>(): Array<T>
|
||||||
local size = #self.inner
|
local t_rev: {T} = {}
|
||||||
|
local t_len = self:len()
|
||||||
|
for i = 1, t_len do
|
||||||
|
t_rev[i] = self.__inner[t_len - i + 1]
|
||||||
|
end
|
||||||
|
self.__inner = t_rev
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:sort<T>(): Array<T>
|
||||||
|
table.sort(self.__inner, function(a: T, z: T)
|
||||||
|
if type(a) == "number" then
|
||||||
|
return a < z
|
||||||
|
end
|
||||||
|
return tostring(a) < tostring(z)
|
||||||
|
end)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:reduce(f: (number, number) -> number): number
|
||||||
|
local init_v = self.__inner[1]
|
||||||
|
if type(init_v) == "string" then
|
||||||
|
return tonumber("nan") :: number
|
||||||
|
end
|
||||||
|
for _, val: number in self.__inner do
|
||||||
|
init_v = f(init_v, val)
|
||||||
|
end
|
||||||
|
return init_v
|
||||||
|
end
|
||||||
|
|
||||||
|
local function binary_search_by(self: Array<number>, x: number, eq: (number, number) -> number): number?
|
||||||
|
local size = self:len()
|
||||||
if size == 0 then return nil end
|
if size == 0 then return nil end
|
||||||
local base = 1
|
local base = 1
|
||||||
|
while base <= size do
|
||||||
while base < size do
|
local mid = eq(base, size)
|
||||||
size -= bit32.rshift(base + size, 1)
|
if self.__inner[mid] == x then
|
||||||
|
return mid
|
||||||
|
elseif self.__inner[mid] < x then
|
||||||
|
base = mid + 1
|
||||||
|
else
|
||||||
|
size = mid - 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function Array:debug_display<T>(): string
|
function Array:binary_search(x: number): number?
|
||||||
return self:map(function(val: T, ind: number)
|
if self:type_id() ~= "number" then
|
||||||
return ind .. ": " .. tostring(val) .. (ind ~= self:len() and ", " or "")
|
return nil
|
||||||
|
end
|
||||||
|
return binary_search_by(self, x, function(base, size)
|
||||||
|
return bit32.rshift(base + size, 1)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:binary_search_64(x: number): number?
|
||||||
|
if self:type_id() ~= "number" then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return binary_search_by(self, x, function(base, size)
|
||||||
|
return math.floor((base + size) / 2)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:tostring<T>(): string
|
||||||
|
return self:map(function(val: T, index: number)
|
||||||
|
local formatted_val = if type(val) == "string" then `"{val}"` else tostring(val)
|
||||||
|
local formatted_end = if index ~= self:len() then ", " else ""
|
||||||
|
return index .. ": " .. formatted_val .. formatted_end
|
||||||
end):concat()
|
end):concat()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ local numbers = Array.new()
|
|||||||
for i = 1, 100 do
|
for i = 1, 100 do
|
||||||
numbers:push(i)
|
numbers:push(i)
|
||||||
end
|
end
|
||||||
print(numbers:debug_display(), "\nlength=", numbers:len())
|
print(numbers:tostring(), "\nlength=", numbers:len())
|
||||||
|
|
||||||
local start = os.clock()
|
|
||||||
|
|
||||||
numbers:map(function(n: number)
|
numbers:map(function(n: number)
|
||||||
return tostring(n)
|
return tostring(n)
|
||||||
@ -17,5 +15,3 @@ end):foreach(function(e) print("(:map)squared=", e) end)
|
|||||||
numbers:filter(function(n: number)
|
numbers:filter(function(n: number)
|
||||||
return bit32.band(n, 1) ~= 0
|
return bit32.band(n, 1) ~= 0
|
||||||
end):foreach(function(e) print("(:filter)odd=", e) end)
|
end):foreach(function(e) print("(:filter)odd=", e) end)
|
||||||
|
|
||||||
print(os.clock()-start)
|
|
13
tests/luau/reduce.luau
Normal file
13
tests/luau/reduce.luau
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
--!strict
|
||||||
|
|
||||||
|
local Array = require("../../luau/src")
|
||||||
|
|
||||||
|
local numbers = Array.new({1, 2, 3, 4})
|
||||||
|
|
||||||
|
print(numbers:tostring(), "\nlength=", numbers:len())
|
||||||
|
|
||||||
|
local sum = numbers:reduce(function(accumulator: number, currentValue: number)
|
||||||
|
return accumulator - currentValue
|
||||||
|
end)
|
||||||
|
|
||||||
|
print("sum=", sum)
|
13
tests/luau/reverse.luau
Normal file
13
tests/luau/reverse.luau
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
--!strict
|
||||||
|
|
||||||
|
local Array = require("../../luau/src")
|
||||||
|
|
||||||
|
local numbers = Array.new()
|
||||||
|
for i = 1, 100 do
|
||||||
|
numbers:push(i)
|
||||||
|
end
|
||||||
|
print(numbers:tostring(), "\nlength=", numbers:len())
|
||||||
|
|
||||||
|
numbers:reverse()
|
||||||
|
|
||||||
|
print(numbers:tostring())
|
18
tests/luau/slice.luau
Normal file
18
tests/luau/slice.luau
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
--!strict
|
||||||
|
|
||||||
|
local Array = require("../../luau/src")
|
||||||
|
|
||||||
|
local animals = Array.new({"ant", "bison", "camel", "duck", "elephant"})
|
||||||
|
|
||||||
|
print(animals:tostring(), "\nlength=", animals:len())
|
||||||
|
|
||||||
|
local slice = animals:slice(3)
|
||||||
|
local slice2 = animals:slice(2,4)
|
||||||
|
local slice3 = animals:slice(1,5)
|
||||||
|
|
||||||
|
print("(:slice 3)" .. slice:tostring())
|
||||||
|
print("(:slice 2,4)" .. slice2:tostring())
|
||||||
|
print("(:slice 1,5)" .. slice3:tostring())
|
||||||
|
|
||||||
|
animals:join({"hi", "shrek"})
|
||||||
|
print("(:join)" .. animals:tostring())
|
11
tests/luau/sort.luau
Normal file
11
tests/luau/sort.luau
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--!strict
|
||||||
|
|
||||||
|
local Array = require("../../luau/src")
|
||||||
|
|
||||||
|
local months = Array.new({"March", "Jan", "Feb", "Dec"})
|
||||||
|
|
||||||
|
print(months:tostring(), "\nlength=", months:len())
|
||||||
|
|
||||||
|
months:sort()
|
||||||
|
|
||||||
|
print(months:tostring())
|
@ -1,11 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
touch results.txt
|
touch results.txt
|
||||||
|
echo "" > results.txt
|
||||||
|
|
||||||
test () {
|
test () {
|
||||||
echo "-- [Test: $1] --" > results.txt
|
echo -e "\n-- [Test: $1] --" >> results.txt
|
||||||
luau $2 >> results.txt
|
luau $2 >> results.txt
|
||||||
echo "-- [Test: $1] --" >> results.txt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "map_filter" "./luau/map_filter.luau"
|
test "map_filter" "./luau/map_filter.luau"
|
||||||
|
test "reverse" "./luau/reverse.luau"
|
||||||
|
test "reduce" "./luau/reduce.luau"
|
||||||
|
test "slice" "./luau/slice.luau"
|
||||||
|
test "sort" "./luau/sort.luau"
|
Reference in New Issue
Block a user