This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
DannySMc's profile picture

Table index is nil when using dofile

Started by DannySMc, 17 July 2016 - 09:41 PM
DannySMc #1
Posted 17 July 2016 - 11:41 PM
Okay hello there!

I have made a test program, which I wrapper in one big function and this all works perfectly. when I execute the wrapping function, so I string.dump 'd it, and attempted to dofile() it, but my error is table index is nil? I have never seen that error before so I am not sure exactly what I am doing wrong…?

I just got the dumped file name (example: "dump.lua") and then did the following:

executeTest = dofile("dump.lua");


But i get: bios:14 table index is nil

I am not trying to execute the function either, this is just the dofile function… Anyone have any ideas?

Thanks in advance.

NOTE:
This is purely just based off of interest, I don't plan on doing anything stupid with it, just interested on what's possible.
Bomb Bloke #2
Posted 18 July 2016 - 12:37 AM
Basically it's telling you that this isn't valid Lua:

local myTable = {[nil] = "Hello World"}

Hard to comment further as you haven't bothered to show the code, but a shot in the dark guess is that it involves the environment.

I am not trying to execute the function either

Er, yes you are? dofile ~= loadfile
DannySMc #3
Posted 18 July 2016 - 01:41 AM
Basically it's telling you that this isn't valid Lua:
local myTable = {[nil] = "Hello World"}
Hard to comment further as you haven't bothered to show the code, but a shot in the dark guess is that it involves the environment.
I am not trying to execute the function either
Er, yes you are? dofile ~= loadfile

I didn't "bother" because it's about 12,000 lines of bytecode which would lag up my tablet. If possible I am actually using an unreleased program as a testing point, would you mind if I PM'd you the data? just because I don't wish to publicly release it just yet?

Again, I didn't actually know that executes it, although that would make a lot of sense as loadstring was coming back as nil. I wonder if there is a limit to CC's string.dump? maybe it didn't do it all? or missed some…
Bomb Bloke #4
Posted 18 July 2016 - 06:48 AM
I didn't "bother" because it's about 12,000 lines of bytecode which would lag up my tablet. If possible I am actually using an unreleased program as a testing point, would you mind if I PM'd you the data?

Sure, so long as you include what it was built out of. The bytecode itself isn't so useful for debugging purposes.
MKlegoman357 #5
Posted 18 July 2016 - 09:07 AM
First of all, when saving the bytecode you have to save it using a "wb" mode, because it contains bytes that will be corrupted if using "w" mode. Second, dofile, loadfile and any other function will not work because they open the file in "r" mode, not "rb" mode which is required to properly load the bytecode.
Bomb Bloke #6
Posted 18 July 2016 - 09:26 AM
Huh. So we can't load bytecode at all? I lose track. :(/>
DannySMc #7
Posted 18 July 2016 - 09:45 AM
First of all, when saving the bytecode you have to save it using a "wb" mode, because it contains bytes that will be corrupted if using "w" mode. Second, dofile, loadfile and any other function will not work because they open the file in "r" mode, not "rb" mode which is required to properly load the bytecode.

I did wonder whether I needed to use rb / wb, because it works in C when loading other bytecode using Lua…

So can we load it ato all?
The Crazy Phoenix #8
Posted 18 July 2016 - 10:09 AM
Huh. So we can't load bytecode at all? I lose track. :(/>
Read with rb mode, concatenate, and use loadstring. I've done it before, it works.
DannySMc #9
Posted 18 July 2016 - 10:36 AM
Huh. So we can't load bytecode at all? I lose track. :(/>
Read with rb mode, concatenate, and use loadstring. I've done it before, it works.

Concatenate what?

local bc = fs.open("dump.lua", "rb");
data = bc.readAll();
bc.close();

local newfunc = loadstring(data);

Do you mean the above or other? apologies if I am wrong, not sure I understand completely what you are saying.
The Crazy Phoenix #10
Posted 18 July 2016 - 04:08 PM
When you read with rb, it's faster to store each char in a table and then uses table.concat. readAll is not a valid method in rb mode (according to the wiki).

local h = fs.open(file, "rb")
local t = {}
for b in h.read do  -- Read all bytes
	t[#t + 1] = string.char(b)
end
local dump = table.concat(t)  -- Concatenate the strings
local func, err = loadstring(dump)  -- Load the string
Edited on 18 July 2016 - 02:08 PM
DannySMc #11
Posted 18 July 2016 - 05:17 PM
When you read with rb, it's faster to store each char in a table and then uses table.concat. readAll is not a valid method in rb mode (according to the wiki).

local h = fs.open(file, "rb")
local t = {}
for b in h.read do -- Read all bytes
t[#t + 1] = string.char(B)/>
end
local dump = table.concat(t) -- Concatenate the strings
local func, err = loadstring(dump) -- Load the string

Interesting, will have a go when I am back, thanks.
Bomb Bloke #12
Posted 19 July 2016 - 03:32 AM
When you read with rb, it's faster to store each char in a table and then uses table.concat.

Surely it'd be faster to unpack to string.char()?:

local h, func, err = fs.open(file, "rb"), {}

for b in h.read do func[#func + 1] = b end

h.close()

func, err = loadstring( string.char( unpack( func ) ) )
Emma #13
Posted 19 July 2016 - 03:53 AM
–snip–

Quite so,
in fact, after running a bunch of benchmarks here are the average computation cycles over 10 seconds:
Bomb's character unpack: 128831.2
Table concatenation: 19178

Using string.char(unpack(func)) is about 6.5 times faster.
Edited on 19 July 2016 - 01:54 AM
Bomb Bloke #14
Posted 19 July 2016 - 04:51 AM
… for a certain string length. I'd expect the gap to widen as it gets longer.

There's a bit of a catch in that some versions of Lua (as used by some ComputerCraft emulators) don't like unpacking large amounts of values. Doesn't seem to be an issue in CC proper, though.