Lua is a simple, yet powerful scripting language. This part is meant as a quick introduction to Lua for programmers familiar with languages derived from C-like syntax. It is a very condensed and simplified view on the language, just to start over. It does not cover all details and features. For complete reference, please read this section. You can also find a lot of information on the web, as well as buy books on Lua.
foo = 5 bar = foo * foo
ingredients = { [ "Potassium" ] = "K", [ "Carbon" ] = "C", [ "Nitrogen" ] = "N" }If you omit the keys, a map with a sequence of integer keys starting at 1 is constructed. This is used to emulate arrays:
workDays = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" } thursday = workDays [ 4 ]
or and < > <= >= ~= == .. + - * / %For C programmers: or, and, ~= are equivalents of ||, &&, !=. The .. (two dots) operators is for string concatenation:
foobar = "foo" .. "bar";
not # -For C programmers: not is equivalent to !, # is the string length operator.
do statements end -- a block statement while exp do statements end -- 'while' loop statement for spec do statements end -- 'for' loop statementThere is however a couple of exceptions:
repeat statements until exp -- like 'do .. while' C statement if exp then statements end -- a simple form of 'if' statement, see below for more complex ones function name ( args ) statements end -- a function definition
if exp then statements elseif exp then statements elseif exp then statements ... else statements end
for var = start, end, step do statements endThe iteration continues until var exceeds end. The step value is optional (by default 1).
for vars in generator do statements endThe generator expression is a more complex subject (please look here for complete understanding). For now, it suffices to know some common usages. To iterate over Lua array (associative table with integer keys), write:
for key, value in ipairs ( arrayName ) do statements -- here 'key' and 'value' variables are defined endTo iterate over generic associative table (with non-integer or random keys) in unspecified order, use the following:
for key, value in pairs ( arrayName ) do statements -- here 'key' and 'value' variables are defined endAs you can see, there can be multiple variables specified in this form of the statement. However, the second one ('value') can be omitted if you need only keys.
Another form is WinGDB-specific and is used to iterate over values of returned DTE arrays. For example, this code snippet prints names of all projects in Visual Studio solution:
for hProj in std.items ( vs:getSolution():getProjects() ) do vs:println ( hProj:getName() ) end
Use . to access static fields and methods, as the 'items' one. It can be thought as a static method defined inside 'std' namespace ('std' namespace is provided by WinGDB).
Use : to access non-static fields and methods of the object. The 'vs' variable is a global variable allowing access to Visual Studio functionality. It holds an object which represents the whole Visual Studio instance. You can query for various components of it, through method calls.
'getSolution' and 'getProjects' are methods returning current solution and array of projects, respectively. 'getName' is a method of the project object returning a string-typed project identifier.
function MyFunction ( a, b ) local c = a * b; return a + b + c; end;Local variables are declared using the local keyword. They "shadow" possible variables with same names from outside scopes.
arr = { "foo", "bar", "baz" } table.sort ( arr, function ( a, b ) return a < b end )You can even return functions and use closures, but this topic is too advanced to be shown here.
function right ( a, b ) return a * b; end function wrong ( a, b ) -- this function will not compile return a * b; vsu.println ( "unreachable code" ); endYou can enclose return inside do .. end block to overcome this limitation.
text = [[ class $Name { public: $Name(); ~$Name(); private: $Type m_array [ $Size ]; }; ]]The result is formally the same as with regular string constant in quotes. However, line breaks and formatting are preserved. Only when a line break occurs immediately after [[, this line break is ignored. You can place e.g. blocks of code inside such constant. If your code contains ]] token, you can use alternative delimiters like this:
text = [=[ This is a text containing ]]. ]=]You can insert arbitrary number of additional = characters, as long as their number match in the opening and closing token.
logFile = io.open ( "d:\\dv\\logs\\log.txt", "w" ); if logFile then logFile:write ( "test output\n" ) logFile:close(); end;The write method can accept multiple arguments, being strings or numbers.
cfgFile, errorMsg = io.open ( "d:\\dv\\cfg\\cfg.txt", "r" ); if cfgFile then contents = cfgFile:read ( "*a" ); cfgFile:close(); else vsu.println ( errorMsg ); end;The read method accepts format strings as arguments. The "*a" format reads entire file contents to a string. No arguments or "*l" reads single line. There are other formats also, please look into the language reference section for more info.
lineTable = {} for lineText in io.lines ( "d:\\dv\\cfg\\cfg.txt" ) do table.insert ( lineTable, lineText ) end; for index, value in ipairs ( lineTable ) do vs:println ( value ); end;
band ( op1, op2 [, op3 ... ] ) -- bitwise and of two or more values bnot ( x ) -- bitwise not bor ( op1, op2 [, op3 ... ] ) -- bitwise or of two or more values bxor ( op1, op2 [, op3 ... ] ) -- bitwise xor of two or more values arshift ( x, disp ) -- arithmetic (sign-preserving) shift to the right rshift ( x, disp ) -- logic (zero-padding) shift to the right lshift ( x, disp ) -- shift to the left lrotate ( x, disp ) -- rotate to the left rrotate ( x, disp ) -- rotate to the right
text = "The White Zone is for loading and unloading only." iFirst, iLast = string.find ( text, "White", 1, true ) if iFirst then vs:println ( "first char=" .. iFirst .. ", last char=" .. iLast ); end;Caution: Lua has a unusual (for C programmers) convention about string indices. They start at 1 and the end index is inclusive. Hence, iFirst in the above example will be equal to 5, and iLast to 9. Third argument specifies starting position and fourth is a boolean specifying type of the search (true means substring search).
text = "Please fill out the 27B/6 form!" iFirst, iLast, sig1, sig2 = string.find ( text, "([0-9]+[A-Z])/([0-9]+)", 1, false ) if iFirst then vs:println ( "first char=" .. iFirst .. ", last char=" .. iLast .. ", sig1=" .. sig1 .. ", sig2=" .. sig2 ); end;The patterns are simplified regexes, according to the description in the language reference. Multi-value assignment is used to retrieve resulting range and captured supbatterns (if any specified). So, in the above example, sig1 will be equal to "27B" and sig2 to "6".
for i, v in ipairs ( myList ) do text = string.format ( "The value at index %d is %s.", i, v ); vs:println ( text ); end;string.format accepts patterns is the same form as printf function in C.
std.try ( function() -- this is the "try" block contents -- 'error' throws an exception error ( "Error object, can (but need not) be string", 0 ); end, function ( hError ) -- "catch" section, handle the error object passed as hError variable vsu.println ( hError ) end );
Here, std.try accepts two unnamed (lambda) functions. The first one corresponds to try block contents in C++. The second one is an equivalent of a catch section. error acts as throw. The mechanism is not selective, there is no way to catch specific exceptions. Hence there can be only one catching function. But you can examine the contents of the exception object and perform different actions inside it. The only real limitation is that you can't directly cause a return from enclosing function typing return in exception handler, as it is a function on its own.
Lua can add location information to the exception object being a string. To prevent that, use 0 as the second parameter in error. Alternatively you can omit it and Lua will prepend a file name and line number of the error call to the message.