crazyinfin8 / wrengo Goto Github PK
View Code? Open in Web Editor NEWGo bindings for the Wren scripting language
License: MIT License
Go bindings for the Wren scripting language
License: MIT License
Consider this simple example where I'm trying to pass a list from Wren to Go:
/* list_trial.wren */
class Lst {
foreign static send(a)
}
var a = (1..10).toList
var b = Lst.send(a)
System.print(b)
/* list_trial.go */
package main
import (
"fmt"
wren "github.com/crazyinfin8/WrenGo"
)
func send(vm *wren.VM, parameters []any) (any, error) {
handle := parameters[1].(*wren.ListHandle)
count, _ := handle.Count()
fmt.Println("The list count is", count)
n := 1 // seg faults if this is changed to 2
for i := 0; i < n; i++ {
ifc, _ := handle.Get(i)
fmt.Println(ifc)
}
handle.Free()
return nil, nil
}
func main() {
vm := wren.NewVM()
fileName := "list_trial.wren"
methodMap := wren.MethodMap{"static send(_)": send}
classMap := wren.ClassMap{"Lst": wren.NewClass(nil, nil, methodMap)}
module := wren.NewModule(classMap)
vm.SetModule(fileName, module)
vm.InterpretFile(fileName)
vm.Free()
}
When run as it stands (Go 1.18.2, Ubuntu 22.04, AMD64), the output is:
The list count is 10
1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
but, if I change the variable 'n' to 2, it seg faults after printing '1' on line 473 of vm.go.
The code for the ListHandle.Get(index)
method which contains that line is:
// Get tries to return the value in the Wren list at the index `index`
func (h *ListHandle) Get(index int) (interface{}, error) {
handle := h.Handle()
if handle.handle == nil {
return nil, &NilHandleError{}
}
vm := h.VM()
C.wrenEnsureSlots(vm.vm, 2)
vm.setSlotValue(handle, 0)
if index < 0 || index >= int(C.wrenGetListCount(vm.vm, C.int(index))) { // line 473
return nil, &OutOfBounds{List: h, Index: index}
}
C.wrenGetListElement(vm.vm, 0, C.int(index), 1)
return vm.getSlotValue(1), nil
}
So the problem appears to be that C.wrenGetListCount
is trying to find the list in slot 'index' when it is in fact in slot 0.
However, I've no idea why my send
method is returning the full list rather than null. Perhaps I could leave @CrazyInfin8 to figure that one out.
Perhaps you could add these to the documentation when you have time.
One other thing I've just noticed is that Nums passed as arguments to Wren foreign methods are coming across to Go as float32's rather than float64's which is losing accuracy.
This seems to be as a result of this function in vm.go:
func (vm *VM) getSlotValue(slot int) (value interface{}) {
cSlot := C.int(slot)
switch C.wrenGetSlotType(vm.vm, C.int(cSlot)) {
//...
case C.WREN_TYPE_NUM:
return float32(C.wrenGetSlotDouble(vm.vm, cSlot))
//...
}
}
I don't understand why this is necessary when Nums are essentially float64's and slots can handle doubles just fine.
Firstly, thanks for creating this which is a useful adjunct for those of us who like to program in Go :)
Just three minor issues I've encountered so far.
Firstly, when I'm using Wren-cli, if I import a library module like this:
import "/someModule" for SomeClass
then Wren-cli would look for the file "./someModule.wren" and find it because I always copy such modules to the same directory as the startup script.
However, that's not happening with WrenGo. Either I have to use the library's full name (which is awkward if that in turn imports other modules) or I need to change the configuration like so:
cfg := wren.NewConfig()
cfg.LoadModuleFn = func(vm *wren.VM, name string) (string, bool) {
if !strings.HasPrefix(name, ".") {
name = "." + name
}
if !strings.HasSuffix(name, ".wren") {
name += ".wren"
}
return wren.DefaultModuleLoader(vm, name)
}
vm := cfg.NewVM()
Although this is not a big problem, it would be nice if the DefaultModuleLoader function could do it for us.
Secondly, I've noticed that when I set up a Go function to represent a static foreign method in Wren, 'parameters' includes an extra parameter (the first one) which is a *wren.Handle and is possibly a meta-class reference or similar. This had me puzzled for a while and it would be useful if there could be a mention in the docs about the extra parameter being passed.
Finally, I couldn't figure out how to wire up a foreign property in Wren i.e. one with no following parentheses. Again no big problem as I can always add the parentheses but if there is a way to do it perhaps you could elucidate.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.