Giter Club home page Giter Club logo

go-lua's Introduction

Build Status GoDoc

A Lua VM in pure Go

go-lua is a port of the Lua 5.2 VM to pure Go. It is compatible with binary files dumped by luac, from the Lua reference implementation.

The motivation is to enable simple scripting of Go applications. For example, it is used to describe flows in Shopify's load generation tool, Genghis.

Usage

go-lua is intended to be used as a Go package. It does not include a command to run the interpreter. To start using the library, run:

go get github.com/Shopify/go-lua

To develop & test go-lua, you'll also need the lua-tests submodule checked out:

git submodule update --init

You can then develop with the usual Go commands, e.g.:

go build
go test -cover

A simple example that loads & runs a Lua script is:

package main

import "github.com/Shopify/go-lua"

func main() {
  l := lua.NewState()
  lua.OpenLibraries(l)
  if err := lua.DoFile(l, "hello.lua"); err != nil {
    panic(err)
  }
}

Status

go-lua has been used in production in Shopify's load generation tool, Genghis, since May 2014, and is also part of Shopify's resiliency tooling.

The core VM and compiler has been ported and tested. The compiler is able to correctly process all Lua source files from the Lua test suite. The VM has been tested to correctly execute over a third of the Lua test cases.

Most core Lua libraries are at least partially implemented. Prominent exceptions are regular expressions, coroutines and string.dump.

Weak reference tables are not and will not be supported. go-lua uses the Go heap for Lua objects, and Go does not support weak references.

Benchmarks

Benchmark results shown here are taken from a Mid 2012 MacBook Pro Retina with a 2.6 GHz Core i7 CPU running OS X 10.10.2, go 1.4.2 and Lua 5.2.2.

The Fibonacci function can be written a few different ways to evaluate different performance characteristics of a language interpreter. The simplest way is as a recursive function:

  function fib(n)
    if n == 0 then
      return 0
    elseif n == 1 then
      return 1
    end
    return fib(n-1) + fib(n-2)
  end

This exercises the call stack implementation. When computing fib(35), go-lua is about 6x slower than the C Lua interpreter. Gopher-lua is about 20% faster than go-lua. Much of the performance difference between go-lua and gopher-lua comes from the inclusion of debug hooks in go-lua. The remainder is due to the call stack implementation - go-lua heap-allocates Lua stack frames with a separately allocated variant struct, as outlined above. Although it caches recently used stack frames, it is outperformed by the simpler statically allocated call stacks in gopher-lua.

  $ time lua fibr.lua
  real  0m2.807s
  user  0m2.795s
  sys   0m0.006s
  
  $ time glua fibr.lua
  real  0m14.528s
  user  0m14.513s
  sys   0m0.031s
  
  $ time go-lua fibr.lua
  real  0m17.411s
  user  0m17.514s
  sys   0m1.287s

The recursive Fibonacci function can be transformed into a tail-recursive variant:

  function fibt(n0, n1, c)
    if c == 0 then
      return n0
    else if c == 1 then
      return n1
    end
    return fibt(n1, n0+n1, c-1)
  end
  
  function fib(n)
    fibt(0, 1, n)
  end

The Lua interpreter detects and optimizes tail calls. This exhibits similar relative performance between the 3 interpreters, though gopher-lua edges ahead a little due to its simpler stack model and reduced bookkeeping.

  $ time lua fibt.lua
  real  0m0.099s
  user  0m0.096s
  sys   0m0.002s

  $ time glua fibt.lua
  real  0m0.489s
  user  0m0.484s
  sys   0m0.005s

  $ time go-lua fibt.lua
  real  0m0.607s
  user  0m0.610s
  sys   0m0.068s

Finally, we can write an explicitly iterative implementation:

  function fib(n)
    if n == 0 then
      return 0
    else if n == 1 then
      return 1
    end
    local n0, n1 = 0, 1
    for i = n, 2, -1 do
      local tmp = n0 + n1
      n0 = n1
      n1 = tmp
    end
    return n1
  end

This exercises more of the bytecode interpreter’s inner loop. Here we see the performance impact of Go’s switch implementation. Both go-lua and gopher-lua are an order of magnitude slower than the C Lua interpreter.

  $ time lua fibi.lua
  real  0m0.023s
  user  0m0.020s
  sys   0m0.003s

  $ time glua fibi.lua
  real  0m0.242s
  user  0m0.235s
  sys   0m0.005s

  $ time go-lua fibi.lua
  real  0m0.242s
  user  0m0.240s
  sys   0m0.028s

License

go-lua is licensed under the MIT license.

go-lua's People

Contributors

