Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Composite and Lua Chris Anderson Terry Knowlton

Slide 3

Slide 3 text

Lua Small scripting language (20K lines, under 275KB) Very fast Embeddable

Slide 4

Slide 4 text

Goal Add Lua support to Composite

Slide 5

Slide 5 text

Why?

Slide 6

Slide 6 text

Configuration files Use a more modern and pleasant programming language For science!

Slide 7

Slide 7 text

Step 1 Statically compile Lua

Slide 8

Slide 8 text

Lua provides different build targets, so we adapted the simplest one that used the fewest dependencies

Slide 9

Slide 9 text

We then checked external dependences with nm. And found some (most notably, the math library).

Slide 10

Slide 10 text

Step 2 Compile Lua in Composite

Slide 11

Slide 11 text

We basically took the Lua source in its entirety and added it to Composite, for completeness and ease of upgrading later on.

Slide 12

Slide 12 text

Composite provides diet libc, so we linked against that to resolve our dependency issue

Slide 13

Slide 13 text

And after some makefile magic, we managed to output a lua_lang.o file that contained the statically compiled Lua libraries, ready to be embedded into C & Composite.

Slide 14

Slide 14 text

Hooray!

Slide 15

Slide 15 text

Step 3 Get Lua code working in Composite

Slide 16

Slide 16 text

Took it slowly to see what we could get working.

Slide 17

Slide 17 text

First, just made a dummy component that included the Lua headers and initialized the Lua stack.

Slide 18

Slide 18 text

Then, we were able to execute Lua code from a string in our component.

Slide 19

Slide 19 text

lua_State *L = luaL_newstate(); printc("Initialized Lua state”); luaL_dostring(L, "return 'Executing Lua inline'"); const char *str = lua_tostring(L, -1); printc("Lua returned value is %s", str); === Initialized Lua state === Lua returned value is ‘Executing Lua inline’

Slide 20

Slide 20 text

We can load values from a configuration file

Slide 21

Slide 21 text

// tests loading configuration from a file // loads the file, then executes it, which converts the variables // in the file to lua parsable data if (luaL_loadfile(L, "config.txt") || lua_pcall(L, 0, 0, 0)){ printc("error %s", lua_tostring(L, -1)); } lua_getglobal(L, "width"); int width = lua_tonumber(L, -1); printc("Width is %d\n", width); // config.txt -- sample config width = 200 height = 500

Slide 22

Slide 22 text

And execute Lua code from a script file

Slide 23

Slide 23 text

-- file 'foo.lua' function fib(n) if n < 2 then return n else return fib(n-1) + fib(n-2) end end

Slide 24

Slide 24 text

if (luaL_loadfile(L, "foo.lua") || lua_pcall(L, 0, 0, 0)){ // if either call fails, will return non-zero error code and print // it out here printc("error %s", lua_tostring(L, -1)); } // loads the fib function lua_getglobal(L, "fib"); // pushes param onto lua stack int fib_num = 20 lua_pushnumber(L,fib_num); // executes function into lua state lua_pcall(L,1,1,0); int result = (int)lua_tonumber(L, -1); printc("Fib of %d is %d", fib_num, result); === Fib of 20 is 6765

Slide 25

Slide 25 text

We did some testing with the Lua garbage collector

Slide 26

Slide 26 text

list = nil function linked_list(n) for i=1,n do list = {next = list, value = 'foobar'} end end function clear_list() list = nil end [ 1068.108374] Create 40000 nodes [ 1068.108374] Loop 1 [ 1068.108379] Garbage 2816kb [ 1068.108383] Loop 2 [ 1068.130174] Garbage 4893kb [ 1068.152191] Loop 3 [ 1068.152196] Garbage 2816kb [ 1068.163271] Loop 4 [ 1068.163275] Garbage 5283kb

Slide 27

Slide 27 text

We then implemented a key/value store based on the Lua stack

Slide 28

Slide 28 text

Powerful and easy to use through the C API. Lua is dynamically typed so a mix of data types can be stored in the same table. These tables exist within the Lua state.

Slide 29

Slide 29 text

// Store a string value in the specified table void luakv_putstring_bytable (char *key, char *value, char *table_name) { lua_getglobal(L, table_name); if(!lua_istable(L, -1)) { create_tablespace(table_name); } lua_pushstring(L, key); lua_pushstring(L, value); lua_settable(L, -3); } // Creates a table on the lua_State object for general use. void create_tablespace (char *table_name) { // Create the new table and assign it to global name *table_name lua_newtable(L); lua_setglobal(L, table_name); // Put the newly created table on top of the stack lua_getglobal(L, table_name); }

Slide 30

Slide 30 text

=== Trying out some keyval operations === Starting lua keyvalue storage test. New Lua state has been set. === tablespace didn't exist so try to create === Attempting to create new lua table with table_name=DEFAULT === trying to getString before fields are entered. received (null) === Put string of value1 into the default table at key1 === Retrieved the value at key1, return was: value1 === Put number value of 2 into the default table at key2 === pull from the table key2: 2 === Attempting to create new lua table with table_name=TABLE2 === Placed key3=value3 and key4=4 into TABLE2 === attempting to retrieve TABLE2 values from DEFAULT table === should have no values returned, retrieved key3=(null) and key4=0 === should now have returned values from table 2 key3=value3 and key4=4 === stored key3=default_value3 in default table === Pulled key3 from both tables. DEFAULT=default_value3 and TABLE2=value3 === lua_state has been closed

Slide 31

Slide 31 text

Future work

Slide 32

Slide 32 text

Export Lua as a usable component, using the cbuf or torrent interface to deal with sharing memory Create a framework to load and parse configuration files Continue testing Lua functions and third party libraries for compatibility

Slide 33

Slide 33 text

github.com/gwu-composite-lua/