neyuki 0.1.1

A small Lua-like scripting language implemented in Rust
local table = {}

function table.length(t: {any}): int
    local n = 0
    for _, _ in t do
        n++
    end
    return n
end

function table.insert(t: {any}, v: any, i: int?): int
    local len = table.length(t)
    i = i ?? len+1
    for j = len, i, -1 do
        t[j + 1] = t[j]
    end
    t[i] = v
    return i
end

function table.unpack(t: {any}): ...any
if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    return __table_unpack(t)
end

function table.freeze(t: {any}): {any}
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    __table_freeze(t)
    return t
end

function table.isfrozen(t: {any}): boolean
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    return __table_isfrozen(t)
end

function table.clear(t: {any}): nil
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end

    for k, _ in t do
        t[k] = nil
    end
    return nil
end

function table.clone(t: {any}): {any}
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end

    local newTable = {}
    for k, v in t do
        newTable[k] = v
    end
    return newTable
end

function table.concat(t: {any}, sep: string, i: int?, j: int?): string
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    sep = sep ?? ""
    i = i ?? 1
    j = j ?? table.length(t)

    local result = ""
    for index = i, j do
        result = result .. tostring(t[index])
        if index < j then
            result = result .. sep
        end
    end
    return result
end

function table.create(n: int, v: any): {any}
    if (n == nil) then error("n must be provided") end
    if (type(n) != "number") then error("n must be a number") end
    if (n < 0) then error("n must be non-negative") end

    local t = {}
    for i = 1, n do
        t[i] = v
    end
    return t
end

function table.find(t: {any}, v: any): int?
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    if (v == nil) then error("v must be provided") end

    for k, val in t do
        if (val == v) then
            return k
        end
    end
    return nil
end

function table.pack(...: any): {any}
    local t = {...}
    return t
end

function table.remove(t: {any}, i: int?): any
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end
    local len = table.length(t)
    if (i == nil) then
        i = len
    end
    if (i < 1 or i > len) then
        error("index out of bounds")
    end

    local removedValue = t[i]
    for j = i, len - 1 do
        t[j] = t[j + 1]
    end
    t[len] = nil
    return removedValue
end

function table.sort(t: {any}, cmp: ((a: any, b: any) -> bool)?): nil
    if (t == nil) then error("t must be provided") end
    if (type(t) != "table") then error("t must be a table") end

    local default_cmp = function(a, b) return a < b end
    local compare = cmp ?? default_cmp

    local len = table.length(t)
    if len <= 1 then return nil end

    local function qsort(low: number, high: number)
        if low < high then
            local pivot = t[high]
            local i = low - 1
            for j = low, high - 1 do
                if compare(t[j], pivot) then
                    i = i + 1
                    local temp = t[i]
                    t[i] = t[j]
                    t[j] = temp
                end
            end
            local temp = t[i + 1]
            t[i + 1] = t[high]
            t[high] = temp
            local pi = i + 1
            qsort(low, pi - 1)
            qsort(pi + 1, high)
        end
    end

    qsort(1, len)
    return nil
end

function table.move(a1: {any}, f: number, e: number, t: number, a2: {any}?): {any}
    if (a1 == nil) then error("a1 must be provided") end
    if (type(a1) != "table") then error("a1 must be a table") end
    local dest = a2 ?? a1
    if (type(dest) != "table") then error("a2 must be a table") end
    if (e >= f) then
        local d = t - f
        if (t > f and t <= e) then
            for i = e, f, -1 do
                dest[i + d] = a1[i]
            end
        else
            for i = f, e do
                dest[i + d] = a1[i]
            end
        end
    end
    return dest
end

return table.freeze(table)