Supported OS
Supported CPU
Each line is a new statement and default scope is global
a = 1 -- global variable
local b = 2 -- prepend with 'local' to bind to lexical scope
Standard standard C and Pascal like binary operators
e = a + b -- add
e = a - b -- subtract
e = a * b -- multiply
e = a % b -- modulus
e = a ^ b -- a to power b
e = a == b -- equality
e = a ~= b -- inequality
e = a < b -- less than
e = a > b -- greater than
e = a <= b -- less than equal
e = a >= b; -- greater than equal
e = "ss" .. "XX"-- string concatenation
Multiple assignment supported and multiple statements per line separated by ;
a, b = b, a -- this swaps the values of a and b
local c = 3; d = 4; -- multiple statements per line
-- define local variable e with no value bound to it
local e; -- ';' not necessary but OK.
Logical operators a bit different (nil and false is false everything else is true)
-- stops on false or nil , returns last evaluated value
e = a and b -- if a true then b else false
-- stops on true (not false or nil ), returns last evaluated value
e = a or b -- if a true then a else b
-- Logically invert
e = not a -- if a false then true else false
-- using and and or for conditional assignment
e = IAmNotDefined or 'So default value' -- result is the string
e = IamNotDefined and IamNotDefined() -- this does not crash
All values in Lua are first-class (stored in variables; passed as arguments; returned as results)
true
or false
.
nil
and false
counts as false everything else is true. number
double
(could be char
, short
, int
, float
). string
char
values.
'\0'
nil
)
'Some\n "blah" string\' don't need to escape\''
"Some\n 'blah' string\" don't need to escape \""
Literal strings
local someString = [[
first new line is ignored
this is a new line but this \n is not
]]
local anotherString = [=[the string does not end here]]
[[some text]]
the string ends here]=]
Indexing
a = t[1] -- access array element 1
a = t['blah'] -- access element string key 'blah'
a = t.blah -- syntactic sugar for t['blah']
Constructors
-- empty table
t = {}
-- simple array elements are t[1], t[2], t[3]
t = {"blah", 1, true}
-- simple map elements t['blah'], t['foo']
t = {blah = 5, foo=true}
-- Explicit keys
t = {['blah'] = 5, [100] = true}
-- mixed elements at t[1], t[2], t[100], t.foo t.bar
t =
{ 'alpha', 'bravo'; -- element separator either , or ;
foo = 5; bar=4,
[100] = false,
}
Insertion and deletion
t.foo = 5 -- Insert value 5 at key foo
t.foo = nil -- Delete key foo from table
Function definition
function (arg1, arg2) return arg1 + arg2 end
function
(a1, a2, ...)
end
return
returns functions resultGlobal function assignment
-- This is syntax sugar
function arb (arg1, arg2) return arg1 + arg2 end
-- for this assignment of a function to the global 'arb'
arb = function (arg1, arg2) return arg1 + arg2 end
Local function assignment
-- This is syntax sugar
local function arb (arg1, arg2) return arg1 + arg2 end
-- for this assignment of a function to the local 'arb'
local arb = function (arg1, arg2) return arg1 + arg2 end
Table function insertion
-- This is syntax sugar
function t.arb (arg1, arg2) return arg1 + arg2 end
-- for this insertion of a function into table t at key arb
t['arb'] = function (arg1, arg2) return arg1 + arg2 end
Table function insertion with implicit self
-- This is syntax sugar
function t:arb (arg1, arg2)
return arg1 + arg2 + self[1]
end
-- for this insertion of a function into table t at key arb
-- and explicit self parameter
t['arb'] = function (self, arg1, arg2)
return arg1 + arg2 + self[1]
end
Function called by applying argument list to function value
local arb = function (a) return a + a end
local x = arb(2) -- x is 4
Calling function implicitly passing self
local t = {
arb = function(self, a)
return self.x + a
end;
x = 1; -- trailing delimiter is fine
}
-- This is syntax sugar for
local b = t:arb(2)
-- this lookup of arb in t and passing it t and 2
local c = t.arb(t, 2)
Parentheses optional when calling function with literal string
-- This is syntax sugar
print "blah"
-- for this
print("blah")
Parentheses optional when calling function with table constructor
-- This is syntax sugar
ipairs {1,2,3,4}
-- for this
ipairs ({1,2,3,4})
Function return types are dynamic
function arb(x)
if x == 1 then return 3,4
elseif x == 'j' then return 'bob',8
elseif x == 'm' then return nil,'s'
elseif x == 2 then return 4
else
-- returning nothing
end
end
a,b = arb(1) -- a == 3, b == 4
a,b = arb('j') -- a == 'bob', b == 8
a,b = arb('m') -- a == nil, b == 's'
a,b = arb(2) -- a == 4, b == nil
a,b = arb(3) -- a == nil, b == nil
Functions support closures
local function makeCounter()
local count = -1 -- local variable
return function () -- return the function
-- capture `count` updating on each invocation
return count = count + 1
end
end
local c1 = makeCounter()
local _1, _2, _3 = c1(), c1(), c1() -- _1 == 0, _2 == 1, _3 == 2
local c2 = makeCounter()
_1, _2, _3 = c2(), c1(), c2() -- _1 == 0, _2 == 4, _3 == 1
Functions support tail call recursion
function fib(n)
local function _fib(fn2, fn1, at)
if at == n then
return fn1 + fn2
else
-- calls it self recursively as a tail call
-- so it will reuse the same stack frame
return _fib(fn1, fn1 + fn2, at+1)
end
end
if n <= 0 then return 0
elseif n == 1 then return 1
else return _fib(0, 1, 2) end
end
-- no stack overflow
-- prints : n4 = 2 n8 = 13 n1000 = 2.6863810024485e+208 n10000 = 1.#INF
print ('n4 = ' .. fib(4) .. ' n8 = '.. fib(8) .. ' n1000 = ' .. fib(1000)
.. ' n10000 = ' .. fib(10000))
Introduces local scope
do
local onlyVisibleHere = 5
end
if then else
Conditional branching with each branch introducing a local scope.
if a == b then -- start if branch
e = 2
elseif a == c then -- optional else if branch
e = 3
else -- optional else branch
e = 4
end -- required terminator
If condition is true then repeatedly execute block until false
local a,b = 1,5
while a < b do
a = a + 1 -- executes 4 times
end
repeat
Execute block and if condition is true repeat until false
local a,b = 4,5
repeat
a = a + 1 -- executes 2 times
until a == b
break
Forces enclosing looping structure to terminate immediately
local a = 1
while true do
break
a = a + 1 -- never executes a remains 1
end
Repeat the block until initial value passes limit incrementing by optional step size. Default step size is 1.
local a = 1
for u=1,10 do
a = u -- executes 10 times (at end a == 10)
end
for u=10,1,-1 do
a = u -- executes 10 times (at end a == 1)
end
The generic for loop works over functions called iterators. On each iteration, the iterator function is called to produce a new value, stopping when this new value is nil.
local a = 1
for k,v in ipairs {0,1,2,3,4,5,6,7,8,9} do
a = k + v -- executes 10 times (at end a == 10 + 9)
end
setmetatable(t, mt)
function__add
, __sub
etc.__eq
, __lt
and __le
.__index
and __newindex
__call
__gc
must be set from Cn
local mtFibber = {}
function makeFibber(n)
local f = {n = n}
setmetatable(f, mtFibber)
return f
end
do
function mtFibber:__call()
local n = math.max(self.n,0)
local function _fib(fn2, fn1, at)
if at == n then
return fn1 + fn2
else
return _fib(fn1, fn1 + fn2, at+1)
end
end
if n <= 0 then return 0
elseif n == 1 then return 1
else return _fib(0, 1, 2) end
end
function mtFibber.__add(lhs, rhs) return makeFibber(lhs.n + rhs.n) end
function mtFibber.__sub(lhs, rhs) return makeFibber(lhs.n - rhs.n) end
function mtFibber:__newindex(k,v) assert(false, "can't add members") end
end
local f1 = makeFibber(10)
local f2 = makeFibber(5)
local f3 = makeFibber(100)
local f4 = (f3 + f2 - f1)
-- The 95th fibonacci is 3.194043463499e+019
print ("The " .. f4.n .. "nth fibonacci number is " .. f4())
IUP Dialog
require "iuplua"
require "iupluacontrols"
local label
local text = ""
local function onText(self)
text = string.upper(self.value)
end
local function modifyLabel(self)
if label then
label.title = text
end
end
dlg = iup.dialog
{
iup.vbox
{
iup.label{title = 'A silly little dialog', map_cb = function(self) label = self end},
iup.vbox
{
iup.hbox
{
iup.label{title='Write text', size="80"},
iup.text{size="80", valuechanged_cb = onText}
;margin="0", gap="10"
};
iup.hbox
{
iup.button{title="Ok",size="40", action = modifyLabel},
iup.button{title="Cancel",size="40" , action = function () return iup.CLOSE end}
;margin="0", gap="10"
};
}
;margin="5x5", gap="5"
}
;title="Some dialog", resize="NO"
}
dlg:popup()
local cosmo = require "cosmo"
mycards = { {rank="Ace", suit="Spades"}
, {rank="Queen", suit="Diamonds"}
, {rank="10", suit="Hearts"}
}
template = "$do_cards[[$rank of $suit, ]]"
-- prints Ace of Spades, Queen of Diamonds, 10 of Hearts,
print (cosmo.fill(template, {do_cards = mycards}))
local List = require 'pl.List'
local func = require 'pl.func'
print (List{10,20,30}:map(_1+1):reduce '+') -- prints 63
class = require 'pl.class'
class.Animal()
function Animal:_init(name)
self.name = name
end
function Animal:__tostring()
return self.name..': '..self:speak()
end
class.Dog(Animal)
function Dog:speak()
return 'bark'
end
class.Cat(Animal)
function Cat:_init(name,breed)
self:super(name) -- must init base!
self.breed = breed
end
function Cat:speak()
return 'meow'
end
fido = Dog('Fido')
felix = Cat('Felix','Tabby')
print(fido,felix) -- Fido: bark Felix: meow
print(felix:is_a(Animal) -- true
print(felix:is_a(Dog)) -- false
print(felix:is_a(Cat)) -- true
-{extension "clist"}
-- integers from 2 to 50, by steps of 2:
x = { i for i = 2, 50, 2 }
-- the same, obtained by filtering over all integers <= 50:
y = { i for i = 1, 50 if i%2==0 }
-{extension 'match'}
match { { 'o', 'k', '!' } } with
| { t } -> match t with
| { a, b } -> print 'KO'
| { a, b, ... } -> print (a..b)
| _ -> print 'KO'
end
| _ -> print 'KO'
end
FLiDataCompiler
{INCLUDE_PCH = [[#include "fliModelsPCH.h"]];
INCLUDE_LIB = [[#include "../fliModelsLib.h"]];
EXPORT_DECL = [[fliMODELS_API]];
INCLUDES = {"dmlGoalState.dsd", "dmlGoalChildrenConstraint.dsd", "dmlTrigger.dmd"};
[[ @brief Goals are a hierarchical way to define what an entity is required to achieve.
]];
MODEL = {"fli::act::DGoal";
[[@brief String used to categorize the goal with categories seperated by / also used to identify the goal]];
{"Category", {"string", 1}};
[[@brief The current active state of the goal]];
{"State", {"EGoalState", 2, default='GOAL_INACTIVE'}};
[[@brief Constrain how the goal's children become active when it is active]];
{"ChildrenConstraint", {"EGoalChildrenConstraint", 3, default="GOAL_CHILDREN_ACTIVE_CONCURRENTLY"}};
[[@brief Child goals]];
{"Children", {"array<DGoal>", 4}};
...
...
[[@brief The number of times the goal has passed]];
{"PassedCount", {"int32", 9, set=false}};
[[@brief The number of times the goal has failed]];
{"FailedCount", {"int32", 10, set=false}};
};
};
fli_data.ScopeModelCreate()
local DoNotRegister = true -- Do not register with fli::data::CManager
-----------------------------------------------------
-- Scenario world
-----------------------------------------------------
-- Define the whole world for the scenario defining which extensions the world has as well as all the entities which are
-- present in the world.
return Root(fli__ent__DWorld("World"), DoNotRegister)
{
Extensions =
{
-- Extension that defines information related to the scenario but not a specific entity
fli__ent__DScenarioInfo
{
Name = "Tutorial_03_SimpleVehicle";
FocusEntity = RefModel("World:Entities.1");
};
};
Entities =
{
Import(assert(RelToData "FLiTutorials/Tutorial_03_SimpleVehicle/Scripts/Terrain.lua"))
{
InInitialTimeOfDay = 16 * 60 * 60;
};
Import(assert(RelToData "FLiTutorials/Tutorial_03_SimpleVehicle/Scripts/SimpleEntityOfTutorial2.lua"))
{
InName = "My Imported Entity";
InPhysicsEnableDebugDrawing = true;
InPosition = {x=-100;y=50;z=0;};
InOrientation = QuaternionToTable( OrientFromYPRd(0, 0, 0) );
InVisualColour = {r=0, g=1, b=0, a=1};
};
Import(assert(RelToData "FLiTutorials/Tutorial_03_SimpleVehicle/Scripts/SimpleEntityOfTutorial2.lua"))
{
InName = "My Second Imported Entity";
InPhysicsEnableDebugDrawing = true;
InPosition = {x=-100;y=50;z=10;};
InOrientation = QuaternionToTable( OrientFromYPRd(DEG_TO_RAD(60), 0, 0) );
InVisualColour = {r=0, g=1, b=1, a=1};
};
Import(assert(RelToData "FLiTutorials/Tutorial_03_SimpleVehicle/Scripts/SimpleEntityOfTutorial2.lua"))
{
InName = "My Third Imported Entity";
InPhysicsEnableDebugDrawing = true;
InPosition = {x=-110;y=50;z=10;};
InOrientation = QuaternionToTable( OrientFromYPRd(0, 0, DEG_TO_RAD(30)) );
InVisualColour = {r=1, g=0, b=1, a=0.5};
};
};
}
Comments