mitchellh / go-mruby

Go (golang) bindings to mruby.
https://gist.github.com/mitchellh/90029601268e59a29e64e55bab1c5bdc
MIT License
471 stars 34 forks source link

Help me understand LoadString, unexpected behavior #62

Closed hkparker closed 6 years ago

hkparker commented 6 years ago

Hello, and thanks for the awesome work on this project!

I'm interested in using go-mruby to create a go application in which third parties can extend the functionality by writing little ruby extensions.

To get a basic idea of how this all works, I tried to re-create irb with the following code:

import (
    "bufio"
    "fmt"
    "github.com/mitchellh/go-mruby"
    "os"
)

func main() {
    mrb := mruby.NewMrb()

    for {
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("irb> ")
        text, _ := reader.ReadString('\n')
        result, err := mrb.LoadString(text)
        if err != nil {
            panic(err)
        }
        fmt.Printf("%s\n", result.String())
    }
}

Trying out some basic stuff:

$ go run main.go
irb> self
main
irb> self.class
Object
irb> a = 3
3
irb> puts a
panic: undefined method 'a' for main

goroutine 1 [running]:
main.main()
    /home/p0tash/Development/Go/src/github.com/hkparker/mrubytest/main.go:19 +0x289
exit status 2

hmm. Didn't seem to hold on to the reference to "a" between iterations of LoadString. For comparison, here's regular irb, which behaves as we'd all expect of course.

$ irb
irb(main):001:0> self
=> main
irb(main):002:0> self.class
=> Object
irb(main):003:0> a = 3
=> 3
irb(main):004:0> a
=> 3

Next I thought to try passing this reference in one call to LoadString.

$ go run main.go 
irb> a = 3; puts a
3

irb> 

So no panic, but we see the call to puts emitted a new line without printing the expected 3.


My guess is that I'm using this library wrong, and that to access (or create) "a" (or anything else), I should be interacting with the ruby VM via go calls and not loading ruby strings. But I don't get why this also doesn't work.

Can anyone explain what's going on here, and why the above code isn't working as I'd expect it to?

erikh commented 6 years ago

Maybe a lot to throw at you but check out this and see if it makes sense. In short, you want to instantiate a parser. https://github.com/box-builder/box/blob/master/builder/evaluator/mruby/mruby.go#L151-L181

On Thu, Aug 30, 2018 at 5:40 PM, Hayden Parker notifications@github.com wrote:

Hello, and thanks for the awesome work on this project!

I'm interested in using go-mruby to create a go application in which third parties can extend the functionality by writing little ruby extensions.

To get a basic idea of how this all works, I tried to re-create irb with the following code:

import ( "bufio" "fmt" "github.com/mitchellh/go-mruby" "os" ) func main() { mrb := mruby.NewMrb()

for { reader := bufio.NewReader(os.Stdin) fmt.Print("irb> ") text, _ := reader.ReadString('\n') result, err := mrb.LoadString(text) if err != nil { panic(err) } fmt.Printf("%s\n", result.String()) } }

Trying out some basic stuff:

$ go run main.go irb> self main irb> self.class Object irb> a = 3 3 irb> puts a panic: undefined method 'a' for main

goroutine 1 [running]: main.main() /home/p0tash/Development/Go/src/github.com/hkparker/mrubytest/main.go:19 +0x289 exit status 2

hmm. Didn't seem to hold on to the reference to "a" between iterations of LoadString. For comparison, here's regular irb, which behaves as we'd all expect of course.

$ irb irb(main):001:0> self => main irb(main):002:0> self.class => Object irb(main):003:0> a = 3 => 3 irb(main):004:0> a => 3

Next I thought to try passing this reference in one call to LoadString.

$ go run main.go irb> a = 3; puts a 3

irb>

So no panic, but we see the call to puts emitted a new line without printing the expected 3.

My guess is that I'm using this library wrong, and that to access (or create) "a" (or anything else), I should be interacting with the ruby VM via go calls and not loading ruby strings. But I don't get why this also doesn't work.

Can anyone explain what's going on here, and why the above code isn't working as I'd expect it to?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/mitchellh/go-mruby/issues/62, or mute the thread https://github.com/notifications/unsubscribe-auth/AABJ62AIkYDyDw45WIY0k-oxzGgFrv5oks5uWIYFgaJpZM4WUbUQ .

hkparker commented 6 years ago

Nice! First of all, cool project you've got there. Working with that example was enough to give me a functioning irb-like demo.

package main

import (
    "bufio"
    "fmt"
    "github.com/mitchellh/go-mruby"
    "os"
)

func main() {
    mrb := mruby.NewMrb()
    cc := mruby.NewCompileContext(mrb)
    cc.CaptureErrors(true)
    parser := mruby.NewParser(mrb)
    stackKeep := 0

    for {
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("irb> ")
        text, _ := reader.ReadString('\n')
        if _, err := parser.Parse(text, cc); err != nil {
            panic(err)
        }
        keep, res, err := mrb.RunWithContext(parser.GenerateCode(), mrb.TopSelf(), stackKeep)
        stackKeep = keep
        if err != nil {
            panic(err)
        }
        ret := res.String()
        if ret == "" {
            ret = "nil"
        }
        fmt.Printf("=> %s\n", ret)
    }
}
$ go run main.go
irb> a = 3
=> 3
irb> a
=> 3
irb> a + 2
=> 5
irb> puts "thanks for the tip!"
thanks for the tip!
=> nil
irb> b = lambda { |x| puts x }
=> #<Proc:0x1f46fa0@-:- (lambda)>
irb> b.call "fancy stuff"
fancy stuff
=> nil
erikh commented 6 years ago

Thanks, have fun!