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

Add array:indexOf #2939

Merged
merged 4 commits into from
Jan 16, 2024
Merged
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
9 changes: 7 additions & 2 deletions data/expression2/tests/runtime/types/array.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ assert(KV[50, number] == 200)
assert(KV[100, number] == 2000)

local Rec = 0
foreach(I, V:number = KV) {
foreach(I:number, V:number = KV) {
Rec++
assert(KV[I, number] == V)
}

assert(Rec == 1) # Only 1 because this breaks the internal ipairs impl (Shouldn't use an array like this anyway.)

A[1, vector] = vec()
assert(A[1, vector] == vec())
assert(A[1, vector] == vec())

A[2, entity] = entity()

assert(A:indexOf(entity()) == 2)
assert(A:indexOf(noentity()) == 0)
77 changes: 42 additions & 35 deletions lua/entities/gmod_wire_expression2/core/array.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ registerType("array", "r", {},
nil,
nil,
function(v)
return !istable(v)
return not istable(v)
end
)

Expand Down Expand Up @@ -65,16 +65,16 @@ end
-- Looped functions and operators
--------------------------------------------------------------------------------
registerCallback( "postinit", function()
local getf, setf
local NO_LEGACY = { legacy = false }
for k,v in pairs( wire_expression_types ) do
local name = k:lower()
if (name == "normal") then name = "number" end
if name == "normal" then name = "number" end
local nameupperfirst = upperfirst( name )
local id = v[1]
local default = v[2]
local typecheck = v[6]

if (!blocked_types[id]) then -- blocked check start
if not blocked_types[id] then -- blocked check start

--------------------------------------------------------------------------------
-- Get functions
Expand All @@ -83,7 +83,7 @@ registerCallback( "postinit", function()
__e2setcost(1)

local function getter( self, array, index, doremove )
if (!array or !index) then return fixDefault( default ) end -- Make sure array and index are value
if not array or not index then return fixDefault( default ) end -- Make sure array and index are value
local ret
if (doremove) then
ret = table_remove( array, index )
Expand Down Expand Up @@ -113,18 +113,17 @@ registerCallback( "postinit", function()
__e2setcost(5)

registerFunction( name, "r:n", id, function(self, args)
local op1, op2 = args[2], args[3]
local array, index = op1[1](self,op1), op2[1](self,op2)
local array, index = args[2], args[3]
return getter( self, array, index )
end, nil, nil, { deprecated = true })
end, nil, nil, { legacy = false, deprecated = true })

--------------------------------------------------------------------------------
-- Set functions
-- R[N,type] = value, and R:set<type>(N,value)
--------------------------------------------------------------------------------

local function setter( self, array, index, value, doinsert )
if (!array or !index) then return fixDefault( default ) end -- Make sure array and index are valid
if not array or not index then return fixDefault( default ) end -- Make sure array and index are valid
if (typecheck and typecheck( value )) then return fixDefault( default ) end -- If typecheck returns true, the type is wrong.
if (doinsert) then
if index > 2^31 or index < 0 then return fixDefault( default ) end -- too large, possibility of crashing gmod
Expand Down Expand Up @@ -153,10 +152,9 @@ registerCallback( "postinit", function()
end

registerFunction("set" .. nameupperfirst, "r:n"..id, id, function(self,args)
local op1, op2, op3 = args[2], args[3], args[4]
local array, index, value = op1[1](self,op1), op2[1](self,op2), op3[1](self,op3)
local array, index, value = args[1], args[2], args[3]
return setter( self, array, index, value )
end, nil, nil, { deprecated = true })
end, nil, nil, { legacy = false, deprecated = true })


--------------------------------------------------------------------------------
Expand All @@ -166,63 +164,72 @@ registerCallback( "postinit", function()
__e2setcost(7)

registerFunction( "push" .. nameupperfirst, "r:" .. id, id, function(self,args)
local op1, op2 = args[2], args[3]
local array, value = op1[1](self,op1), op2[1](self,op2)
local array, value = args[1], args[2]
return setter( self, array, #array + 1, value )
end)
end, nil, nil, NO_LEGACY)

--------------------------------------------------------------------------------
-- Insert functions
-- Inserts the value at the specified index. Subsequent values are moved up to compensate.
--------------------------------------------------------------------------------
registerFunction( "insert" .. nameupperfirst, "r:n" .. id, id, function( self, args )
local op1, op2, op3 = args[2], args[3], args[4]
local array, index, value = op1[1](self,op1), op2[1](self,op2), op3[1](self,op3)
local array, index, value = args[1], args[2], args[3]
return setter( self, array, index, value, true )
end)
end, nil, nil, NO_LEGACY)

--------------------------------------------------------------------------------
-- Pop functions
-- Removes and returns the last value in the array.
--------------------------------------------------------------------------------
registerFunction( "pop" .. nameupperfirst, "r:", id, function(self,args)
local op1 = args[2]
local array = op1[1](self,op1)
if (!array) then return fixDefault( default ) end
local array = args[1]
if not array then return fixDefault(default) end
return getter( self, array, #array, true )
end)
end, nil, nil, NO_LEGACY)

--------------------------------------------------------------------------------
-- Unshift functions
-- Inserts the value at the beginning of the array. Subsequent values are moved up to compensate.
--------------------------------------------------------------------------------
registerFunction( "unshift" .. nameupperfirst, "r:" .. id, id, function(self,args)
local op1, op2 = args[2], args[3]
local array, value = op1[1](self,op1), op2[1](self,op2)
local array, value = args[1], args[2]
return setter( self, array, 1, value, true )
end)
end, nil, nil, NO_LEGACY)

--------------------------------------------------------------------------------
-- Shift functions
-- Removes and returns the first value of the array. Subsequent values are moved down to compensate.
--------------------------------------------------------------------------------
registerFunction( "shift" .. nameupperfirst, "r:", id, function(self,args)
local op1 = args[2]
local array = op1[1](self,op1)
if (!array) then return fixDefault( default ) end
local array = args[1]
if not array then return fixDefault(default) end
return getter( self, array, 1, true )
end)
end, nil, nil, NO_LEGACY)

--------------------------------------------------------------------------------
-- Remove functions
-- Removes and returns the specified value of the array. Subsequent values are moved down to compensate.
--------------------------------------------------------------------------------
registerFunction( "remove" .. nameupperfirst, "r:n", id, function(self,args)
local op1, op2 = args[2], args[3]
local array, index = op1[1](self,op1), op2[1](self,op2)
if (!array or !index) then return fixDefault( default ) end
local array, index = args[1], args[2]
if not array or not index then return fixDefault(default) end
return getter( self, array, index, true )
end)
end, nil, nil, NO_LEGACY)

