Giter Site home page Giter Site logo

cosmos72 / gomacro Goto Github PK

View Code? Open in Web Editor NEW
2.1K 32.0 91.0 15.43 MB

Interactive Go interpreter and debugger with REPL, Eval, generics and Lisp-like macros

License: Mozilla Public License 2.0

Go 99.91% Python 0.01% Shell 0.01% Assembly 0.07%
golang interpreter debugger eval repl macros generics

gomacro's Introduction

gomacro - interactive Go interpreter and debugger with generics and macros

gomacro is an almost complete Go interpreter, implemented in pure Go. It offers both an interactive REPL and a scripting mode, and does not require a Go toolchain at runtime (except in one very specific case: import of a 3rd party package at runtime).

It has two dependencies beyond the Go standard library: github.com/peterh/liner and golang.org/x/tools/go/packages

Gomacro can be used as:

  • a standalone executable with interactive Go REPL, line editing and code completion: just run gomacro from your command line, then type Go code. Example:

    $ gomacro
    [greeting message...]
    
    gomacro> import "fmt"
    gomacro> fmt.Println("hello, world!")
    hello, world!
    14      // int
    <nil>   // error
    gomacro>
    

    press TAB to autocomplete a word, and press it again to cycle on possible completions.

    Line editing follows mostly Emacs: Ctrl+A or Home jumps to start of line, Ctrl+E or End jumps to end of line, Ald+D deletes word starting at cursor... For the full list of key bindings, see https://github.com/peterh/liner

  • a tool to experiment with Go generics: see Generics

  • a Go source code debugger: see Debugger

  • an interactive tool to make science more productive and more fun. If you use compiled Go with scientific libraries (physics, bioinformatics, statistics...) you can import the same libraries from gomacro REPL (immediate on Linux and Mac OS X, requires restarting on other platforms, see Importing packages below), call them interactively, inspect the results, feed them to other functions/libraries, all in a single session. The imported libraries will be compiled, not interpreted, so they will be as fast as in compiled Go.

    For a graphical user interface on top of gomacro, see Gophernotes. It is a Go kernel for Jupyter notebooks and nteract, and uses gomacro for Go code evaluation.

  • a library that adds Eval() and scripting capabilities to your Go programs in few lines of code:

     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"))
     }

    Also, github issue #13 explains how to have your application's functions, variable, constants and types available in the interpreter.

    Note: gomacro license is MPL 2.0, which imposes some restrictions on programs that use gomacro. See MPL 2.0 FAQ for common questions regarding the license terms and conditions.

  • a way to execute Go source code on-the-fly without a Go compiler: you can either run gomacro FILENAME.go (works on every supported platform)

    or you can insert a line #!/usr/bin/env gomacro at the beginning of a Go source file, then mark the file as executable with chmod +x FILENAME.go and finally execute it with ./FILENAME.go (works only on Unix-like systems: Linux, *BSD, Mac OS X ...)

  • a Go code generation tool: gomacro was started as an experiment to add Lisp-like macros to Go, and they are extremely useful (in the author's opinion) to simplify code generation. Macros are normal Go functions, they are special only in one aspect: they are executed before compiling code, and their input and output is code (abstract syntax trees, in the form of go/ast.Node)

    Don't confuse them with C preprocessor macros: in Lisp, Scheme and now in Go, macros are regular functions written in the same programming language as the rest of the source code. They can perform arbitrary computations and call any other function or library: they can even read and write files, open network connections, etc... as a normal Go function can do.

    See doc/code_generation.pdf for an introduction to the topic.

Installation

Prerequites

Supported platforms

Gomacro is pure Go, and in theory it should work on any platform supported by the Go compiler. The following combinations are tested and 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 (tested with Termux and the Go compiler distributed with it)

How to install

The command

go install github.com/cosmos72/gomacro@latest

downloads, compiles and installs gomacro and its dependencies

Current Status

Almost complete.

The main limitations and missing features are:

  • importing 3rd party libraries at runtime currently only works on Linux, Mac OS X and *BSD. On other systems as Windows and Android it is cumbersome and requires recompiling - see Importing packages.
  • when importing packages, both from standard library or from 3rd party libraries, generics are not imported.
  • defining generic functions and types in interpreted code is experimental and incomplete - see Generics
  • conversions from/to unsafe.Pointer are not supported.
  • some corner cases using interpreted interfaces, as interface -> interface type assertions and type switches, are not implemented yet.
  • some corner cases using recursive types may not work correctly.
  • goto can only jump backward, not forward
  • out-of-order code is under testing - some corner cases, as for example out-of-order declarations used in keys of composite literals, are not supported. Clearly, at REPL code is still executed as soon as possible, so it makes a difference mostly if you separate multiple declarations with ; on a single line. Example: var a = b; var b = 42
    Support for "batch mode" is in progress - it reads as much source code as possible before executing it, and it's useful mostly to execute whole files or directories.

The documentation also contains the full list of features and limitations

Extensions

Compared to compiled Go, gomacro supports several extensions:

  • an integrated debugger, see Debugger

  • configurable special commands. Type :help at REPL to list them, and see cmd.go:37 for the documentation and API to define new ones.

  • untyped constants can be manipulated directly at REPL. Examples:

    gomacro> 1<<100
    {int 1267650600228229401496703205376}	// untyped.Lit
    gomacro> const c = 1<<100; c * c / 100000000000
    {int 16069380442589902755419620923411626025222029937827}	// untyped.Lit
    

    This provides a handy arbitrary-precision calculator.

    Note: operations on large untyped integer constants are always exact, while operations on large untyped float constants are implemented with go/constant.Value, and are exact as long as both numerator and denominator are <= 5e1232.

    Beyond that, go/constant.Value switches from *big.Rat to *big.Float with precision = 512, which can accumulate rounding errors.

    If you need exact results, convert the untyped float constant to *big.Rat (see next item) before exceeding 5e1232.

  • untyped constants can be converted implicitly to *big.Int, *big.Rat and *big.Float. Examples:

    import "math/big"
    var i *big.Int = 1<<1000                 // exact - would overflow int
    var r *big.Rat = 1.000000000000000000001 // exact - different from 1.0
    var s *big.Rat = 5e1232                  // exact - would overflow float64
    var t *big.Rat = 1e1234                  // approximate, exceeds 5e1232
    var f *big.Float = 1e646456992           // largest untyped float constant that is different from +Inf

    Note: every time such a conversion is evaluated, it creates a new value - no risk to modify the constant.

    Be aware that converting a huge value to string, as typing f at REPL would do, can be very slow.

  • zero value constructors: for any type T, the expression T() returns the zero value of the type

  • macros, quoting and quasiquoting: see doc/code_generation.pdf

and slightly relaxed checks:

  • unused variables and unused return values never cause errors

Examples

Some short, notable examples - to run them on non-Linux platforms, see Importing packages first.

plot mathematical functions

  • install libraries: go get gonum.org/v1/plot gonum.org/v1/plot/plotter gonum.org/v1/plot/vg
  • start the interpreter: gomacro
  • at interpreter prompt, paste the whole Go code listed at https://github.com/gonum/plot/wiki/Example-plots#functions (the source code starts after the picture under the section "Functions", and ends just before the section "Histograms")
  • still at interpreter prompt, enter main() If all goes well, it will create a file named "functions.png" in current directory containing the plotted functions.

simple mandelbrot web server

  • install libraries: go get github.com/sverrirab/mandelbrot-go
  • chdir to mandelbrot-go source folder: cd; cd go/src/github.com/sverrirab/mandelbrot-go
  • start interpreter with arguments: gomacro -i mbrot.go
  • at interpreter prompt, enter init(); main()
  • visit http://localhost:8090/ Be patient, rendering and zooming mandelbrot set with an interpreter is a little slow.

Further examples are listed by Gophernotes

Importing packages

Gomacro supports the standard Go syntax import, including package renaming. Examples:

import "fmt"
import (
    "io"
    "net/http"
    r "reflect"
)

Third party packages - i.e. packages not in Go standard library - can also be imported with the same syntax.

Extension: unpublished packages can also be imported from a local filesystem directory (implemented on 2022-05-28). Supported syntaxes are:

import (
     "."                             // imports the package in current directory
     ".."                            // imports the package in parent directory
     "./some/relative/path"          // "./"  means relative to current directory
     "../some/other/relative/path"   // "../" means relative to parent directory
     "/some/absolute/path"           // "/"   means absolute
)

For an import to work, you usually need to follow its installation procedure: sometimes there are additional prerequisites to install, and the typical command go get PACKAGE-PATH may or may not be needed.

The next steps depend on the system you are running gomacro on:

Linux, Mac OS X and *BSD

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

$ gomacro
[greeting message...]

gomacro> import ( "gonum.org/v1/gonum/floats"; "gonum.org/v1/plot" )
// debug: running "go get gonum.org/v1/plot gonum.org/v1/gonum/floats" ...
go: downloading gonum.org/v1/gonum v0.12.0
go: downloading gonum.org/v1/plot v0.12.0
[ more "go: downloading " messages for dependencies...]
go: added gonum.org/v1/gonum v0.12.0
go: added gonum.org/v1/plot v0.12.0
// debug: running "go mod tidy" ...
go: downloading golang.org/x/exp v0.0.0-20220827204233-334a2380cb91
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_44092/import_1" ...

gomacro> floats.Sum([]float64{1,2,3})
6       // float64

Note: internally, gomacro will compile and load a single Go plugin containing the exported declarations of all the packages listed in import ( ... ).

The command go mod tidy is automatically executed before compiling the plugin, and it tries - among other things - to resolve any version conflict due to different versions of the same package being imported directly (i.e. listed in import ( ... )) or indirectly (i.e. as a required dependency).

Go plugins are currently supported only on Linux and Mac OS X.

WARNING On Mac OS X, never execute strip gomacro: it breaks plugin support, and loading third party packages stops working.

Other systems

On all other systems as Windows, Android and *BSD you can still use import, but there are more steps: you need to manually download the package, and you also need to recompile gomacro after the import (it will tell you). Example:

$ go get gonum.org/v1/plot
$ gomacro
[greeting message...]

gomacro> import "gonum.org/v1/plot"
// warning: created file "/home/max/go/src/github.com/cosmos72/gomacro/imports/thirdparty/gonum_org_v1_plot.go", recompile gomacro to use it

Now quit gomacro, recompile and reinstall it:

gomacro> :quit
$ go install github.com/cosmos72/gomacro

Finally restart it. Your import is now linked inside gomacro and will work:

$ gomacro
[greeting message...]

gomacro> import "gonum.org/v1/plot"
gomacro> plot.New()
&{...} // *plot.Plot
<nil>  // error

Note: if you need several packages, you can first import all of them, then quit and recompile gomacro only once.

Generics

gomacro contains two alternative, experimental versions of Go generics:

  • the first version is modeled after C++ templates, and is appropriately named "C++ style"
    See doc/generics-c++.md for how to enable and use them.

  • the second version is named "contracts are interfaces" - or more briefly "CTI". It is modeled after several preliminary proposals for Go generics, most notably Ian Lance Taylor's Type Parameters in Go It has some additions inspired from Haskell generics and original contributions from the author - in particular to create a simpler alternative to Go 2 contracts

    For their design document and reasoning behind some of the design choices, see doc/generics-cti.md

The second version of generics "CTI" is enabled by default in gomacro.

They are in beta status, and at the moment only generic types and functions are supported. Syntax and examples:

// declare a generic type with two type arguments T and U
type Pair#[T,U] struct {
	First T
	Second U
}

