github.com/ganehag/gopher-lua@v0.0.0-20170625082135-754bc3935067/README.rst (about) 1 =============================================================================== 2 GopherLua: VM and compiler for Lua in Go. 3 =============================================================================== 4 5 .. image:: https://godoc.org/github.com/yuin/gopher-lua?status.svg 6 :target: http://godoc.org/github.com/yuin/gopher-lua 7 8 .. image:: https://travis-ci.org/yuin/gopher-lua.svg 9 :target: https://travis-ci.org/yuin/gopher-lua 10 11 .. image:: https://coveralls.io/repos/yuin/gopher-lua/badge.svg 12 :target: https://coveralls.io/r/yuin/gopher-lua 13 14 .. image:: https://badges.gitter.im/Join%20Chat.svg 15 :alt: Join the chat at https://gitter.im/yuin/gopher-lua 16 :target: https://gitter.im/yuin/gopher-lua?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge 17 18 | 19 20 21 GopherLua is a Lua5.1 VM and compiler written in Go. GopherLua has a same goal 22 with Lua: **Be a scripting language with extensible semantics** . It provides 23 Go APIs that allow you to easily embed a scripting language to your Go host 24 programs. 25 26 .. contents:: 27 :depth: 1 28 29 ---------------------------------------------------------------- 30 Design principle 31 ---------------------------------------------------------------- 32 33 - Be a scripting language with extensible semantics. 34 - User-friendly Go API 35 - The stack based API like the one used in the original Lua 36 implementation will cause a performance improvements in GopherLua 37 (It will reduce memory allocations and concrete type <-> interface conversions). 38 GopherLua API is **not** the stack based API. 39 GopherLua give preference to the user-friendliness over the performance. 40 41 ---------------------------------------------------------------- 42 How about performance? 43 ---------------------------------------------------------------- 44 GopherLua is not fast but not too slow, I think. 45 46 GopherLua has almost equivalent ( or little bit better ) performance as Python3 on micro benchmarks. 47 48 There are some benchmarks on the `wiki page <https://github.com/yuin/gopher-lua/wiki/Benchmarks>`_ . 49 50 ---------------------------------------------------------------- 51 Installation 52 ---------------------------------------------------------------- 53 54 .. code-block:: bash 55 56 go get github.com/yuin/gopher-lua 57 58 GopherLua supports >= Go1.6. 59 60 ---------------------------------------------------------------- 61 Usage 62 ---------------------------------------------------------------- 63 GopherLua APIs perform in much the same way as Lua, **but the stack is used only 64 for passing arguments and receiving returned values.** 65 66 GopherLua supports channel operations. See **"Goroutines"** section. 67 68 Import a package. 69 70 .. code-block:: go 71 72 import ( 73 "github.com/yuin/gopher-lua" 74 ) 75 76 Run scripts in the VM. 77 78 .. code-block:: go 79 80 L := lua.NewState() 81 defer L.Close() 82 if err := L.DoString(`print("hello")`); err != nil { 83 panic(err) 84 } 85 86 .. code-block:: go 87 88 L := lua.NewState() 89 defer L.Close() 90 if err := L.DoFile("hello.lua"); err != nil { 91 panic(err) 92 } 93 94 Refer to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ and `Go doc <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information. 95 96 Note that elements that are not commented in `Go doc <http://godoc.org/github.com/yuin/gopher-lua>`_ equivalent to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ , except GopherLua uses objects instead of Lua stack indices. 97 98 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 99 Data model 100 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 All data in a GopherLua program is an ``LValue`` . ``LValue`` is an interface 102 type that has following methods. 103 104 - ``String() string`` 105 - ``Type() LValueType`` 106 107 108 Objects implement an LValue interface are 109 110 ================ ========================= ================== ======================= 111 Type name Go type Type() value Constants 112 ================ ========================= ================== ======================= 113 ``LNilType`` (constants) ``LTNil`` ``LNil`` 114 ``LBool`` (constants) ``LTBool`` ``LTrue``, ``LFalse`` 115 ``LNumber`` float64 ``LTNumber`` ``-`` 116 ``LString`` string ``LTString`` ``-`` 117 ``LFunction`` struct pointer ``LTFunction`` ``-`` 118 ``LUserData`` struct pointer ``LTUserData`` ``-`` 119 ``LState`` struct pointer ``LTThread`` ``-`` 120 ``LTable`` struct pointer ``LTTable`` ``-`` 121 ``LChannel`` chan LValue ``LTChannel`` ``-`` 122 ================ ========================= ================== ======================= 123 124 You can test an object type in Go way(type assertion) or using a ``Type()`` value. 125 126 .. code-block:: go 127 128 lv := L.Get(-1) // get the value at the top of the stack 129 if str, ok := lv.(lua.LString); ok { 130 // lv is LString 131 fmt.Println(string(str)) 132 } 133 if lv.Type() != lua.LTString { 134 panic("string required.") 135 } 136 137 .. code-block:: go 138 139 lv := L.Get(-1) // get the value at the top of the stack 140 if tbl, ok := lv.(*lua.LTable); ok { 141 // lv is LTable 142 fmt.Println(L.ObjLen(tbl)) 143 } 144 145 Note that ``LBool`` , ``LNumber`` , ``LString`` is not a pointer. 146 147 To test ``LNilType`` and ``LBool``, You **must** use pre-defined constants. 148 149 .. code-block:: go 150 151 lv := L.Get(-1) // get the value at the top of the stack 152 153 if lv == lua.LTrue { // correct 154 } 155 156 if bl, ok := lv.(lua.LBool); ok && bool(bl) { // wrong 157 } 158 159 In Lua, both ``nil`` and ``false`` make a condition false. ``LVIsFalse`` and ``LVAsBool`` implement this specification. 160 161 .. code-block:: go 162 163 lv := L.Get(-1) // get the value at the top of the stack 164 if lua.LVIsFalse(lv) { // lv is nil or false 165 } 166 167 if lua.LVAsBool(lv) { // lv is neither nil nor false 168 } 169 170 Objects that based on go structs(``LFunction``. ``LUserData``, ``LTable``) 171 have some public methods and fields. You can use these methods and fields for 172 performance and debugging, but there are some limitations. 173 174 - Metatable does not work. 175 - No error handlings. 176 177 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 178 Callstack & Registry size 179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 180 Size of the callstack & registry is **fixed** for mainly performance. 181 You can change the default size of the callstack & registry. 182 183 .. code-block:: go 184 185 lua.RegistrySize = 1024 * 20 186 lua.CallStackSize = 1024 187 L := lua.NewState() 188 defer L.Close() 189 190 You can also create an LState object that has the callstack & registry size specified by ``Options`` . 191 192 .. code-block:: go 193 194 L := lua.NewState(lua.Options{ 195 CallStackSize: 120, 196 RegistrySize: 120*20, 197 }) 198 199 An LState object that has been created by ``*LState#NewThread()`` inherits the callstack & registry size from the parent LState object. 200 201 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 202 Miscellaneous lua.NewState options 203 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 204 - **Options.SkipOpenLibs bool(default false)** 205 - By default, GopherLua opens all built-in libraries when new LState is created. 206 - You can skip this behaviour by setting this to ``true`` . 207 - Using the various `OpenXXX(L *LState) int` functions you can open only those libraries that you require, for an example see below. 208 - **Options.IncludeGoStackTrace bool(default false)** 209 - By default, GopherLua does not show Go stack traces when panics occur. 210 - You can get Go stack traces by setting this to ``true`` . 211 212 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 213 API 214 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 215 216 Refer to `Lua Reference Manual <http://www.lua.org/manual/5.1/>`_ and `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information. 217 218 +++++++++++++++++++++++++++++++++++++++++ 219 Calling Go from Lua 220 +++++++++++++++++++++++++++++++++++++++++ 221 222 .. code-block:: go 223 224 func Double(L *lua.LState) int { 225 lv := L.ToInt(1) /* get argument */ 226 L.Push(lua.LNumber(lv * 2)) /* push result */ 227 return 1 /* number of results */ 228 } 229 230 func main() { 231 L := lua.NewState() 232 defer L.Close() 233 L.SetGlobal("double", L.NewFunction(Double)) /* Original lua_setglobal uses stack... */ 234 } 235 236 .. code-block:: lua 237 238 print(double(20)) -- > "40" 239 240 Any function registered with GopherLua is a ``lua.LGFunction``, defined in ``value.go`` 241 242 .. code-block:: go 243 244 type LGFunction func(*LState) int 245 246 Working with coroutines. 247 248 .. code-block:: go 249 250 co, _ := L.NewThread() /* create a new thread */ 251 fn := L.GetGlobal("coro").(*lua.LFunction) /* get function from lua */ 252 for { 253 st, err, values := L.Resume(co, fn) 254 if st == lua.ResumeError { 255 fmt.Println("yield break(error)") 256 fmt.Println(err.Error()) 257 break 258 } 259 260 for i, lv := range values { 261 fmt.Printf("%v : %v\n", i, lv) 262 } 263 264 if st == lua.ResumeOK { 265 fmt.Println("yield break(ok)") 266 break 267 } 268 } 269 270 +++++++++++++++++++++++++++++++++++++++++ 271 Opening a subset of builtin modules 272 +++++++++++++++++++++++++++++++++++++++++ 273 274 The following demonstrates how to open a subset of the built-in modules in Lua, say for example to avoid enabling modules with access to local files or system calls. 275 276 main.go 277 278 .. code-block:: go 279 280 func main() { 281 L := lua.NewState(lua.Options{SkipOpenLibs: true}) 282 defer L.Close() 283 for _, pair := range []struct { 284 n string 285 f lua.LGFunction 286 }{ 287 {lua.LoadLibName, lua.OpenPackage}, // Must be first 288 {lua.BaseLibName, lua.OpenBase}, 289 {lua.TabLibName, lua.OpenTable}, 290 } { 291 if err := L.CallByParam(lua.P{ 292 Fn: L.NewFunction(pair.f), 293 NRet: 0, 294 Protect: true, 295 }, lua.LString(pair.n)); err != nil { 296 panic(err) 297 } 298 } 299 if err := L.DoFile("main.lua"); err != nil { 300 panic(err) 301 } 302 } 303 304 +++++++++++++++++++++++++++++++++++++++++ 305 Creating a module by Go 306 +++++++++++++++++++++++++++++++++++++++++ 307 308 mymodule.go 309 310 .. code-block:: go 311 312 package mymodule 313 314 import ( 315 "github.com/yuin/gopher-lua" 316 ) 317 318 func Loader(L *lua.LState) int { 319 // register functions to the table 320 mod := L.SetFuncs(L.NewTable(), exports) 321 // register other stuff 322 L.SetField(mod, "name", lua.LString("value")) 323 324 // returns the module 325 L.Push(mod) 326 return 1 327 } 328 329 var exports = map[string]lua.LGFunction{ 330 "myfunc": myfunc, 331 } 332 333 func myfunc(L *lua.LState) int { 334 return 0 335 } 336 337 mymain.go 338 339 .. code-block:: go 340 341 package main 342 343 import ( 344 "./mymodule" 345 "github.com/yuin/gopher-lua" 346 ) 347 348 func main() { 349 L := lua.NewState() 350 defer L.Close() 351 L.PreloadModule("mymodule", mymodule.Loader) 352 if err := L.DoFile("main.lua"); err != nil { 353 panic(err) 354 } 355 } 356 357 main.lua 358 359 .. code-block:: lua 360 361 local m = require("mymodule") 362 m.myfunc() 363 print(m.name) 364 365 366 +++++++++++++++++++++++++++++++++++++++++ 367 Calling Lua from Go 368 +++++++++++++++++++++++++++++++++++++++++ 369 370 .. code-block:: go 371 372 L := lua.NewState() 373 defer L.Close() 374 if err := L.DoFile("double.lua"); err != nil { 375 panic(err) 376 } 377 if err := L.CallByParam(lua.P{ 378 Fn: L.GetGlobal("double"), 379 NRet: 1, 380 Protect: true, 381 }, lua.LNumber(10)); err != nil { 382 panic(err) 383 } 384 ret := L.Get(-1) // returned value 385 L.Pop(1) // remove received value 386 387 If ``Protect`` is false, GopherLua will panic instead of returning an ``error`` value. 388 389 +++++++++++++++++++++++++++++++++++++++++ 390 User-Defined types 391 +++++++++++++++++++++++++++++++++++++++++ 392 You can extend GopherLua with new types written in Go. 393 ``LUserData`` is provided for this purpose. 394 395 .. code-block:: go 396 397 type Person struct { 398 Name string 399 } 400 401 const luaPersonTypeName = "person" 402 403 // Registers my person type to given L. 404 func registerPersonType(L *lua.LState) { 405 mt := L.NewTypeMetatable(luaPersonTypeName) 406 L.SetGlobal("person", mt) 407 // static attributes 408 L.SetField(mt, "new", L.NewFunction(newPerson)) 409 // methods 410 L.SetField(mt, "__index", L.SetFuncs(L.NewTable(), personMethods)) 411 } 412 413 // Constructor 414 func newPerson(L *lua.LState) int { 415 person := &Person{L.CheckString(1)} 416 ud := L.NewUserData() 417 ud.Value = person 418 L.SetMetatable(ud, L.GetTypeMetatable(luaPersonTypeName)) 419 L.Push(ud) 420 return 1 421 } 422 423 // Checks whether the first lua argument is a *LUserData with *Person and returns this *Person. 424 func checkPerson(L *lua.LState) *Person { 425 ud := L.CheckUserData(1) 426 if v, ok := ud.Value.(*Person); ok { 427 return v 428 } 429 L.ArgError(1, "person expected") 430 return nil 431 } 432 433 var personMethods = map[string]lua.LGFunction{ 434 "name": personGetSetName, 435 } 436 437 // Getter and setter for the Person#Name 438 func personGetSetName(L *lua.LState) int { 439 p := checkPerson(L) 440 if L.GetTop() == 2 { 441 p.Name = L.CheckString(2) 442 return 0 443 } 444 L.Push(lua.LString(p.Name)) 445 return 1 446 } 447 448 func main() { 449 L := lua.NewState() 450 defer L.Close() 451 registerPersonType(L) 452 if err := L.DoString(` 453 p = person.new("Steeve") 454 print(p:name()) -- "Steeve" 455 p:name("Alice") 456 print(p:name()) -- "Alice" 457 `); err != nil { 458 panic(err) 459 } 460 } 461 462 +++++++++++++++++++++++++++++++++++++++++ 463 Terminating a running LState 464 +++++++++++++++++++++++++++++++++++++++++ 465 GopherLua supports the `Go Concurrency Patterns: Context <https://blog.golang.org/context>`_ . 466 467 468 .. code-block:: go 469 470 L := lua.NewState() 471 defer L.Close() 472 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) 473 defer cancel() 474 // set the context to our LState 475 L.SetContext(ctx) 476 err := L.DoString(` 477 local clock = os.clock 478 function sleep(n) -- seconds 479 local t0 = clock() 480 while clock() - t0 <= n do end 481 end 482 sleep(3) 483 `) 484 // err.Error() contains "context deadline exceeded" 485 486 With coroutines 487 488 .. code-block:: go 489 490 L := lua.NewState() 491 defer L.Close() 492 ctx, cancel := context.WithCancel(context.Background()) 493 L.SetContext(ctx) 494 defer cancel() 495 L.DoString(` 496 function coro() 497 local i = 0 498 while true do 499 coroutine.yield(i) 500 i = i+1 501 end 502 return i 503 end 504 `) 505 co, cocancel := L.NewThread() 506 defer cocancel() 507 fn := L.GetGlobal("coro").(*LFunction) 508 509 _, err, values := L.Resume(co, fn) // err is nil 510 511 cancel() // cancel the parent context 512 513 _, err, values = L.Resume(co, fn) // err is NOT nil : child context was canceled 514 515 **Note that using a context causes performance degradation.** 516 517 .. code-block:: 518 519 time ./glua-with-context.exe fib.lua 520 9227465 521 0.01s user 0.11s system 1% cpu 7.505 total 522 523 time ./glua-without-context.exe fib.lua 524 9227465 525 0.01s user 0.01s system 0% cpu 5.306 total 526 527 528 +++++++++++++++++++++++++++++++++++++++++ 529 Goroutines 530 +++++++++++++++++++++++++++++++++++++++++ 531 The ``LState`` is not goroutine-safe. It is recommended to use one LState per goroutine and communicate between goroutines by using channels. 532 533 Channels are represented by ``channel`` objects in GopherLua. And a ``channel`` table provides functions for performing channel operations. 534 535 Some objects can not be sent over channels due to having non-goroutine-safe objects inside itself. 536 537 - a thread(state) 538 - a function 539 - an userdata 540 - a table with a metatable 541 542 You **must not** send these objects from Go APIs to channels. 543 544 545 546 .. code-block:: go 547 548 func receiver(ch, quit chan lua.LValue) { 549 L := lua.NewState() 550 defer L.Close() 551 L.SetGlobal("ch", lua.LChannel(ch)) 552 L.SetGlobal("quit", lua.LChannel(quit)) 553 if err := L.DoString(` 554 local exit = false 555 while not exit do 556 channel.select( 557 {"|<-", ch, function(ok, v) 558 if not ok then 559 print("channel closed") 560 exit = true 561 else 562 print("received:", v) 563 end 564 end}, 565 {"|<-", quit, function(ok, v) 566 print("quit") 567 exit = true 568 end} 569 ) 570 end 571 `); err != nil { 572 panic(err) 573 } 574 } 575 576 func sender(ch, quit chan lua.LValue) { 577 L := lua.NewState() 578 defer L.Close() 579 L.SetGlobal("ch", lua.LChannel(ch)) 580 L.SetGlobal("quit", lua.LChannel(quit)) 581 if err := L.DoString(` 582 ch:send("1") 583 ch:send("2") 584 `); err != nil { 585 panic(err) 586 } 587 ch <- lua.LString("3") 588 quit <- lua.LTrue 589 } 590 591 func main() { 592 ch := make(chan lua.LValue) 593 quit := make(chan lua.LValue) 594 go receiver(ch, quit) 595 go sender(ch, quit) 596 time.Sleep(3 * time.Second) 597 } 598 599 ''''''''''''''' 600 Go API 601 ''''''''''''''' 602 603 ``ToChannel``, ``CheckChannel``, ``OptChannel`` are available. 604 605 Refer to `Go doc(LState methods) <http://godoc.org/github.com/yuin/gopher-lua>`_ for further information. 606 607 ''''''''''''''' 608 Lua API 609 ''''''''''''''' 610 611 - **channel.make([buf:int]) -> ch:channel** 612 - Create new channel that has a buffer size of ``buf``. By default, ``buf`` is 0. 613 614 - **channel.select(case:table [, case:table, case:table ...]) -> {index:int, recv:any, ok}** 615 - Same as the ``select`` statement in Go. It returns the index of the chosen case and, if that 616 case was a receive operation, the value received and a boolean indicating whether the channel has been closed. 617 - ``case`` is a table that outlined below. 618 - receiving: `{"|<-", ch:channel [, handler:func(ok, data:any)]}` 619 - sending: `{"<-|", ch:channel, data:any [, handler:func(data:any)]}` 620 - default: `{"default" [, handler:func()]}` 621 622 ``channel.select`` examples: 623 624 .. code-block:: lua 625 626 local idx, recv, ok = channel.select( 627 {"|<-", ch1}, 628 {"|<-", ch2} 629 ) 630 if not ok then 631 print("closed") 632 elseif idx == 1 then -- received from ch1 633 print(recv) 634 elseif idx == 2 then -- received from ch2 635 print(recv) 636 end 637 638 .. code-block:: lua 639 640 channel.select( 641 {"|<-", ch1, function(ok, data) 642 print(ok, data) 643 end}, 644 {"<-|", ch2, "value", function(data) 645 print(data) 646 end}, 647 {"default", function() 648 print("default action") 649 end} 650 ) 651 652 - **channel:send(data:any)** 653 - Send ``data`` over the channel. 654 - **channel:receive() -> ok:bool, data:any** 655 - Receive some data over the channel. 656 - **channel:close()** 657 - Close the channel. 658 659 '''''''''''''''''''''''''''''' 660 The LState pool pattern 661 '''''''''''''''''''''''''''''' 662 To create per-thread LState instances, You can use the ``sync.Pool`` like mechanism. 663 664 .. code-block:: go 665 666 type lStatePool struct { 667 m sync.Mutex 668 saved []*lua.LState 669 } 670 671 func (pl *lStatePool) Get() *lua.LState { 672 pl.m.Lock() 673 defer pl.m.Unlock() 674 n := len(pl.saved) 675 if n == 0 { 676 return pl.New() 677 } 678 x := pl.saved[n-1] 679 pl.saved = pl.saved[0 : n-1] 680 return x 681 } 682 683 func (pl *lStatePool) New() *lua.LState { 684 L := lua.NewState() 685 // setting the L up here. 686 // load scripts, set global variables, share channels, etc... 687 return L 688 } 689 690 func (pl *lStatePool) Put(L *lua.LState) { 691 pl.m.Lock() 692 defer pl.m.Unlock() 693 pl.saved = append(pl.saved, L) 694 } 695 696 func (pl *lStatePool) Shutdown() { 697 for _, L := range pl.saved { 698 L.Close() 699 } 700 } 701 702 // Global LState pool 703 var luaPool = &lStatePool{ 704 saved: make([]*lua.LState, 0, 4), 705 } 706 707 Now, you can get per-thread LState objects from the ``luaPool`` . 708 709 .. code-block:: go 710 711 func MyWorker() { 712 L := luaPool.Get() 713 defer luaPool.Put(L) 714 /* your code here */ 715 } 716 717 func main() { 718 defer luaPool.Shutdown() 719 go MyWorker() 720 go MyWorker() 721 /* etc... */ 722 } 723 724 725 ---------------------------------------------------------------- 726 Differences between Lua and GopherLua 727 ---------------------------------------------------------------- 728 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 729 Goroutines 730 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 731 732 - GopherLua supports channel operations. 733 - GopherLua has a type named ``channel``. 734 - The ``channel`` table provides functions for performing channel operations. 735 736 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 737 Unsupported functions 738 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 739 740 - ``string.dump`` 741 - ``os.setlocale`` 742 - ``lua_Debug.namewhat`` 743 - ``package.loadlib`` 744 - debug hooks 745 746 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 747 Miscellaneous notes 748 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 749 750 - ``collectgarbage`` does not take any arguments and runs the garbage collector for the entire Go program. 751 - ``file:setvbuf`` does not support a line buffering. 752 - Daylight saving time is not supported. 753 - GopherLua has a function to set an environment variable : ``os.setenv(name, value)`` 754 755 ---------------------------------------------------------------- 756 Standalone interpreter 757 ---------------------------------------------------------------- 758 Lua has an interpreter called ``lua`` . GopherLua has an interpreter called ``glua`` . 759 760 .. code-block:: bash 761 762 go get github.com/yuin/gopher-lua/cmd/glua 763 764 ``glua`` has same options as ``lua`` . 765 766 ---------------------------------------------------------------- 767 How to Contribute 768 ---------------------------------------------------------------- 769 See `Guidlines for contributors <https://github.com/yuin/gopher-lua/tree/master/.github/CONTRIBUTING.md>`_ . 770 771 ---------------------------------------------------------------- 772 Libraries for GopherLua 773 ---------------------------------------------------------------- 774 775 - `gopher-luar <https://github.com/layeh/gopher-luar>`_ : Custom type reflection for gopher-lua 776 - `gluamapper <https://github.com/yuin/gluamapper>`_ : Mapping a Lua table to a Go struct 777 - `gluare <https://github.com/yuin/gluare>`_ : Regular expressions for gopher-lua 778 - `gluahttp <https://github.com/cjoudrey/gluahttp>`_ : HTTP request module for gopher-lua 779 - `gopher-json <https://github.com/layeh/gopher-json>`_ : A simple JSON encoder/decoder for gopher-lua 780 - `gluayaml <https://github.com/kohkimakimoto/gluayaml>`_ : Yaml parser for gopher-lua 781 - `glua-lfs <https://github.com/layeh/gopher-lfs>`_ : Partially implements the luafilesystem module for gopher-lua 782 - `gluaurl <https://github.com/cjoudrey/gluaurl>`_ : A url parser/builder module for gopher-lua 783 - `gluahttpscrape <https://github.com/felipejfc/gluahttpscrape>`_ : A simple HTML scraper module for gopher-lua 784 - `gluaxmlpath <https://github.com/ailncode/gluaxmlpath>`_ : An xmlpath module for gopher-lua 785 786 ---------------------------------------------------------------- 787 Donation 788 ---------------------------------------------------------------- 789 790 BTC: 1NEDSyUmo4SMTDP83JJQSWi1MvQUGGNMZB 791 792 ---------------------------------------------------------------- 793 License 794 ---------------------------------------------------------------- 795 MIT 796 797 ---------------------------------------------------------------- 798 Author 799 ---------------------------------------------------------------- 800 Yusuke Inuzuka