Re: [go-nuts] Go Interpreter

433 views
Skip to first unread message

Jan Mercl

unread,
Feb 18, 2015, 3:02:29 PM2/18/15
to xxx, golan...@googlegroups.com
On Wed Feb 18 2015 at 20:43:34 xxx <cyt...@gmail.com> wrote:

> I am planning to write a Go interpreter that's fully compatible with Go's 
> language spec.
> Would any body be interested? Coming from Python, I am really missing 
> a line-by-line REPL

But that's not easily feasible, if at all, in the general case if the above ("fully compatible with Go's language spec") is a goal. Consider this Go-spec-valid code (http://play.golang.org/p/JLnrctTfyl):

        package main

        import "fmt"

        func main() {
                fmt.Println(k)
        }

        const k = 42

Feeding this program to a REPL, line by line, top to bottom, encounters a situation which a REPL will have hard time to solve. It seems the only way to get around the problem for it is to not be a REPL in the first place.

> (not one like Scala's, which compiles your code and pretends to be an 
> interpreter). Currently there 's go-eval, but it doesn't support import nor > any of Go's builtin concurrency constructs (chan, go, etc). 

Go compilers are so fast that spending a _lot_ of time to create a partial-spec-conforming REPL might seem like a waste of time.

However, it would be a lot of fun! 

-j

Tom Chen

unread,
Feb 18, 2015, 3:04:41 PM2/18/15
to Jan Mercl, golan...@googlegroups.com
You are right on the having fun part. I agree that the compiler is so fast that an interpreter is not a big jump.

wkharold

unread,
Feb 18, 2015, 3:32:19 PM2/18/15
to golan...@googlegroups.com, cyt...@gmail.com
I suspect the best that can be hoped for is an incremental compiler. I love the Haskell and Lisp REPLs, I don't know how useful it would be for go, I usually just use play.golang.org.

Kevin Gillette

unread,
Feb 18, 2015, 8:09:09 PM2/18/15
to golan...@googlegroups.com, cyt...@gmail.com
Indeed. If enough of the components of the compiler can be factored out into reusable libraries, it would be advantageous to just compile to something like nacl and run as a low priority child process communicating over stdio (e.g. how the playground works).

A good embedded interpreter needs re-entrancy and will have memory or time efficiency problems with type declarations, for example. A child process can easily be stopped, continued, or terminated.

mattn

unread,
Feb 18, 2015, 9:33:47 PM2/18/15
to golan...@googlegroups.com, cyt...@gmail.com

Sebastien Binet

unread,
Feb 19, 2015, 5:27:32 AM2/19/15
to mattn, golang-nuts, cyt...@gmail.com
On Thu, Feb 19, 2015 at 3:33 AM, mattn <matt...@gmail.com> wrote:
> How about this? https://github.com/motemen/gore

it has this very unfortunate caveat (which is shared with all the
other "on-the-fly" re-compilation REPLs):
https://github.com/motemen/gore#caveats
"""
gore runs code using go run for each input. If you have entered
time-consuming code, gore will run it for each input and take some
time.
"""

this is a bit of a big no-no for the kind of interpreter-y work I
envision (data analysis + data plotting with go.)

the way I see it, there are 2 options to implement a proper go interpreter:
- improve reflect so the whole language syntax and constructs are
available from that package
- implement a VM and (re-)implement the whole language on top of it.

for go-eval, I think I'll go with option a) as it's less time
consuming on my end (see: golang.org/cl/4111, golang.org/cl/1996)
the only issue (AFAICT) with option a) is the handling of imports. for
this to work in a reflect-based interpreter, one would need some
support for dynamic code loading, like this:
https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit

that said, I am more than happy to collaborate on a go interpreter,
whatever its name or repo :)

-s

David Thomas

unread,
Feb 20, 2015, 6:59:08 PM2/20/15
to golan...@googlegroups.com, matt...@gmail.com, cyt...@gmail.com
Check out github.com/davidthomas426/goconsole  (I'm the author)

It's a project I work on for fun from sometimes. It is far from finished, but it's worth checking out. It relies very heavily on the reflect package to do its magic.

Restrictions that are intended, by design:
  * no type declarations
  * no function declarations like Go has at the top level
    -> you just create variables of function type instead
  * no imports *once the interpreter's already running*
    -> instead, you can list packages when you start the interpreter, and it uses code generation and go run to bake them in.
  * if you type in a deadlock, the interpreter deadlocks. I wanted the interpreter to be as close to the real runtime as possible, though this is admittedly perhaps less than ideal. Though, I'm not sure what I'd rather it do, and the design doesn't really allow anything else that I can think of.

Missing features because it's unfinished:
  * panic/defer
  * switch statements
  * method calls (this one is major, of course)
  * interpreted code is very slow and memory hungry
    -> note that if you make calls to compiled code, that code is run natively. This makes the interpreter quite good at interactive glue code.
  * errors of just about any kind cause log.Fatal, which means you lose all interpreter state. This of course is meant to be replaced with real error handling.
  * various other language features that I haven't gotten around to implementing.

Particularly notable features that ARE there:
  * goroutines (actual goroutines)
  * channels
  * select statements (turns into reflect.Select call with real communication ops, with correct semantics)
  * Calling from interpreter code into native code (libraries)
  * Calling from native code into interpreted code (think closures, I'll include an example below)


Here's my favorite example that actually works today, based on an example from net/http package docs:

  $ goconsole net/http html log fmt
  >>> http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  ...         fmt.Fprintf(w, "Hello, %q\n", html.EscapeString(r.URL.Path))
  ... })
  >>> log.Fatal(http.ListenAndServe(":8080", nil))

 (other terminal window)

  Hello, "/foobar"
    

I'll stop rambling. If you'd like to know more, let me know. I've always thought some interactive way to play with Go code would be nice, so I'm excited to see other people interesting in working on it.
Reply all
Reply to author
Forward
0 new messages