// instantiate the generic type using explicit types for T and U,
// and create a variable of such type.
var pair Pair#[complex64, struct{}]

// equivalent:
pair := Pair#[complex64, struct{}] {}

// a more complex example, showing higher-order functions
func Transform#[T,U](slice []T, trans func(T) U) []U {
	ret := make([]U, len(slice))
	for i := range slice {
		ret[i] = trans(slice[i])
	}
	return ret
}
Transform#[string,int] // returns func([]string, func(string) int) []int

// returns []int{3, 2, 1} i.e. the len() of each string in input slice:
Transform#[string,int]([]string{"abc","xy","z"}, func(s string) int { return len(s) })

Contracts specify the available methods of a generic type. For simplicity, they do not introduce a new syntax or new language concepts: contracts are just (generic) interfaces. With a tiny addition, actually: the ability to optionally indicate the receiver type.

For example, the contract specifying that values of type T can be compared with each other to determine if the first is less, equal or greater than the second is:

type Comparable#[T] interface {
	// returns -1 if a is less than b
	// returns  0 if a is equal to b
	// returns  1 if a is greater than b
	func (a T) Cmp(b T) int
}

A type T implements Comparable#[T] if it has a method func (T) Cmp(T) int. This interface is carefully chosen to match the existing methods of *math/big.Float, *math/big.Int and *math/big.Rat. In other words, *math/big.Float, *math/big.Int and *math/big.Rat already implement it.

