gomacro is a near-complete Go interpreter, implemented in pure Go, that provides both interactive REPL and scripting modes and does not require the Go toolchain at runtime (except for some very specific scenarios: importing third-party packages at runtime). It has two dependencies outside the Go standard library: github.com/peterh/liner and golang.org/x/tools/go/packages.

gomacro

REPL is an acronym for Read-Eval-Print Loop, a simple, interactive programming environment where REPL means, respectively.

  • Read: gets user input
  • Eval: Evaluate the input
  • Print: prints and outputs the result of the evaluation
  • Loop: loop that repeats Read-Eval-Print over and over again

REPL is very useful for learning a new programming language, and you can quickly verify your understanding through the output in this interactive environment. For example, Python, which we use most often, comes with a programming environment like this.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
➜  ~ python3
Python 3.8.9 (default, Mar 30 2022, 13:51:16)
[Clang 13.1.6 (clang-1316.0.21.2.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 1
>>> a + 2
3
>>> print(a - 2)
-1
>>>

Features

Gomacro is one such REPL tool for the Go language, which can be used as.

  • A standalone executable with interactive Go REPL, line editing and code completion: just run gomacro from the command line and type Go code.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    $ gomacro
    [greeting message...]
    
    gomacro> import "fmt"
    gomacro> fmt.Println("hello, world!")
    hello, world!
    14      // int
    <nil>   // error
    gomacro>
    
  • Just press the TAB key to be automatically prompted, and press the TAB key again to cycle through the possible contents. Line editing mainly follows Emacs. Ctrl+A or Home jumps to the beginning of the line, Ctrl+E or End jumps to the end of the line, Ald+D deletes the word starting from the cursor ……

  • A Go generalization tool for experimentation

  • A Go source code debug tool

  • An interactive tool, if you use compiled Go with scientific libraries (physics, bioinformatics, statistics ……) ), you can import the same libraries from gomacro REPL (immediately on Linux and Mac OS X, restart required on other platforms), call them interactively, check the results, feed them to other functions/libraries, all in one session. Imported libraries will be compiled, not interpreted, so they will be just as fast as compiled Go.

  • Add Eval() and script functions to your Go programs with just a few lines of code.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    package main
    import (
        "fmt"
        "reflect"
        "github.com/cosmos72/gomacro/fast"
    )
    func RunGomacro(toeval string) reflect.Value {
        interp := fast.New()
        vals, _ := interp.Eval(toeval)
        // for simplicity, only use the first returned value
        return vals[0].ReflectValue()
    }
    func main() {
        fmt.Println(RunGomacro("1+1"))
    }
    
  • One way to execute Go source code on-the-fly without a Go compiler: you can run gomacro FILENAME.go. Or you can insert a line at the beginning of the Go source file #! /usr/bin/env gomacro, then mark the file as executable with chmod +x FILENAME.go, and finally use . /FILENAME.go to execute it (only on Unix-like systems: Linux, *BSD, Mac OS X …).

  • Go code generation tools: gomacro originally started as an experiment to add Lisp-like macros to Go, and they are very useful to simplify code generation. Macros are ordinary Go functions that are special in only one way: they are executed before the code is compiled, and their input and output is code.

Install

Requires Go version 1.13+, Gomacro is pure Go and in theory it should run on any platform supported by the Go compiler. The following combinations have been tested and are known to work.

  • Linux: amd64,386, arm64, arm, mips, ppc64le
  • Mac OS X: amd64,386 (386 binaries running on amd64 system)
  • Windows: amd64,386
  • FreeBSD: amd64,386
  • Android: arm64, arm

The installation is done by executing the following command.

1
go get -u github.com/cosmos72/gomacro

Usage

If you are running gomacro on Linux or Mac OS X, then import will work: it will automatically download, compile and import a package as follows.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ gomacro
[greeting message...]

gomacro> import ( "gonum.org/v1/floats"; "gonum.org/v1/plot" )
// debug: running "go get gonum.org/v1/gonum/floats gonum.org/v1/plot" ...
go: downloading gonum.org/v1/plot v0.11.0
[... more messages from go toolchain ...]
// debug: running "go mod tidy" ...
go: downloading github.com/go-fonts/latin-modern v0.2.0
go: downloading rsc.io/pdf v0.1.1
go: downloading github.com/go-fonts/dejavu v0.1.0
// debug: compiling plugin "/home/max/go/src/gomacro.imports/gomacro_pid_187824/import_1" ...
gomacro> plot.New()
&{...} // *gonum.org/v1/plot.Plot

Note: Internally, gomacro will compile and load a Go plugin containing all the export declarations listed in import ( ... ) with the export declarations of all the packages listed in import( ...).

The command go mod tidy, which is executed automatically before the plugin is compiled, will attempt to resolve any version conflicts due to direct import or indirect import of different versions of the same package (i.e. as required dependencies).

The Go plugin is currently only supported on Linux and Mac OS X.

Starting with version 2.6, gomacro also has an integrated debugger. There are three input methods.

  • Press CTRL+C while explaining the code run
  • Type : debug STATEMENT-OR-FUNCTION-CALL at the prompt
  • Add a statement (not enough expressions) "break" or _ ="break" to the code and execute it normally

In all cases, execution will be paused and you will receive a debug> prompt that accepts the following commands: step, next, finish, continue, env [NAME], inspect EXPR, list, print EXPR-OR- STATEMENT .

The overall experience is a REPL that supports basic functionality, Tab auto-completion (e.g. typing fmt.Print and pressing Tab will switch between fmt.Print, fmt.Printf and fmt.Println), debugging and simple viewing of function signatures. gomacro is sufficient for basic quick verification of code run results.