abecevello avatar alexmax avatar anaminus avatar aybabtme avatar burke avatar cursedcoder avatar d6o avatar dgryski avatar etiennemartin avatar fbogsany avatar jules2689 avatar katdrobnjakovic avatar meunierd avatar nilium avatar rbindra avatar serima avatar shivnagarajan avatar shopify-admins avatar siddhesh avatar thriqon avatar tmlayton avatar xrash avatar xthexder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-lua's Issues

XMove not implemented

I'm trying to use the debug module to limit things such as "while true do end" from hanging, yet I get an "XMove not implemented" error from this line.

I was wondering what is up? If it's just something that needs doing I'd be willing to take a look if I was pointed in the right direction.

Thanks.

Missing usage instructions

I wanted to run a lua script liket gopher-lua shows on its readme. Their version is:

L := lua.NewState()
defer L.Close()
if err := L.DoFile("hello.lua"); err != nil {
    panic(err)
}

I arrived at the below by trial and error (print worked!), but it would be great if you had the correct version on the frontpage. (Actually, it would probably be a better idea to have a DoFile that sets everything up, like gopher-lua does)

package main

import "github.com/Shopify/go-lua"

func main() {
    L := lua.NewState()

    lua.BaseOpen(L)
    if err := lua.LoadFile(L, "hello.lua", ""); err != nil {
        panic(err)
    }
    L.Call(0, 0)
}

Comparing a table to nil results in an error.

In Lua it is valid to compaire a table to nil, but this VM does not support that.

Lucky you, it is an easy fix and I have a patch, so here you go.

--- C:/Users/Milo/Desktop/vm.go Wed Jul 29 07:29:30 2015
+++ D:/Projects/Go/src/github.com/Shopify/go-lua/vm.go  Fri Nov 06 14:27:57 2015
@@ -108,6 +108,12 @@
        if t1 == t2 {
            return true
        }
+       
+       // Change by Milo: Somebody at Shopify forgot that you can compare tables to nil...
+       if t2 == nil {
+           return false
+       }
+       
        tm = l.equalTagMethod(t1.metaTable, t2.(*table).metaTable, tmEq)
    default:
        return t1 == t2

Bug: Tabled concatenated values read from metatable have wrong values

local meta = {
  __index = function (self, key)
    return "ASD"
  end
}

TEST = {}
setmetatable(TEST, meta)

local x = {
  'a ' .. TEST.A .. ' a',
  'b ' .. TEST.B .. ' b'
}

assert(x[1] == 'a ASD a')
assert(x[2] == 'b ASD b')

assert('c ' .. TEST.C == 'c ASD')

This fails in go-lua, but succeeds in Lua5.3.

os.date = nil

This line in an old Lua script of mine has never produced an error in any version of Lua, but in go-lua to gives me a "nil value" error

version = os.date('%y.%m.%d')

P.S. Tried it in the Lua command line tool too :)

Lua 5.3.4  Copyright (C) 1994-2017 Lua.org, PUC-Rio
> version = os.date('%y.%m.%d')
> =version
17.12.15
> 

No way to cancel reading file?

Imagine I make an infinite loop....
Is there no way to cancel executing that LUA code?
(Other than killing the whole program)

conversion type not yet supported: c

Works:

import datetime
now = datetime.datetime.now()
now2 = datetime.datetime.now()
print now2-now

// Output: 0:00:00.000198

Does not work (contents of hello.py):

import datetime
now = datetime.datetime.now()
print now
[u@x220 grumpy]$ grumpc -modname=hello $GOPATH/src/__python__/hello.py >     $GOPATH/src/__python__/hello/module.go
[u@x220 grumpy]$ echo 'import hello' | grumprun
NotImplementedError: conversion type not yet supported: c

Open Source go-lua

Steps to release Shopify/go-lua as an open source project:

  • #25 move test fixtures (originally Lua test code) to a separate repo
  • sanity check documentation
  • cleanup README.md, include status & limitations
  • add license?
  • ask "someone" to open the repo

Panic when returning from a lua function directly, but not if I store the results in a variable first

package main

import (
    "bytes"
    "log"

    "github.com/Shopify/go-lua"
)

func main() {
    l := lua.NewState()
    lua.OpenLibraries(l)

    loadInline := func(code string) {
        if err := l.Load(bytes.NewBufferString(code), "", "bt"); err != nil {
            log.Fatal(err)
        }
    }

    // Load in a global function
    loadInline(`
        function doingStuff(a, b)
            return a + b
        end
    `)
    l.Call(0, 0)

    // Call the function, first storing the result in a local variable
    loadInline(`
        local res = doingStuff(1, 2)
        return res
    `)
    l.Call(0, 1)
    i, _ := l.ToInteger(-1)
    log.Printf("i: %d", i)
    l.Remove(-1)

    // Call the function, directly returning the result from it
    loadInline(`
        return doingStuff(1, 2)
    `)
    l.Call(0, 1)
    i, _ = l.ToInteger(-1)
    log.Printf("i: %d", i)
    l.Remove(-1)
}