What about basic types as int8, int16, int32, uint... float*, complex* ... ? Gomacro extends them, automatically adding many methods equivalent to the ones declared on *math/big.Int to perform arithmetic and comparison, including Cmp which is internally defined as (no need to define it yourself):

func (a int) Cmp(b int) int {
	if a < b {
		return -1
	} else if a > b {
		return 1
	} else {
		return 0
	}
}

Thus the generic functions Min and Max can be written as

func Min#[T: Comparable] (a, b T) T {
	if a.Cmp(b) < 0 { // also <= would work
		return a
	}
	return b
}
func Max#[T: Comparable] (a, b T) T {
	if a.Cmp(b) > 0 { // also >= would work
		return a
	}
	return b
}

Where the syntax #[T: Comparable] or equivalently #[T: Comparable#[T]] indicates that T must satisfy the contract (implement the interface) Comparable#[T]

Such functions Min and Max will then work automatically for every type T that satisfies the contract (implements the interface) Comparable#[T]:
all basic integers and floats, plus *math/big.Float, *math/big.Int and *math/big.Rat, plus every user-defined type T that has a method func (T) Cmp(T) int

If you do not specify the contract(s) that a type must satisfy, generic functions cannot access the fields and methods of a such type, which is then treated as a "black box", similarly to interface{}.

Two values of type T can be added if T has an appropriate method. But which name and signature should we choose to add values? Copying again from math/big, the method we choose is func (T) Add(T,T) T If receiver is a pointer, it will be set to the result - in any case, the result will also be returned. Similarly to Comparable, the contract Addable is then

type Addable#[T] interface {
	// Add two values a, b and return the result.
	// If recv is a pointer, it must be non-nil
	// and it will be set to the result
	func (recv T) Add(a, b T) T
}

With such a contract, a generic function Sum is quite straightforward:

func Sum#[T: Addable] (args ...T) T {
	// to create the zero value of T,
	// one can write 'var sum T' or equivalently 'sum := T()'
	// Unluckily, that's not enough for math/big numbers, which require
	// the receiver of method calls to be created with a function `New()`
	// Once math/big numbers have such method, the following
	// will be fully general - currently it works only on basic types.
	sum := T().New()

	for _, elem := range args {
		// use the method T.Add(T, T)
		//
		// as an optimization, relevant at least for math/big numbers,
		// also use sum as the receiver where result of Add will be stored
		// if the method Add has pointer receiver.
		//
		// To cover the case where method Add has instead value receiver,
		// also assign the returned value to sum
		sum = sum.Add(sum, elem)
	}
	return sum
}
Sum#[int]         // returns func(...int) int
Sum#[int] (1,2,3) // returns int(6)

Sum#[complex64]                 // returns func(...complex64) complex64
Sum#[complex64] (1.1+2.2i, 3.3) // returns complex64(4.4+2.2i)

Sum#[string]                         // returns func(...string) string
Sum#[string]("abc.","def.","xy","z") // returns "abc.def.xyz"

Partial and full specialization of generics is not supported in CTI generics, both for simplicity and to avoid accidentally providing Turing completeness at compile-time.

Instantiation of generic types and functions is on-demand.

Current limitations:

  • type inference on generic arguments #[...] is not yet implemented, thus generic arguments #[...] must be explicit.
  • generic methods are not yet implemented.
  • types are not checked to actually satisfy contracts.

Debugger

Since version 2.6, gomacro also has an integrated debugger. There are three ways to enter it:

  • hit CTRL+C while interpreted code is running.
  • type :debug STATEMENT-OR-FUNCTION-CALL at the prompt.
  • add a statement (an expression is not enough) "break" or _ = "break" to your code, then execute it normally.

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

Also,

  • commands can be abbreviated.
  • print fully supports expressions or statements with side effects, including function calls and modifying local variables.
  • env without arguments prints all global and local variables.
  • an empty command (i.e. just pressing enter) repeats the last command.

Only interpreted statements can be debugged: expressions and compiled code will be executed, but you cannot step into them.

The debugger is quite new, and may have some minor glitches.

Why it was created

First of all, to experiment with Go :)

Second, to simplify Go code generation tools (keep reading for the gory details)


Problem: "go generate" and many other Go tools automatically create Go source code from some kind of description - usually an interface specifications as WSDL, XSD, JSON...