-- indexOf

registerFunction("indexOf", "r:" .. id, "n", function(self, args)
local arr, val = args[1], args[2]
local l = #arr
for i = 1, l do
if arr[i] == val then
self.prf = self.prf + i
return i
end
end
self.prf = self.prf + l
return 0
end, nil, { "value" }, NO_LEGACY)

--------------------------------------------------------------------------------
-- Foreach operators
Expand Down Expand Up @@ -507,7 +514,7 @@ end
--------------------------------------------------------------------------------
__e2setcost(1)
e2function array array:add( array other )
if (!next(this) and !next(other)) then return {} end -- Both of them are empty
if not next(this) and not next(other) then return {} end -- Both of them are empty
local ret = {}
for i=1,#this do
ret[i] = this[i]
Expand All @@ -525,7 +532,7 @@ end
--------------------------------------------------------------------------------
__e2setcost(1)
e2function array array:merge( array other )
if (!next(this) and !next(other)) then return {} end -- Both of them are empty
if not next(this) and not next(other) then return {} end -- Both of them are empty
local ret = {}
for i=1,math.max(#this,#other) do
ret[i] = other[i] or this[i]
Expand Down
1 change: 1 addition & 0 deletions lua/wire/client/e2descriptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,7 @@ E2Helper.Descriptions["concat(r:snn)"] = "Concatenates all values in the array,
E2Helper.Descriptions["count(r:)"] = "Returns the number of entries in the array"
E2Helper.Descriptions["exists(r:n)"] = "Returns 1 if the array contains any value at specified index"
E2Helper.Descriptions["id(r:)"] = "Returns the unique ID of the array"
E2Helper.Descriptions["indexOf"] = "Returns the index of the element in the array or 0 if it's not found. This function is very inefficient for large arrays. You should use look-up tables if you intend on using this frequently."
E2Helper.Descriptions["invert(r)"] = "Inverts the array, creating a lookup table"
E2Helper.Descriptions["min(r:)"] = "Returns the smallest number in array"
E2Helper.Descriptions["max(r:)"] = "Returns the largest number in array"
Expand Down
Loading