dibyendumajumdar/ravi

Lua parsing error

mustime opened this issue · 4 comments

Compiling the following code into bytecode:

local t = {}

function t:GetNumFromStr(strData, Substr: string)
    local iSubLen = #Substr
    local iCount = 0
    local temp1 = strData
    for i = 1, #strData, 1 do
        local temp2 = string.sub(temp1, i, i + iSubLen - 1)
        if temp2 == Substr then
            i = i + iSubLen
            iCount = iCount + 1
        end
    end

    return iCount
end

and will end up with an error:

test.lua:11: Invalid assignment: integer expected near 'iCount'

However, if I change line: 4 to local iSubLen: integer = #Substr, it will get passed.

So I wonder doesn't # operation make iSubLen an integer already? Why : integer is needed.

hi
the # operator is not guaranteed to return an integer value as you can have meta method to override the behavior.

Although I suppose if operand is a string, unlikely to have a metamethod on it. Maybe in this case we could assert its an integer

Although I suppose if operand is a string, unlikely to have a metamethod on it. Maybe in this case we could assert its an integer

The # operator is guaranteed to return integers for ravi-arrays and strings. There is already a case for that when parsing the length operator

ravi/src/lcode.c

Lines 1315 to 1319 in a6eeb86

case OP_LEN:
e->u.info = luaK_codeABC(fs, OP_LEN, 0, r, 0);
if ((e->ravi_type_map & (~(RAVI_TM_INTEGER_ARRAY | RAVI_TM_FLOAT_ARRAY | RAVI_TM_STRING))) == 0) {
e->ravi_type_map = RAVI_TM_INTEGER;
}

but Substr: string allows Substr to be a string or nil and nil can have a metamethod for the length operator.

Also, there is a bug in lcode.c:

--- a/src/lcode.c
+++ b/src/lcode.c
@@ -1391,7 +1391,7 @@ static void codebinexpval (FuncState *fs, OpCode op,
     }                                                                      \
     e1->u.info = luaK_codeABC(fs, OP_##op, 0, rk1, rk2);                   \
     if ((e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0 && \
-        (e1->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0) { \
+        (e2->ravi_type_map & (~(RAVI_TM_FLOAT | RAVI_TM_INTEGER))) == 0) { \
       if (e1->ravi_type_map & e2->ravi_type_map & RAVI_TM_INTEGER) {       \
         e1->ravi_type_map = RAVI_TM_FLOAT | ii;                            \
       }                                                                    \

@mustime I do not know what you do with i = i + iSubLen as

for i = 1, 10 do
    print(i)
    i = i + 2
end

might not give the result you expected.

@mustime I do not know what you do with i = i + iSubLen as

for i = 1, 10 do
    print(i)
    i = i + 2
end

might not give the result you expected.

Well, the logic I list above had been stripped down and somehow pointless. Just try to explain the case. And it seems only happened within the for-statement.

To make this simpler, try the following code:

function foo(a, b)
    local x = #b
    for i = 1, #a, 1 do
        i = i + x
    end
end

And will get test.lua: 5: Invalid assignment: integer expected near 'end'