Jump tables with loadstring and dostring

Thalassicus

Bytes and Nibblers
Joined
Nov 9, 2005
Messages
11,057
Location
Texas
I'm trying to learn how to use loadstring and dostring to execute code, but having difficulty understanding this part of the reference manual. I'm starting with a very simple operation:

local test = city:IsRazing();

I've tried replacing this operation (which works correctly) with each of the ones below, and all produce the generic nil error:

local test = dostring("return city:IsRazing()");
local test = dostring("city:IsRazing()");
local test = loadstring("return city:IsRazing()");
local test = loadstring("city:IsRazing()");

What's the correct syntax? I've also tried adding assertions and other things indicated in the reference manual.

The reason I ask is because if I understand correctly, either dostring or loadstring are how to implement an externally-stored jump table in Lua, which is what I need.
 
Figured it out... didn't need loadstring or dostring at all, Lua automatically understands what you're doing with simply () on the end.

If you created some XML file named TestXML (to use as a jump table with function names) you access it like this:

Code:
for city in pPlayer:Cities() do
  cityID = city:GetID();
  testValue[cityID] = 1;
  
  -- retrieve function and weight from jump table stored with XML
[B]  for row in GameInfo.TestXML() do
    if city[row.Type](city) then
      testValue[cityID] = testValue[cityID] * row.Value;
    end;
  end[/B]
 
Curious about your first problem: Did you check the error message? What was it?
 
Well, how I understand it is if the string is incorrect it becomes 'nil' when processed by loadstring and dostring. Then it tries to run a nil as a function, which doesn't work so it complains. :)

The error message is just something along the lines of "attempt to call a nil."
 
Not to be a contrarian, but loadstring works fine for me. Here's some mockup code I wrote just to make sure it was a viable option.
Code:
local filename = "FEATURE_CRATER";
include (filename);
local className = "FeatureCrater";
local s = loadstring("f = "..className..":new()");
s();
print(f:CanBe(10,5));
Basically what I was testing is if I could programmatically load lua files when I retrieve the function name from the database (essentially like your jump tables). What I was doing doesn't really matter, though. What matters here is that f.CanBe ran properly, which meant that loadstring worked.

The thing to keep in mind is that loadstring operates at a global level. Any variable you use in there will be global, not, for instance, a local variable you define before using it.
 
The thing to keep in mind is that loadstring operates at a global level. Any variable you use in there will be global, not, for instance, a local variable you define before using it.
You mean local variables cant be used as arguments for loadstring function?
i tried loadstring once and IIRC fire tuner said that loadstring was not found or something like this...
 
Any variable you use in the string portion, such as "f" above, is going to be a global variable.

This will not work:
Code:
local filename = "FEATURE_CRATER";
include (filename);
local className = "FeatureCrater";
local s = loadstring("f = className:new()");
s();
print(f:CanBe(10,5));
However, this will work:
Code:
local filename = "FEATURE_CRATER";
include (filename);
local className = "FeatureCrater";
local s = loadstring("f = "..className..":new()");
s();
print(f:CanBe(10,5));
The local variable className works properly, because it is evaluated for its value to add to the string, rather than being used as part of the string to be loaded. On the global level, className is nil, and you'd get errors stating such.
 
Maybe the tuner's Lua implementation is more restrictive?
 
Any variable you use in the string portion, such as "f" above, is going to be a global variable.

This will not work:
Code:
local filename = "FEATURE_CRATER";
include (filename);
local className = "FeatureCrater";
local s = loadstring("f = className:new()");
s();
print(f:CanBe(10,5));
However, this will work:
Code:
local filename = "FEATURE_CRATER";
include (filename);
local className = "FeatureCrater";
local s = loadstring("f = "..className..":new()");
s();
print(f:CanBe(10,5));
The local variable className works properly, because it is evaluated for its value to add to the string, rather than being used as part of the string to be loaded. On the global level, className is nil, and you'd get errors stating such.

Okay, so I ran into a problem today where this would be helpful. I have a long table called BuildingStats where each value in the table is code to execute, and I would like to export it to XML for better modularity.

XML
Code:
<GameData>
  . . .
  <BuildingStats>
    <Row>
      <Type>Name</Type>
      <Value>(not bExcludeName)</Value>
    </Row>
	. . .

Lua
Code:
function GetHelpTextForBuilding(iBuildingID, bExcludeName, bExcludeHeader, bNoMaintenance)
  . . .
  for row in GameInfo.BuildingStats() do
    local statType = row.Type
    local statValue = loadstring(row.Value)
    statValue()
    . . .

This gives an error that loadstring is nil. How would I modify it to work as indicated in the first quote?
 
I don't know where JeBuS27 used it but from my tests, loadstring simply doesn't exist in Civ5 Lua except in the main state. So unless you load your mod files from the mainstate, which isn't possible without using firetuner afaik, you can't access it. You definitely can't access it from Lua contexts created with LoadNewContext
 
Back
Top Bottom