Lua
This package provides a #lang implementation of the Lua programming language. It is still a work in progress, but much of the core language is supported already.
1 Calling Lua from Racket
1.1 Requiring Modules
Lua modules can be imported directly from Racket. Every Lua module provides a list called #%chunk which represents the set of return values of that module. For example, if you save the following program to a file named "add1.lua":
#lang lua function add1(x) return 1 + x end return {add1 = add1}
You can use it from Racket like so:
(require lua/value "add1.lua") (define add1 (table-ref (car #%chunk) #"add1")) (add1 5)
1.2 Evaluating Code at Runtime
You can run Lua code at runtime using racket/sandbox. For example:
> (require racket/sandbox) > ((make-module-evaluator "#lang lua\nreturn 42") '#%chunk) '(42)
> ((make-module-evaluator "#lang lua\nreturn 42, 43") '#%chunk) '(42 43)
>
> (define dangerous-prog (string-append "#lang lua\n" "\n" "return io.input('/etc/passwd'):read('a')")) > ((make-module-evaluator dangerous-prog) '#%chunk) open-input-file: `read' access denied for /etc/passwd
> (define chunk (parameterize ([sandbox-path-permissions '((read #rx#".*"))]) ((make-module-evaluator dangerous-prog) '#%chunk))) > (subbytes (car chunk) 0 5) #"root:"
2 Calling Racket from Lua
Lua modules can access values from racket/base by indexing into the racket global. This is only allowed when the value of current-racket-imports-enabled? is #t.
#lang lua local list = racket.list print(list(1, 2, 3))
You can also alter the global environment in any way you like via the current-global-environment parameter.
3 Differences from Lua
3.1 Chunks
Chunks may return multiple values, but everything after the first value is discarded when the results get bound to #%chunk.
3.2 The goto Statement and Labels
Labels are lexically scoped so the goto statement cannot jump to labels that have not yet been defined at the time the statement is executed or that are outside its scope.
3.3 Values
Integers are backed by regular Racket integer? values, so they do not overflow.
4 REPL
You can run a Lua REPL by loading the lua/repl module:
racket -l lua/repl -i |
Note that unlike a typical REPL, since lua is statement oriented, you must return values for them to be printed. Multi-line statements can be entered by bracketing them with :{ and :}. For example:
> :{ |
| do |
| local x = 42 |
| print(x) |
| end |
| :} |
42 |
Individual local declarations at the top level have no effect.
5 Reference
5.1 Values
(require lua/value) | package: lua-lib |
procedure
(~lua-bytes v) → bytes?
v : lua-value/c
procedure
v : lua-value/c
procedure
(make-table v ...) → table?
v : (or/c lua-value/c (cons/c lua-value/c lua-value/c))
> (require lua/value) > (make-table 1 2 nil 3 (cons #"a" #"b")) (make-table 1 2 nil 3 '(#"a" . #"b"))
procedure
(table-ref t k [default-proc]) → lua-value/c
t : table? k : lua-value/c default-proc : (-> lua-value/c) = default
This procedure is used during index lookups in Lua code.
procedure
(table-set! t k v) → void?
t : table? k : lua-value/c v : lua-value/c
This procedure is used during index assignments in Lua code.
procedure
t : table?
procedure
(table-metatable t) → (or/c nil? table?)
t : table?
This procedure is accessible from Lua code as getmetatable.
procedure
(set-table-metatable! t meta) → table?
t : table? meta : table?
This procedure is accessible from Lua code as setmetatable.
5.2 Environments
(require lua/env) | package: lua-lib |
procedure
parameter
(current-racket-imports-enabled? enabled?) → void? enabled? : boolean?
= #f
parameter
(current-global-environment env) → void? env : table?
= (make-initial-environment)
parameter
→
(listof (cons/c bytes? (or/c module-path? resolved-module-path? module-path-index?))) (current-standard-library-modules modules) → void?
modules :
(listof (cons/c bytes? (or/c module-path? resolved-module-path? module-path-index?)))
Modules in this list are typically only instantiated once so they must not modify the global environment because the global environment may change to a fresh table after these modules are loaded for the first time.