Skip to content

Commit

Permalink
Add array:indexOf (#2939)
Browse files Browse the repository at this point in the history
* Update array functions
Add array:indexOf

* Remove remainder of C nots

* Update description

* Change loop
  • Loading branch information
Denneisk authored Jan 16, 2024
1 parent 842f5a1 commit 93bb7cc
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 37 deletions.
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

0 comments on commit 93bb7cc

Please sign in to comment.