Such specification may be written in Go, for example when creating JSON marshallers/unmarshallers from Go structs, or in some other language, for example when creating Go structs from JSON sample data.

In both cases, a variety of external programs are needed to generate Go source code: such programs need to be installed separately from the code being generated and compiled.

Also, Go is currently lacking generics (read: C++-like templates) because of the rationale "we do not yet know how to do them right, and once you do them wrong everybody is stuck with them"

The purpose of Lisp-like macros is to execute arbitrary code while compiling, in particular to generate source code.

This makes them very well suited (although arguably a bit low level) for both purposes: code generation and C++-like templates, which are a special case of code generation - for a demonstration of how to implement C++-like templates on top of Lisp-like macros, see for example the project https://github.com/cosmos72/cl-parametric-types from the same author.

Building a Go interpreter that supports Lisp-like macros, allows to embed all these code-generation activities into regular Go source code, without the need for external programs (except for the interpreter itself).

As a free bonus, we get support for Eval()

LEGAL

Gomacro is distributed under the terms of Mozilla Public License 2.0 or any later version.

gomacro's People

Contributors

au-phiware avatar cosmos72 avatar dwhitena avatar eclipseo avatar fiorix avatar glycerine avatar matiasinsaurralde avatar mattn avatar mewmew avatar nujabse avatar rabits avatar yakkomajuri 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

gomacro's Issues

Add generics

This is a complex and challenging task.

The idea is to use gomacro as a playground to experiment with Go language extensions, since in many cases it's much easier to add new features to gomacro than to one of the Go compilers.

Generics in Go are a very discussed proposal, and many programmers would like to have them, but their complexity and the miriad of possible variations don't offer a clear solution. Implementing an official but suboptimal solution with warts and issues means that everybody will be stuck with them for a long time due to the need to preserve language compatibility.

Gomacro offers an escape hatch: it's an unofficial Go interpreter, and gives no guarantees analogous to the Go compatibity promise. It merely does a best-effort attempt to implement Go language, and already contains several extensions to it. In the author's opinion, it's a very good environment where to experiment further language extensions.

Combine it with gomacro author's love-hate relationship with C++ templates (love for the power, hate for the syntax) and his dislike for protracted programming discussions with no code to show for them, and you can imagine the outcome.

This issue exists to track progress of the generics implementation in gomacro. Feel free to comment.

:source codefile

It would great to have a easy way to read and interpret a file full of expressions and declarations.

Perhaps there is always a way I'm not finding. The opposite of :write. One could ideally :write the current set of definitions and types, then :source them back in later, in a different session.

Error on some ordering of interface methods

Reported by @korewayume in gopherdata/gophernotes#119

type Integer int
func (a Integer) Less(b Integer) bool {
    return a < b
}
func (a *Integer) Add(b Integer) {
    *a += b
}
type LessAdder1 interface {
    Add(b Integer)
    Less(b Integer) bool
}
type LessAdder2 interface {
    Less(b Integer) bool
    Add(b Integer)
}
var a Integer = 1
var b LessAdder1 = &a // ok
var c LessAdder2 = &a // error: reflect.Set: value of type func(int) is not assignable to type func(int) bool

internal error: containLocalBinds() returned false, but block actually defined 1 Binds and 0 IntBinds

This program, a first-order test of select and channel work, works fine under regular go, but not under gomacro.

package main

import "fmt"

var ch = make(chan string)

func a() {for {select {case b := <-ch: fmt.Printf("got from ch a= '%v'\n", b); if b == "q\
uit" { return }}}}

func main() {
    go a()
    ch <- "hi"
    ch <- "quit"
}

under gomacro:

jaten@jatens-MacBook-Pro ~ $ gomacro
// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2017-2018 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help
gomacro> import "fmt"
gomacro> var ch = make(chan string)
gomacro> func a() {for {select {case b := <-ch: fmt.Printf("got from ch a= '%v'\n", b); if b == "quit" { return }}}}
repl.go:1:97: internal error: containLocalBinds() returned false, but block actually defined 1 Binds and 0 IntBinds:
	Binds = map[]
	Block =
{
	select {
	case b := <-ch:
		fmt.Printf("got from ch a= '%v'\n", b)
		if b == "quit" {
			return
		}
	}
}
gomacro> 

Error after Installing on OSX

Hey,

This is my first or second day using gomacro.

I got the following error today.

Steele232s-MacBook-Air:Desktop steele232 $ go install github.com/cosmos72/gomacro
github.com/cosmos72/gomacro
ld: warning: text-based stub file /System/Library/Frameworks//CoreFoundation.framework/CoreFoundation.tbd and library file /System/Library/Frameworks//CoreFoundation.framework/CoreFoundation are out of sync. Falling back to library file for linking.
ld: warning: text-based stub file /System/Library/Frameworks//Security.framework/Security.tbd and library file /System/Library/Frameworks//Security.framework/Security are out of sync. Falling back to library file for linking.
ld: warning: text-based stub file /System/Library/Frameworks//IOKit.framework/Versions/A/IOKit.tbd and library file /System/Library/Frameworks//IOKit.framework/Versions/A/IOKit are out of sync. Falling back to library file for linking.

Steele232s-MacBook-Air:Desktop steele232 $ gomacro -bash: gomacro: command not found

I got the same error when I did the install command (like above) and when I do
go get -u github.com/cosmos72/gomacro

I am pretty sure I had gomacro working yesterday.. or at least I did the go get command from the README.md . But I don't really remember.

I installed this on my windows work computer and it was working great.

The docs say that things work better on iOS than they do on Windows, so I was surprised when I got this error. None of the codes looked remotely familiar, so I thought I'd bring it to you guys and see what you think.

Other System Details:
OS: macOS High Sierra version 10.13.6

PS I haven't restarted my computer, but I could do that if you think it would help 😛