So first I'm loading a more or less useless function into the global namespace. Then I go to call it. If I Store the return value as a local variable It works fine and prints out 3 like it should. However, if I just directly return the result without first storing it I get a panic:

panic: runtime error: index out of range

goroutine 1 [running]:
github.com/Shopify/go-lua.func·125(0xc2080485f0, 0xc200400006, 0x5d6ca8, 0xc200400006)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/vm.go:358 +0x3fc
github.com/Shopify/go-lua.(*State).executeFunctionTable(0xc208038000)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/vm.go:942 +0x22e
github.com/Shopify/go-lua.(*State).execute(0xc208038000)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/vm.go:928 +0x28
github.com/Shopify/go-lua.(*State).call(0xc208038000, 0x1, 0x1, 0xc208010000)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/stack.go:381 +0xa6
github.com/Shopify/go-lua.(*State).CallWithContinuation(0xc208038000, 0x0, 0x1, 0x0, 0x0)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/lua.go:349 +0x126
github.com/Shopify/go-lua.(*State).Call(0xc208038000, 0x0, 0x1)
        /home/mediocregopher/src/go/src/github.com/Shopify/go-lua/lua.go:1345 +0x4e
main.main()
        /tmp/wat.go:42 +0x240

Could this be a bug with the shopify implementation, or is what I'm doing fundamentally incorrect in some way? Thanks!

Status of IO Library

The IO library seems to be implemented, but I can't get it to work correctly. This is my Go code:

package main

import "github.com/Shopify/go-lua"
import "os"

func main() {
        l := lua.NewState()
        lua.OpenLibraries(l)
        if err := lua.DoFile(l, os.Args[1]); err != nil {
                panic(err)
        }
}

And this is the contents of my Lua file:

for line in io.lines("lines.txt") do
  print(line)
end

When run with C-Lua it correctly reads in the file and prints it back out, however, with go-lua it just outputs nothing. Upon closer inspection I discovered that io.lines always returns nil, indicating EOF. Am I doing something wrong or is the io library just not ready (yet)?

Error too informative

=p

When a script is loaded with LoadString and an error occur during runtime, the following error message is returned:

