github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/README.md (about)

     1  [![Build Status](https://travis-ci.com/arnodel/golua.svg?branch=master)](https://travis-ci.com/arnodel/golua)
     2  [![Go Report Card](https://goreportcard.com/badge/github.com/arnodel/golua)](https://goreportcard.com/report/github.com/arnodel/golua)
     3  [![Coverage](https://codecov.io/gh/arnodel/golua/branch/master/graph/badge.svg)](https://codecov.io/gh/arnodel/golua)
     4  
     5  # GoLua
     6  
     7  Implementation of Lua **5.4** in Go with **no third party dependencies**. The
     8  compiler and runtime are complete (including coroutines), the standard Lua
     9  library is mostly implemented.
    10  
    11  - [GoLua](#golua)
    12  	- [Quick start: running golua](#quick-start-running-golua)
    13  		- [Safe execution environment (alpha)](#safe-execution-environment-alpha)
    14  		- [Importing and using Go packages](#importing-and-using-go-packages)
    15  	- [Quick start: embedding golua](#quick-start-embedding-golua)
    16  	- [Quick start: extending golua](#quick-start-extending-golua)
    17  	- [Aim](#aim)
    18  	- [Design constraints](#design-constraints)
    19  	- [Components](#components)
    20  		- [Lexer / Parser](#lexer--parser)
    21  		- [AST → IR Compilation](#ast--ir-compilation)
    22  		- [IR → Code Compilation](#ir--code-compilation)
    23  		- [Runtime](#runtime)
    24  		- [Test Suite](#test-suite)
    25  		- [The "official" Lua 5.4.3 Test Suite](#the-official-lua-543-test-suite)
    26  		- [Standard Library](#standard-library)
    27  
    28  ## Quick start: running golua
    29  
    30  To install, run:
    31  
    32  ```sh
    33  $ go get github.com/arnodel/golua
    34  ```
    35  
    36  To run interactively (in a repl):
    37  
    38  ```lua
    39  $ golua
    40  > function fac(n)
    41  |   if n == 0 then
    42  |     return 1
    43  |   else
    44  |     return n * fac(n - 1)
    45  |   end
    46  | end
    47  > -- For convenience the repl also evaluates expressions
    48  > -- and prints their value
    49  > fac(10)
    50  3628800
    51  > for i = 0, 5 do
    52  |   print(i, fac(i))
    53  | end
    54  0	1
    55  1	1
    56  2	2
    57  3	6
    58  4	24
    59  5	120
    60  >
    61  ```
    62  
    63  ### Safe execution environment (alpha)
    64  
    65  A unique feature of Golua is that you can run code in a safe execution
    66  environment where cpu and memory are restricted.  E.g.
    67  
    68  ```lua
    69  $ golua -cpulimit=10000000
    70  > while true do end
    71  !!! CPU limit of 10000000 exceeded
    72  Reset limits and continue? [yN] 
    73  ```
    74  
    75  You can even do this within Lua itself:
    76  
    77  ```lua
    78  $ golua
    79  > a = "a"
    80  > runtime.callcontext({kill={memory=1000000}}, function() while true do a = a..a end end)
    81  killed
    82  > #a
    83  262144
    84  ```
    85  
    86  For more details read more [here](quotas.md).
    87  
    88  ### Importing and using Go packages
    89  
    90  You can dynamically _import Go packages_ very easily as long as they are already
    91  downloaded - this include the standard library. Here is an example of running an
    92  http server in the repl:
    93  
    94  ```lua
    95  $ golua
    96  > go = require('golib')
    97  > http = go.import('net/http')
    98  > http.HandleFunc('/hello/', function(w, r)
    99  |   w.Write('hi there from Lua! You requested ' .. r.URL.Path)
   100  | end)
   101  > http.ListenAndServe(':7777')
   102  ```
   103  
   104  In another terminal you can do:
   105  
   106  ```sh
   107  $ curl http://localhost:7777/hello/golua
   108  hi there from Lua! You requested /hello/golua
   109  ```
   110  
   111  To run a lua file:
   112  
   113  ```sh
   114  $ golua myfile.lua
   115  ```
   116  
   117  Or
   118  
   119  ```sh
   120  cat myfile.lua | golua
   121  ```
   122  
   123  E.g. if the file `myfile.lua` contains:
   124  
   125  ```lua
   126  local function counter(start, step)
   127      return function()
   128          local val = start
   129          start = start + step
   130          return val
   131      end
   132  end
   133  
   134  local nxt = counter(5, 3)
   135  print(nxt(), nxt(), nxt(), nxt())
   136  ```
   137  
   138  Then:
   139  
   140  ```sh
   141  $ golua myfile.lua
   142  5	8	11	14
   143  ```
   144  
   145  Errors produce useful tracebacks, e.g. if the file `err.lua` contains:
   146  
   147  ```lua
   148  function foo(x)
   149      print(x)
   150      error("do not do this")
   151  end
   152  
   153  function bar(x)
   154      print(x)
   155      foo(x*x)
   156  end
   157  
   158  bar(2)
   159  ```
   160  
   161  Then:
   162  
   163  ```
   164  $ golua err.lua
   165  2
   166  4
   167  !!! error: do not do this
   168  in function foo (file err.lua:3)
   169  in function bar (file err.lua:8)
   170  in function <main chunk> (file err.lua:11)
   171  ```
   172  
   173  ## Quick start: embedding golua
   174  
   175  It's very easy to embed the golua compiler / runtime in a Go program. The example below compiles a lua function, runs it and displays the result.
   176  
   177  ```golang
   178  	// First we obtain a new Lua runtime which outputs to stdout
   179  	r := rt.New(os.Stdout)
   180  
   181  	// This is the chunk we want to run.  It returns an adding function.
   182  	source := []byte(`return function(x, y) return x + y end`)
   183  
   184  	// Compile the chunk. Note that compiling doesn't require a runtime.
   185  	chunk, _ := r.CompileAndLoadLuaChunk("test", source, rt.TableValue(r.GlobalEnv()))
   186  
   187  	// Run the chunk in the runtime's main thread.  Its output is the Lua adding
   188  	// function.
   189  	add, _ := rt.Call1(r.MainThread(), rt.FunctionValue(chunk))
   190  
   191  	// Now, run the Lua function in the main thread.
   192  	sum, _ := rt.Call1(r.MainThread(), add, rt.IntValue(40), rt.IntValue(2))
   193  
   194  	// --> 42
   195  	fmt.Println(sum.AsInt())
   196  ```
   197  
   198  ## Quick start: extending golua
   199  
   200  It's also very easy to add write Go functions that can be called from Lua code.
   201  The example below shows how to.
   202  
   203  This is the Go function that we are going to call from Lua. Its inputs are:
   204  
   205  - `t`: the thread the function is running in.
   206  - `c`: the go continuation that represents the context the function is called in.
   207    It contains the arguments to the function and the next continuation (the
   208    one which receives the values computed by this function).
   209  
   210  It returns the next continuation on success, else an error.
   211  
   212  ```golang
   213  func addints(t *rt.Thread, c *rt.GoCont) (rt.Cont, error) {
   214  	var x, y rt.Int
   215  
   216  	// First check there are two arguments
   217  	err := c.CheckNArgs(2)
   218  	if err == nil {
   219  		// Ok then try to convert the first argument to a lua integer (rt.Int).
   220  		x, err = c.IntArg(0)
   221  	}
   222  	if err == nil {
   223  		// Ok then try to convert the first argument to a lua integer (rt.Int).
   224  		y, err = c.IntArg(1)
   225  	}
   226  	if err != nil {
   227  		// Some error occured, we return it in our context
   228  		return nil, err
   229  	}
   230  	// Arguments parsed!  First get the next continuation.
   231  	next := c.Next()
   232  
   233  	// Then compute the result and push it to the continuation.
   234  	t.Push1(next, x + y)
   235  
   236  	// Finally return the next continuation.
   237  	return next, nil
   238  
   239  	// Note: the last 3 steps could have been written as:
   240  	// return c.PushingNext(x + y), nil
   241  }
   242  ```
   243  
   244  The code sample below shows how this function can be added to the Lua runtime
   245  environment and demonstrates calling it from Lua.
   246  
   247  ```golang
   248  	// First we obtain a new Lua runtime which outputs to stdout
   249  	r := rt.New(os.Stdout)
   250  
   251  	// Load the basic library into the runtime (we need print)
   252  	base.Load(r)
   253  
   254  	// Then we add our addints function to the global environment of the
   255  	// runtime.
   256  	r.SetEnvGoFunc(r.GlobalEnv(), "addints", addints, 2, false)
   257  
   258  	// This is the chunk we want to run.  It calls the addints function.
   259  	source := []byte(`print("hello", addints(40, 2))`)
   260  
   261  	// Compile the chunk.
   262  	chunk, _ := rt.CompileAndLoadLuaChunk("test", source, r.GlobalEnv())
   263  
   264  	// Run the chunk in the runtime's main thread.  It should output 42!
   265  	_, _ = rt.Call1(r.MainThread(), chunk)
   266  ```
   267  
   268  You can also make custom libraries and use Go values in Lua (using e.g. the
   269  `runtime.UserData` type). There is an example implementing a `regex` Lua
   270  package that uses Go `regexp.Regexp` in [examples/userdata](examples/userdata)
   271  
   272  ## Aim
   273  
   274  To implememt the Lua programming language in Go, easily embeddable in
   275  Go applications. It should be able to run any pure Lua code
   276  
   277  ## Design constraints
   278  
   279  - clean room implementation: do not look at existing implementations
   280  - self contained: no dependencies
   281  - small: avoid re-implementing features which are already present in
   282    the Go language or in the standard library (e.g. garbage collection)
   283  - register based VM
   284  - no call stack (continuation passing), tail call optimisation.
   285  
   286  ## Components
   287  
   288  ### Lexer / Parser
   289  
   290  - The lexer is implemented in the package `scanner`.
   291  - The parser is hand-written and implemented in the `parsing` package.
   292  
   293  ### AST → IR Compilation
   294  
   295  The `ast` package defines all the AST nodes.  The `astcomp` package defines a
   296  `Compiler` type that is able to compile an AST to IR, using an instance of
   297  `ir.CodeBuilder`.
   298  
   299  The `ir` package defines all the IR instructions and the IR compiler.
   300  
   301  ### IR → Code Compilation
   302  
   303  The runtime bytecode is defined in the `code` package. The `ircomp` package
   304  defines a `ConstantCompiler` type that is able to compile IR code to runtime
   305  bytecode, using an instance of `code.Builder`.
   306  
   307  ### Runtime
   308  
   309  The runtime is implemented in the `runtime` package. This defines a
   310  `Runtime` type which contains the global state of a runtime, a
   311  `Thread` type which can run a continuation, can yield and can be
   312  resumed, the various runtime data types (e.g. `String`, `Int`...). The
   313  bytecode interpreter is implemented in the `RunInThread` method of the
   314  `LuaCont` data type.
   315  
   316  ### Test Suite
   317  
   318  There is a framework for running lua tests in the package `luatesting`. In the
   319  various Go packages, if there is a `lua` directory, each `.lua` file is a test.
   320  Expected output is specified in the file as comments of a special form, starting
   321  with `-->`:
   322  
   323  ```lua
   324  print(1 + 2)
   325  --> =3
   326  -- "=" means match literally the output line
   327  
   328  print("ababab")
   329  --> ~^(ab)*$
   330  -- "~" means match with a regexp (syntax is go regexp)
   331  ```
   332  
   333  Most of the code is covered with such Lua tests. Specific packages or functions
   334  are covered with Go tests.
   335  
   336  ### The "official" Lua 5.4.3 Test Suite
   337  
   338  Lua provides a test suites for each version (https://www.lua.org/tests/).  There
   339  is an adapted version of the 5.4.3 tests
   340  [here](https://github.com/arnodel/golua-tests/pull/3) which is supposed to be
   341  passed by the latest version of Golua.  It is the form of a PR so that the
   342  difference with the original test suite can be seen easily.
   343  
   344  Assuming `golua` is installed on your system, those tests can be run from the
   345  root of the repository above as follows.
   346  
   347  ```sh
   348  golua -u -e "_U=true" all.lua
   349  ```
   350  
   351  For the moment `db.lua` is disabled (the file testing the debug module).  All
   352  other "soft" tests are run, some with adaptations.  The most significant
   353  differences are in error messages.
   354  
   355  ### Standard Library
   356  
   357  The `lib` directory contains a number of package, each implementing a
   358  lua library.
   359  
   360  - `base`: basic library. It is complete.
   361  - `coroutine`: the coroutine library, which is done.
   362  - `packagelib`: the package library. It is able to load lua modules
   363    but not "native" modules, which would be written in Go. Obviously
   364    this is not part of the official Lua specification. Perhaps using
   365    the plugin mechanism (https://golang.org/pkg/plugin/) would be a way
   366    of doing it. I have no plan to support Lua C modules!
   367  - `stringlib`: the string library. It is complete.
   368  - `mathlib`: the math library, It is complete.
   369  - `tablelib`: the table library. It is complete.
   370  - `iolib`: the io library. It is complete.
   371  - `utf8lib`: the utf8 library. It is complete.
   372  - `debug`: partially implemented (mainly to pass the lua test suite). The
   373    `getupvalue`, `setupvalue`, `upvalueid`, `upvaluejoin`, `setmetatable`,
   374    functions are implemented fully. The `getinfo` function is partially
   375    implemented.  The `traceback` function is implemented but its output is
   376    different from the C Lua implementation.  The `sethook` and `gethook` values
   377    are implemented - line hooks may not be as accurate as for C Lua.
   378  - `os` package is almost complete - `exit` doesn't support "closing" the Lua
   379    state (need to figure out what it means.)