Help choosing new gomacro license?

As Gomacro author,
I recently discovered that the current LGPL license is more restrictive than I want.
Thanks to @glycerine for pointing it out.

LGPL 3.0, section 4. Combined Works imposes the following when someone wants to distribute a commercial program that includes a (modified or unmodified) copy of LGPL code:


  1. [you must] Do one of the following:

    1. Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.

    2. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.


Unluckily, dynamic linking in Go is cumbersome and extremely limited - the plugin module is more similar to dlopen() than to dynamic linking, and currently only works on Linux and Go 1.8+ (support on Mac OS X and Go 1.10 is still alpha-quality in my opinion, and other platforms don't have it at all). In my opinion, dynamic linking is not a viable solution for Go code.

LGPL allows static linking (the norm for Go) of LGPL code with commercial code, but then the commercial code must be also provided as object files that can be relinked with a newer version of LGPL code. Again, this is very cumbersome. I have no wish to impose such a restriction on commercial programs that use gomacro.

I am looking for a license that

  1. allows binary-only distribution of statically linked programs that include gomacro
  2. requires the distribution of such programs to include a copy of the gomacro source code they used, including any modifications they made, under their original license
  3. does not require releasing the source code for the rest of such programs.

Suggestions welcome :)

TestInterfaceIoReader failure with Go 1.11 beta

We are building with Go 1.11 beta on Fedora Rawhide in preparation for the next release, and gomacro fails in TestInterfaceIoReader. The output is not too verbose, so I'm not sure if it's a bug in Go 1.11, or something that needs to be fixed here:

Testing: "/builddir/build/BUILD/gomacro-2.7/_build/src/github.com/cosmos72/gomacro/xreflect"
+ GOPATH=/builddir/build/BUILD/gomacro-2.7/_build:/usr/share/gocode
+ go test -buildmode pie -compiler gc -ldflags '-extldflags '\''-Wl,-z,relro   -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld '\'''
// debug: importer: cannot find package "github.com/cosmos72/gomacro/xreflect" metadata, approximating it with reflection
// debug: struct xreflect.Request4Test
// debug: . map map[string]string
// debug: . ptr *xreflect.Response4Test
// debug: . . struct xreflect.Response4Test
// debug: . . . ptr *xreflect.Request4Test
--- FAIL: TestInterfaceIoReader (0.01s)
    type_test.go:33: expecting true <bool>, found false <bool>
    type_test.go:33: expecting true <bool>, found false <bool>

Support reloading files and single function definitions.

First - wow! This is a great solution for Lisp-style interactive programming in Go. I'm very impressed.

Now I'm hoping to duplicate even more of the experience of programming in Lisp. When running in Emacs, I can reload either all of the definitions in the entire file, or single variable/function definitions. Trying this now with EvalFile in cmd.go results in issues with the package declaration.

I'm thinking of a workflow like:

  1. Start gomacro (or another REPL that wraps it).
  2. Run my compiled function bound to "mypkg.F" and see an issue
  3. Edit the definition for "mypkg.F" and recompile it, as described above. This updates the imports.Package binding to point to the recompiled definition.
  4. Run "mypkg.F" again, though now with the new definition...

How feasible is this?

Bug in len() builtin

The builtin len() function fails on the following:

gomacro> a := [...]int{1,2,3}
gomacro> a
[1 2 3]	// [3]int
gomacro> cap(a)
3	// int
gomacro> len(a)
runtime error: invalid memory address or nil pointer dereference

This is on an x86-64 Linux system running kernel 4.14.60. Doubt the system I'm running has much to do with this error but if so just let me know and I can provide further details.

Thanks,
Jason

Allow to import from Go modules

It would be nice to be able to import packages from Go module in current directory.
My use case is launching gomacro from project directory to interactively test functions.

What do you think?

go:generate gomacro -genimport

Having just been bitten by stale dependencies, I wonder if gomacro could add a flag to do this part of package import:

import _i "import/path/for/your/application"

under command from a go generate run. In other words, if there was a flag (call it -genimport for discussion) to the gomacro binary that caused import _i output to be generated for the current working directory, then a

go:generate gomacro -genimport

line could be added to a file in the package we wish to keep up to date. Upon every build I always run go generate to keep the other parts up to date, and this would result in the x_package.go file also being kept up to date at the same time.

Would that make sense? I didn't see such a flag already but maybe there is already a way? Thanks for considering it.

feature request: tab complete suggestions dropdown

Right now, the tab complete requires that you tab through to see options. fmt.+tab,tab,tab,tab,shift+tab. That is a fantastic start. It would be even more awesome if a dropdown showed up or similar so you can see a list of autocomplete suggestions. Great for discoverability.

gomacro> fmt.Print<tab>
[Print Println Printf]

(with an underline on the current position, so underlined Print)

error executing go get github.com/cosmos72/gomacro/... (ending with literal three dots)

go get -v -d github.com/cosmos72/gomacro/...
tries to compile everything in gomacro which results with the following error:

package github.com/cosmos72/gomacro/experiments/jit/template/arm64: C source files
not allowed when not using cgo or SWIG: bitmask_immediate.c set.c

go build github.com/cosmos72/gomacro/... returns the same error.

Adding import "C" in one of the go file in experiments/jit/template/arm64 fixes the errors but then many others are triggered like:

# github.com/cosmos72/gomacro/experiments/jit/template/arm64
add.s:8:2: error: unknown use of instruction mnemonic without a size suffix
        add     x0,x0,x0
        ^
add.s:9:2: error: unknown use of instruction mnemonic without a size suffix
        add     x0,x0,x1
        ^

Would it be possible to have a version where everything compile in the master branch ?

implement interfaces at runtime [was: methods declared in the interpreter are not visible in compiled code]

Hello,

I'd like to know where is the problem with this piece of code:

package main