runtime error: config(\"domain\")

step.initiate = function(previous_response)
    return get(config.domain)
    end

step.finish = function(previous_response)
    if not previous_response then
        fail(\"previous_response is nil =/\")
        return {}
    end
    local body = previous_response.body
    if not body then
        fail(\"body is nil =/ code=\"..previous_response.code)
        return {}
    end
    report(\"Response=\"..previous_response.code..\" body=\"..body)
    return {}
    end
:4: performing GET, Get http://54.82.33.31:8080/: dial tcp 54.82.33.31:8080: cannot assign requested address

Golang packages

Hi,

I want integrate it on my project:
https://github.com/prsolucoes/goci

It is a continuous integration system that use script files to make the build steps. I want use LUA now. How i can export some Go packages to this implementation? How multiple return works in this LUA implementation?

Thanks.

Error stack tracebacks?

Hi there!

(little disclaimer first: I'm not terribly familiar with go)

I'm struggling a bit on how to get proper tracebacks for errors using go-lua.

Giving this hello.lua file, containing:

print("Hello World")

function foo()
  print("Hello, I'm foo!")
  bar()
end

foo()

…run with lua hello.lua gives me:

Hello World
Hello, I'm foo!
lua: hello.lua:5: attempt to call global 'bar' (a nil value)
stack traceback:
	hello.lua:5: in function 'foo'
	hello.lua:8: in main chunk
	[C]: in ?

If I run this with the example provided in the README, I get:

go run lua-test.go
Hello World
Hello, I'm foo!
2017/08/03 11:38:42 runtime error: hello.lua:6: attempt to call a nil value

How can I get a comparable traceback with go-lua? Something that can be presented to a user. Are there more examples somewhere?

io.read() on stdin?

Am I stupid - Or is io.read() broken?
Attempt:

thing = io.read();
exec("say User input: "..thing);

I've also tried read("*line") (which gave a nil result) and readLine() (method not found)

Making my own reading method works fine, but...

go get fails on Windows 7 (go version go1.4 windows/amd64)

I couldn't install the library by go getting it. I got the following errors:

C:\Users\hugo>go get github.com/Shopify/go-lua

github.com/Shopify/go-lua

c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:12: undefined: CheckType
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:23: undefined: MetaField
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:24: undefined: CheckType
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:41: undefined: CheckInteger
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:42: undefined: CheckType
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:95: undefined: CheckStackWithMessage
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:101: undefined: Errorf
c:\users\hugo\go\src\github.com\Shopify\go-lua\base.go:326: undefined: SetFunctions
c:\users\hugo\go\src\github.com\Shopify\go-lua\bit32.go:32: undefined: CheckUnsigned
c:\users\hugo\go\src\github.com\Shopify\go-lua\bit32.go:43: undefined: CheckUnsigned
c:\users\hugo\go\src\github.com\Shopify\go-lua\bit32.go:43: too many errors

output difference between clua and go-lua

local set = {}

function set:new(list)
local this = {}
setmetatable(this, self)
self.__index = self
for _,v in ipairs(list) do this[v] = true end
return this
end

set.__add = function (l, r)
local this = set:new{}
for k in pairs(l) do this[k] = true end
for k in pairs(r) do this[k] = true end
return this
end

set.__mul = function (l, r)
local this = set:new{}
for k in pairs(l) do this[k] = r[k] end
return this
end

set.__tostring = function (f)
local this = {}
for k in pairs(f) do this[#this+1] = k end
return '{' .. table.concat(this, ', ') .. '}'
end

A,B,C = set:new{2,5,7}, set:new{3,9,27}, set:new{2,3,16}
print(A)
print(B)
print(C) -- expected: {2, 3, 16}; but {2, 3}

Executing Lua closure from Go

If I have a *lua.State where I register a function:

l := lua.NewState()

var closure interface{} 
l.Register("myCallback", func(l *lua.State) int {
    closure = l.ToValue(1)
    return 0
})

is it possible to call the function in Lua and pass a closure that can be executed later:

myCallback(function()
  print("hello!")
end)

So then I can call l.Call() on the body of the script which executes my callback to my registered function. Then I tried pushing it back on the stack and calling:

l.PushLightUserData(closure)
l.Call(0, 0)

However, I get this error:

runtime error: [string "main"]:4: attempt to call a nil value

I checked closure and verified that it's a *luaClosure.

Is it possible to save a closure and call it later from Go?


/cc @aybabtme

Can't remove a `nil` value from the stack

This test will fail:

package lua

import (
    "testing"
)

func TestCanRemoveNilObjectFromStack(t *testing.T) {

    defer func() {
        if r := recover(); r != nil {
            t.Fatalf("failed to remove `nil`, %v", r)
        }
    }()

    l := NewState()

    PushString(l, "hello")
    Remove(l, -1)

    PushNil(l)
    Remove(l, -1)
}

PR #20 provides a regression test that will pass when this is fixed.

io.write discards spaces after trailing numbers

Consider this Lua code:

io.write("123 ")
io.write("456 ")
io.write("Hello, ")
io.write("world!\n")

This does what it's supposed to when run with the standard Lua interpreter:

$ lua5.3
Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> dofile("bad-format.lua")
123 456 Hello, world!
> 

Now run the code using go-lua:

package main

import "github.com/Shopify/go-lua"
import "os"

func main() {
	l := lua.NewState()
	lua.OpenLibraries(l)
	if err := lua.DoFile(l, os.Args[1]); err != nil {
		panic(err)
	}
}

The space following each number mysteriously disappears:

$ go run bad-format.go bad-format.lua
123456Hello, world!

lua.Next skips values

Calling lua.Next on maps will sometime fail to retrieve all the values in a table. This is because the implementation of next relies on the order of iteration in Go maps:

func (l *State) next(t *table, key int) bool {
    i, k := 0, l.stack[key]
    // ...
    found := k == nil

    // checks for the key `hk == k`
    // then returns the value at the next iteration
    //
    // following calls to `next` assume future iteration on t.hash 
    // will be in the same order
    for hk, v := range t.hash {
        if found {
            if v != nil {
                l.stack[key] = hk
                l.stack[key+1] = v
                return true  
            }
        } else if l.equalObjects(hk, k) {
            found = true
        }
    }
    return false // no more elements
}

From the spec, this order is not guaranteed to be stable between iterations in a for-range loop. See bullet point 3: http://golang.org/ref/spec#For_statements

To enforce this, iteration over map is randomized between for-range clauses since Go 1: http://golang.org/src/pkg/runtime/hashmap.c (line 785)

They talk about it in http://blog.golang.org/go-maps-in-action

Questions about this project

Fist question is about error handling. Other libs that im using to integrate has a problem in calling functions with 3 types of error:

1 - Call a export function to LUA using fewer params number
2 - Call a export function to LUA using too many params number
3 - Call a export function to LUA using invalid type param

This is a common problem when user develop their scripts, but another lib simply CRASH the host process!

How it works on this lib?

Second question: It is in active development? Have any contact (email, skype, hangout)?

Third question: You see any problem to use it in my project? Any limitations?

Thanks. Sorry for questions, but it is an important search to my project.

Implement coroutines

This issue is a marker indicating that the coroutine module is not implemented yet.

Implement package library

The package library is missing, so it currently isn't possible to require Go or Lua modules that haven't been explicitly registered. This library should be implemented, at least for Lua modules.

Cannot iterate over the same table

This is a side-effect of #80 being reported, but because iteration over tables causes the table's iterationKeys field to be assigned, it is not currently possible to perform nested iteration over the same table. For example, the following test will fail (but it will pass in regular Lua 5.2):

func TestConcurrentNext(t *testing.T) {
	testString(t, `
	t = {}
	t[1], t[2], t[3] = true, true, true

	r = {}
	for k1 in pairs(t) do
		r[#r + 1] = k1
		for k2 in pairs(t) do
			r[#r + 1] = k2
		end
	end

	got = table.concat(r, "")
	want = "112321233123"
	assert(got == want, "got " .. got .. "; want " .. want)
	`)
}

Informative error message when `LoadFile` fails

Proposed solution

Provide more context as to what failed with the call.

Problem

At this time, both a syntax error or a missing file show up as file error:

Missing file:

func TestLuaRegexp(t *testing.T) {
    l := lua.NewState()
    lua.OpenLibraries(l)
    regexp.Open(l)
    luatest.RunLuaTests(t, l, "im_not_a_file.lua")
    // luatest.RunLuaTests(t, l, "regexp_test.lua")
}
// --- FAIL: TestLuaRegexp (0.00 seconds)
//         lua_test_runner.go:31: loading lua test script in VM, file error

Syntax error (in regexp_test.lua):

local re = require("goluago/regexp")

derp!

-- quotemeta
equals("quotemeta: example", "\\[foo\\]", re.quotemeta("[foo]"))
func TestLuaRegexp(t *testing.T) {
    l := lua.NewState()
    lua.OpenLibraries(l)
    regexp.Open(l)
    luatest.RunLuaTests(t, l, "regexp_test.lua")
}
// --- FAIL: TestLuaRegexp (0.00 seconds)
//         lua_test_runner.go:31: loading lua test script in VM, file error

Limiting script execution time reliably

I'm struggling to find a good solution to implementing a reliable mechanism to limit how long a script is allowed to run.

A lot of examples show using debug.sethook to check if a timer has elapsed every 100k instructions or so but this is not that reliable as a C call can block.

Another solution is to use alarm system call or setrlimit on lua in a new thread/process but that has its own set of drawbacks.

Has a script timeout been considered before as something we can set on the VM before executing a pcall?

ToBoolean returns true on too-large stack index

package main

import (
    "fmt"

    "github.com/Shopify/go-lua"
)

func main() {
    l := lua.NewState()
    l.PushBoolean(true)
    l.PushBoolean(false)
    fmt.Printf("Top: %d\n", l.Top())
    for i := 0; i < 4; i++ {
        fmt.Printf("ToBoolean(%d) %t\n", i, l.ToBoolean(i))
    }
}

Results in:

Top: 2
ToBoolean(0) false
ToBoolean(1) true
ToBoolean(2) false
ToBoolean(3) true

That last result is puzzling.

Here's the same sort of thing written in C against PUC-Rio Lua 5.2:

#include <stdio.h>

#include "lua.h"
#include "lauxlib.h"

int main() {
    lua_State *L;
    L = luaL_newstate();
    lua_pushboolean(L, 1);
    lua_pushboolean(L, 0);
    printf("Top: %d\n", lua_gettop(L));
    for (int i = 0; i < 4; i++) {
        printf("ToBoolean(%d) %d\n", i, lua_toboolean(L, i));
    }
}

Results in:

Top: 2
ToBoolean(0) 0
ToBoolean(1) 1
ToBoolean(2) 0
ToBoolean(3) 0

Other ToWhatever API's in go-lua appear to have a value, ok multi-valued return. Is the correct fix here to add a second API value, or to simply return false? The former would be consistent with other go-lua API's, the latter would be consistent with the C API and on the surface would not require changing existing code - although this might actually be a downside if there is any code that relies on this peculiarity of out-of-bounds truthiness.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.