ryobg / JContainers

JSON-based data structures for Papyrus - the TESV Skyrim SE scripting language
MIT License
107 stars 23 forks source link

Testing for nil forms in Lua #33

Closed RealAntithesis closed 6 years ago

RealAntithesis commented 6 years ago

One of my lua scripts tests whether two papyrus forms are identical or not. Testing whether they are equal is fine. However, if I wanted to test whether either form is nil, then lua generates an error.

I believe it comes down to the metatype function in jc.lua:

local CForm = ffi.metatype('CForm', { __eq = function(l, r) return l.___id == r.___id end })

This function doesn't appear to consider the situation if either side is a nil value since referencing the id of either would generate an error (however, this is unfamiliar to me)? Thanks

ryobg commented 6 years ago

Hmm... have to see that for myself. On first sight it is like you said. It will be more generic to have these nulls considered. I suppose you have workarounded by checking explicitly for null values?

RealAntithesis commented 6 years ago

The checking for nil values was the thing causing the error, so I had to remove it:

if itemForm ~= nil then
--
end

The above code causes an error - I assume because the equality function references r.___id, but r in this case is nil. Perhaps it should return true if both sides are nil? Then it will be up to the code to check if there is a nil value.

ryobg commented 6 years ago

In programming languages which cross my mind currently the null value is part of the check. Have you tried to check the type itself for null first? Adaptation of what I mean:

if (A and B) and (A.id == B.id) then
   -- true
else
    -- false
    -- or: A and B are both nil
end

I will check to fix that equation to consider null if any.

ryobg commented 6 years ago

Hi @RealAntithesis ,

I have basically build new version with all the stuff (Lua funcs and its new CForm equality operator) here. Can you check it out?

I have decided to follow the current logic for comparing JArrays/Maps/etc... which is strangely, if you compare two null values you will get false. Not sure why it was done like this.

RealAntithesis commented 6 years ago

Thanks - I'll check it out. I'm not sure about the logic though. If the itemForm variable is a form, and is nil, then shouldn't itemForm == nil return true (yes, it is nil), not false (this is then saying that itemForm is not nil, when it is)? Otherwise there's no way of checking that it is nil, because if itemForm is not nil, then itemForm == nil will still return false (because they aren't equal).

Edit: now that I've had a look at the change - it looks like it will work. I'll test it out.

RealAntithesis commented 6 years ago

Tested - and it works great. No errors that the previous version generated. I suppose the "l.id == r.id or false" part of the function is supposed to check if there is an CForm object but it is somehow invalid.

ryobg commented 6 years ago

I didn't get quite well what you said? I think the only issue is if you have nil == nil which will return false.

RealAntithesis commented 6 years ago

NP - I think it's working now with the scenarios I've tested it against. If this becomes an issue later, I'll raise it then.