import(
    "fmt"
    "bytes"
    "github.com/cosmos72/gomacro/fast"
)

const source = `type T struct{}
func (*T) F() {}
`

func main(){
    src := bytes.NewReader([]byte(source))

    it := fast.New()
    if _, err := it.EvalReader(src); err != nil { panic(err) }

    v, _ := it.Eval1("new(T)")

    fmt.Println(v.NumMethod())
}

It prints «0» (zéro). So that's mean that with a type with methods when a value is created from this type, it don't have the methods.

gomacro has trouble importing aws-sdk

Hi, I'm having difficulty getting the aws-sdk working with gomacro.

jovyan@6ee76cc0911e:~$ go version
go version go1.12 linux/amd64
jovyan@6ee76cc0911e:~$ go get github.com/aws/aws-sdk-go/...
jovyan@6ee76cc0911e:~$ gomacro
// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2018-2019 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help
gomacro> import "github.com/aws/aws-sdk-go/aws"
// debug: created file "/go/src/gomacro_imports/github.com/aws/aws-sdk-go/aws/aws.go"...
// debug: compiling "/go/src/gomacro_imports/github.com/aws/aws-sdk-go/aws/aws.go" ...
# gomacro_imports/github.com/aws/aws-sdk-go/aws
./aws.go:8:2: imported and not used: "context"
error executing "/usr/local/go/bin/go build -buildmode=plugin" in directory "/go/src/gomacro_imports/github.com/aws/aws-sdk-go/aws/": exit status 2

test failures with Go 1.12 Beta 1

most test failures seem to be caused by gomacro incorrectly believing that time.Duration.String needs a pointer receiver i.e. a *time.Duration

support out-of-order declarations

currently types, constants, variables and functions must be declared before using them.

Compiled Go does not have this restriction - top level declarations can appear in any order.

It would be useful to have a "batch" mode that reproduces the same behaviour, to execute stock Go source files/packages in the interpreter

Shell based IDE / debugger.

Have to commend this work.
This is really amazing stuff.

The notebook integration is fab.
Now I am thinking about a 100% golang / web notebook like thing when you can write experiments and get benchmarking graphs , Venn diagrams to help with ML and other things where you need diagrams to cognitively understand the quantitative results.

Also i see another big ysecase here.
Slot of orgs will write their top layer of server code in nodejs because be it's fast to twiddle with etc but gomacro could fill its place nicely.

Also with the debugger. Now that's really powerful. This would mean you could attach to a running server, drain the connections off to another server in the cluster and degub a tough problem that requires live production data. Not having the data to reproduce a bug can be the source of lots of slow downs in fixing bugs.

If we could make a quasi IDE using a shall then it allows all these amazing possibilities.
There are a few out there I think....

interactive debugger

partially functional, working on it :)

To try the debugger, insert a statement (an expression is not enough) "break" or _ = "break" in some interpreted code, then execute the code.

Execution will stop at the "break", and the usual debugger commands will be available (type ? for help):
continue, finish, next, step, list, print ARG

The argument of print can be an expression, a statement or a declaration. Function calls and statements with side effects are supported.

Currently, step is a bit unreliable

Load changes in a package without restarting

@novikk commented on Dec 19, 2017 in gopherdata/gophernotes#93


If I import a package and then make changes to a function in this package, these changes won't take any effect if I do not restart the kernel. Running the import again doesn't solve the issue, I need to restart the kernel, and re-run the imports.


@cosmos72 note: in gophernotes context, the kernel is gophernotes, which contains a vendored copy of gomacro

Any low-hanging fruit for contribution?

Looking to improve my resume with the contribution to golang open-source projects. I'm an experienced lisper, so the idea of this thing is clear and attractive. Made two contributions to gitql recently. Also I have my own slime-based IDE for CL, written in tcl/tk.

feature request: shell commands

Would be great to run commands prefixed with ! in a shell like in ipython (and others?), eg

gomacro> !ls -la
drwxr-xr-x    6 peter  staff   204 12 Jul 22:49 .
drwxr-xr-x    3 peter  staff   102 12 Apr  2014 ..
drwxr-xr-x  140 peter  staff  4760 19 Mar  2016 5072f70927f95a13e54e775676c51ee144a14dd7
drwxr-xr-x  264 peter  staff  8976 13 Aug  2017 5a774f194ac60210f83ba3cfa6c7a769f5600dee

More examples https://jakevdp.github.io/PythonDataScienceHandbook/01.05-ipython-and-shell-commands.html#Shell-Commands-in-IPython

Feature request: provide code completion

Ideally, there would be a function available on fast.Interp like:
Complete(prefix string) []string
which would return the list of possible completions. It seems that such list could be returned to liner using line.SetCompleter to improve the REPL provided in gomacro.

type inference in composite literals not supported

