github.com/coyove/nj@v0.0.0-20221110084952-c7f8db1065c3/README.md (about)

     1  NJ is a simple script engine written in golang with Lua-like syntax.
     2  
     3  (If you are looking for a Lua 5.2 compatible engine, refer to tag `v0.2`)
     4  
     5  ## Differ from Lua
     6  
     7  - There is no `table`, instead there are `array` and `object` respectively:
     8  	- `a=[1, 2, 3]`.
     9  	- `a={a=1, b=2}`.
    10  	- Empty array and empty object are `true` when used as booleans.
    11  - There are `typed` array and `untyped` array:
    12  	- Untyped arrays are generic arrays created by `[...]`, it is the builtin array type.
    13  	- Typed arrays are special arrays created by Go, say `[]byte`:
    14  		- `a = bytes(16)` creates a 16-byte long `[]byte`.
    15  		- `a.append(1)` appends 1 to it.
    16  		- `a.append(true)` will panic.
    17  		- `a.untype().append(true)` will `untype` the array into a (new) generic array.
    18  - Functions are callable objects:
    19  	- `function foo() end; assert(type(foo), "object")`
    20  	- `function foo() end; assert(foo is callable)`
    21  - Closures are created by capturing all symbols seen in the current scope and binding them to the returned function:
    22  	- `function foo(a, b) return function(c) return self.a + self.b + c end end`
    23      - `assert(foo(1, 2)(3), 6)`
    24  - Syntax of calling functions strictly requires no spaces between the callee and '(':
    25  	- `print(1)` is the only right way of calling a function.
    26  	- `print (1)` literally means two things: 1) get value of `print` and discard it, 2) evaluate `(1)`.
    27      - Also note that all required arguments must be provided to call a function properly:
    28          - `function foo(a, b) end; foo(1)` is invalid.
    29  - Spacing rule also applies to unary operator `-`:
    30  	- `a = 1-a <=> a = 1 - a` means assign the result of `1-a` to `a`.
    31  	- `a = 1 -a` means assign `1` to `a` and negate `a`.
    32  	- `a = 1 -a+1` means assign `1` to `a` and eval `-a+1`.
    33  	- `a = -a` means negate `a` and assign the result to `a`.
    34  	- `a = - a` is invalid.
    35  - There are two ways to write `if`:
    36  	- `if cond then true else false end` as a statement.
    37  	- `local a = if(cond, true, false)` as an expression.
    38  	- `if(cond) then ... end` is invalid, spaces after `if` statement is mandatory.
    39  	- `if (cond, true, false)` is invalid, spaces after `if` expression is not allowed.
    40  - To write variadic functions:
    41  	- `function foo(a, b...) end; args = [1, 2, 3]; foo(args...)`.
    42      - Parameters after `...` are optional:
    43  	    - `function foo(a ... b, c) end; foo(1); foo(1, 2); foo(1, 2, 3)`
    44  - Returning multiple arguments will be translated into returning an array, e.g.:
    45  	- `function foo() return 1, 2 end <=> function foo() return [1, 2] end`
    46  	- `local a, b, c = d <=> local a, b, c = d[0], d[1], d[2]`
    47  - Everything starts at ZERO. For-loops start inclusively and end exclusively, e.g.:
    48  	- `a=[1, 2]; assert(a[0] == 1)`.
    49  	- `for i=0,n do ... end` ranges `[0, n-1]`.
    50  	- `for i=n-1,-1,-1 do ... end` ranges `[n-1, 0]`.
    51  - For method function, it can access `this` which points to the receiver:
    52  	- `a={}; function a.foo(x) this.x = x end; a.foo(1); assert(a.x, 1)`
    53  - For any function, use `self` to get itself in the body:
    54      - `function foo(x) self.x = x end; foo(1); assert(foo.x, 1)`
    55  - You can define up to 32000 variables (varies depending on the number of temporal variables generated by interpreter) in a function.
    56  - Numbers are `int64 + float64` internally, interpreter may promote it to `float64` when needed and downgrade it to `int64` when possible.
    57  - You can `return` anywhere inside functions, `continue` inside for-loops, `goto` any label within the same function.
    58  
    59  ## Run
    60  
    61  ```golang
    62  program, err := nj.LoadString("return 1")
    63  v, err := program.Run() // v == 1
    64  ```
    65  
    66  ### Global Values
    67  
    68  ```golang
    69  bas.AddGlobal("G", bas.ValueOf(func() int { return 1 }))
    70  
    71  program, _ := nj.LoadString("return G() + 1")
    72  v, err := program.Run() // v == 2
    73  
    74  program, _ = nj.LoadString("return G() + 2")
    75  v, err = program.Run() // v == 3
    76  
    77  program, _ = nj.LoadString("return G + 2", &CompileOptions{
    78  	Globals: bas.NewObject(0).SetProp("G", 10).ToMap(), // override the global 'G'
    79  })
    80  v, err = program.Run() // v == 12
    81  ```
    82  
    83  ## Benchmarks
    84  
    85  Refer to [here](https://github.com/coyove/nj/blob/master/tests/bench/perf.md).
    86