For the classic interpreter (haven't tested with fast but looks to be the same)

When writing a composite literal array, slice, or map where the element (or key) is also a composite literal where the type is omitted the interpreter raised a nil pointer dereference as the type inference doesn't yet look complete.

The following gives the error message runtime error: invalid memory address or nil pointer dereference

var p = map[string][]string{"world":{"hello"}}

where as the same expression with the type written explicitly evaluates fine

var p = map[string][]string{"world":[]string{"hello"}}

At classic/type.go#L175 the branch for handling the inference case looks to be empty and then evalType2 returns nil. I understand that this is not a trivial implementation but a better error message from evalCompositeLiteral in the event where evalType2 returns nil would be appreciated. Or perhaps directly in evalType2. Something along the lines of type inference not supported?

reflect error working with go-redis/redis client

Repro below assumes a local Redis server running on default port

// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2017-2018 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help

import "github.com/go-redis/redis"
// debug: created file "~/go/src/gomacro_imports/github.com/go-redis/redis/redis.go"...
// debug: compiling "~/go/src/gomacro_imports/github.com/go-redis/redis/redis.go" ...
client := redis.NewClient(&redis.Options{
. . . .      Addr:     "localhost:6379",
. . . .      Password: "", // no password set
. . . .      DB:       0,  // use default DB
. . . .      })

client
// Redis<localhost:6379 db:0>	// *github.com/go-redis/redis.Client

pong, err := client.Ping().Result()
// reflect: Field index out of range

woot := client.Ping()
//reflect: Field index out of range

Should this "just work"? I don't even know where to start here...

I discovered this using GopherNotes, but just the bare CLI REPL shows the same errors.

Thanks for this great package and any help!

Error when assigning to a recursive struct slice type

Minimal reproduction:

type foo struct {
    bar []foo
}
fooslice := make([]foo, 8)
fooslice[0].bar = fooslice[1:2]    // Error

Running the above returns:

// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2017-2018 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help
gomacro> type foo struct {
. . . .        bar []foo
. . . .    }
gomacro> fooslice := make([]foo, 8)
gomacro> fooslice[0].bar = fooslice[1:2]    // Error
reflect.Value.Convert: value of type []struct { 𒀸bar []xreflect.Forward } cannot be converted to type []xreflect.Forward

Thanks for any assistance!

Install error: undefined strings.Builder

Just tried to install and got the error below. The error is followed by my setup. Ideas?

$ go version
go version go1.9.2 windows/amd64
$ go get -u github.com/cosmos72/gomacro
# github.com/cosmos72/gomacro/base/dep
C:\Users\mando\go\src\github.com\cosmos72\gomacro\base\dep\graph.go:238:10: undefined: strings.Builder
$ go env
set GOARCH=amd64
set GOBIN=C:/Users/mando/bin
set GOEXE=.exe
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOOS=windows
set GOPATH=C:\Users\mando\go
set GORACE=
set GOROOT=C:\Go
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
set CC=gcc
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
set CXX=g++
set CGO_ENABLED=1
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config

Stop shipping imports/plugin.go for debuggability by default

Due to golang/go#23733 for Go 1.10~1.11, delve is unable to debug a Go app if "plugin" is imported, err like:

API server listening at: 127.0.0.1:64634
could not launch process: decoding dwarf section info at offset 0x0: too short

Debugger finished with exit code 1

Debug will be normal if imports/plugin.go is removed. And dynamic imports work just fine per my run (OSX 10.11 Go1.11).

As golang/go#23733 will seemingly only go into Go1.12 in the future, I would suggest stop shipping imports/plugin.go by default.

can unexported fields and methods be accessed?

Howdy,

I'm playing with this insane tool for the first time, and I've got a question. I'm thinking of embedding gomacro into my codebase and exposing a hook to drop into the interpreter. And so I'm wondering about the limits of the interpreter (if any!). Can the interpreter give access to unexported fields / call unexported methods (also on unexported types)? I have not been able to do it.

Thanks!

readsig.go:66: unknown SigElemType: '9'

I tried to :env inspect a large package (not publicly available) and got this error, readsig.go:66: unknown SigElemType: '9', followed by gomacro stopping.

$ gomacro
gomacro
// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2017-2018 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help
gomacro> :package "github.com/my/private/pkg"
...
gomacro> :env
:env
// ----- builtin binds -----
Eval            = {0x47df830 ...
...
// ----- "github.com/my/private/pkg" binds -----
...
readsig.go:66: unknown SigElemType: '9'
$

Handle list of directories in $GOPATH

When $GOPATH is a list, import statements in gomacro create erroneous directories in the filesystem. For example, /a:/b:/c/gomacro_imports/{pkg}.

I have a PR for this with more details.

strings.Builder type not recognized by gomacro

The strings.Builder type is apparently not being properly recognized by gomacro.

The example code from the go documentation: https://play.golang.org/p/Dv96oDHG0tF

Does not correctly run in gomacro:

$ gomacro
// GOMACRO, an interactive Go interpreter with generics and macros
// Copyright (C) 2017-2018 Massimiliano Ghilardi <https://github.com/cosmos72/gomacro>
// License MPL v2.0+: Mozilla Public License version 2.0 or later <http://mozilla.org/MPL/2.0/>
// This is free software with ABSOLUTELY NO WARRANTY.
//
// Type :help for help
gomacro> package main
// debug: package main has no effect. To switch to a different package, use package "PACKAGE/FULL/PATH" - note the quotes
gomacro> 
gomacro> import (
. . . .    "fmt"
. . . .    "strings"
. . . .    )
gomacro> 
gomacro> func main() {
. . . .    var b strings.Builder
. . . .    for i := 3; i >= 1; i-- {
. . . .      fmt.Fprintf(&b, "%d...", i)
. . . .      }
. . . .    b.WriteString("ignition")
. . . .    fmt.Println(b.String())
. . . .    
. . . .    }
repl.go:2:7: not a type: strings.Builder <*ast.SelectorExpr>
gomacro> 

Struct field tag not being recognised/processed

I tried the following code using gomacro and got the following result:

gomacro> import (
. . . .    "fmt"
. . . .    "encoding/json"
. . . .    )
gomacro> type Person struct {
. . . .    Name string `json:"name"`
. . . .    Age int `json:"age"`
. . . .    }
gomacro> a := Person{Name: "Bob", Age: 10}
gomacro> b, _ := json.Marshal(a)
gomacro> fmt.Printf("%s", b)
{"Name":"Bob","Age":10}23	// int
<nil>	// error

It seems like the field tags are not being picked up/processed correctly.

Here is a go playground reproduction to show the expected behaviour:

Go Playground

Consider making a version of gomacro more portable

Problem:

  1. gomacro does not compile on a raspberry pi (the compiler runs out of memory) which is problematic when using gomacro with native libraries (because cross-compiling with cgo is not straightforward).
    (on a positive note, gomacro does run on a raspberry using cross-compiling, which is great... but plugins do not seem to be supported)
  2. gomacro cannot be used with google app engine because it uses the unsafe package

Question:
would it be possible to have a smaller and simpler version of gomacro ? (perhaps at the cost of performance and/or features ?)

Cannot update fields in elements of map[T1]*T2

While map elements are not themselves addressable, if the element is a pointer the pointee should be modifiable directly via map access as shown in this playground snippet.

gomacro> import "reflect" // Just a package with a handy struct.
gomacro> m := make(map[string]*reflect.SliceHeader)
gomacro> m["a"] = &reflect.SliceHeader{}
gomacro> m["a"].Len = 2
repl.go:1:1: cannot assign to m["a"].Len
	repl.go:1:1: cannot take the address of a map element: m["a"]

gomacro repl hanging on start

I've just installed gomacro. built with go-1.10 on linux/amd64.
While the command works for once-off evaluating expressions being passed to it, if I run gomacro with no flags, to get the repl, the program hangs indefinitely and I have to manually kill it by pid. An strace on the process shows it blocked on a pselect.

Are there any known issues running the repl on linux (specifically Ubuntu 16.04)

single-valued type assertion not working

I'm not sure if this is supposed to work; the README suggests that it should be.

Attempt to run the interpreted equivalent of the code here which outputs 2.

gomacro> var i interface{}
gomacro> i = 1
gomacro> import "fmt"
gomacro> fmt.Println(i.(int)+1)
// warning: expression returns 2 values, using only the first one: [int bool]
interface conversion: fast.I is func(*fast.Env) (reflect.Value, []reflect.Value), not func(*fast.Env) int

[go 1.9+] xreflect: invalid name used for struct fields

Currently tests fail due to an invalid struct name generated by xreflect.approxInterfaceHeader from StrGensymInterface. Is this expected behaviour? The restriction on struct names was enforced in go1.9 in to fix golang/go#20600.

$ go test ./...
panic: reflect.StructOf: field 0 has invalid name

goroutine 1 [running]:
reflect.StructOf(0xc420176680, 0x2, 0x2, 0x0, 0x0)
	/home/daniel/Development/go/src/reflect/type.go:2404 +0x33e2
github.com/cosmos72/gomacro.init()
	/home/daniel/Development/src/github.com/cosmos72/gomacro/all_test.go:145 +0x226
main.init()
	<autogenerated>:1 +0x53
FAIL	github.com/cosmos72/gomacro	0.010s
?   	github.com/cosmos72/gomacro/ast2	[no test files]
?   	github.com/cosmos72/gomacro/base	[no test files]
?   	github.com/cosmos72/gomacro/classic	[no test files]
?   	github.com/cosmos72/gomacro/example	[no test files]
?   	github.com/cosmos72/gomacro/example/earljwagner1	[no test files]
?   	github.com/cosmos72/gomacro/example/earljwagner2	[no test files]
ok  	github.com/cosmos72/gomacro/experiments	0.001s [no tests to run]
?   	github.com/cosmos72/gomacro/experiments/bytecode_interfaces	[no test files]
?   	github.com/cosmos72/gomacro/experiments/bytecode_values	[no test files]
?   	github.com/cosmos72/gomacro/experiments/closure_interfaces	[no test files]
?   	github.com/cosmos72/gomacro/experiments/closure_maps	[no test files]
?   	github.com/cosmos72/gomacro/experiments/closure_values	[no test files]
?   	github.com/cosmos72/gomacro/fast	[no test files]
?   	github.com/cosmos72/gomacro/imports	[no test files]
?   	github.com/cosmos72/gomacro/parser	[no test files]
?   	github.com/cosmos72/gomacro/scanner	[no test files]
?   	github.com/cosmos72/gomacro/token	[no test files]
?   	github.com/cosmos72/gomacro/typeutil	[no test files]
--- FAIL: TestInterface1 (0.00s)
panic: reflect.StructOf: field 0 has invalid name [recovered]
	panic: reflect.StructOf: field 0 has invalid name

goroutine 38 [running]:
testing.tRunner.func1(0xc4201cc4b0)
	/home/daniel/Development/go/src/testing/testing.go:711 +0x2d2
panic(0xf64380, 0xc42018c460)
	/home/daniel/Development/go/src/runtime/panic.go:491 +0x283
reflect.StructOf(0xc42028e000, 0x3, 0x3, 0x0, 0x0)
	/home/daniel/Development/go/src/reflect/type.go:2404 +0x33e2
github.com/cosmos72/gomacro/xreflect.(*Universe).InterfaceOf(0xc4202042c0, 0xc420042ce0, 0x2, 0x2, 0xc420042d00, 0x2, 0x2, 0x0, 0x0, 0x0, ...)
	/home/daniel/Development/src/github.com/cosmos72/gomacro/xreflect/interface.go:81 +0x5c7
github.com/cosmos72/gomacro/xreflect.InterfaceOf(0xc420042ce0, 0x2, 0x2, 0xc420042d00, 0x2, 0x2, 0x0, 0x0, 0x0, 0x1, ...)
	/home/daniel/Development/src/github.com/cosmos72/gomacro/xreflect/interface.go:100 +0xc9
github.com/cosmos72/gomacro/xreflect.TestInterface1(0xc4201cc4b0)
	/home/daniel/Development/src/github.com/cosmos72/gomacro/xreflect/type_test.go:109 +0x1c6
testing.tRunner(0xc4201cc4b0, 0x10b5488)
	/home/daniel/Development/go/src/testing/testing.go:746 +0xd0
created by testing.(*T).Run
	/home/daniel/Development/go/src/testing/testing.go:789 +0x2de
FAIL	github.com/cosmos72/gomacro/xreflect	0.010s

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.