Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Printed output is stacking, is this intended behavior? #67

Closed
mtaufen opened this issue May 19, 2016 · 5 comments
Closed

Printed output is stacking, is this intended behavior? #67

mtaufen opened this issue May 19, 2016 · 5 comments

Comments

@mtaufen
Copy link

mtaufen commented May 19, 2016

gore> :import "fmt"
gore> fmt.Println("ha!")
ha!
(int)4
(interface {})<nil>
gore> fmt.Println("ha!")
ha!
ha!
(int)4
(interface {})<nil>
gore> fmt.Println("ha!")
ha!
ha!
ha!
(int)4
(interface {})<nil>
gore> fmt.Println("ha!");
ha!
ha!
ha!
ha!
gore> 
gore> 
gore> 

See the above short session, and note that the calls to fmt.Println("ha!") seem to stack and repeat each time fmt.Println is used, is this intended?

Also note that omitting the semicolon results in

(int)4
(interface {})<nil>

being printed after the accumulated output from fmt.Println.

@mtaufen mtaufen changed the title Printed output is stacking, is this defined behavior? Printed output is stacking, is this intended behavior? May 19, 2016
@wkhere
Copy link

wkhere commented Sep 2, 2016

I'm having the same. Quite annoying really..

@syohex
Copy link
Contributor

syohex commented Sep 2, 2016

[NOTE] you can see current source code by :print. You can see some fmt.Println in source.

@idubinskiy
Copy link

I think the issue here is that most people using a REPL don't expect every previous line to be re-run every time. The expectation is that the effects results of running previous lines (variable declarations/manipulation, etc.) will be kept, but not that the lines will actually be run again every time (with possible side effects).

For example, I created a small server that logs the URL being accessed for each request.

Input to gore:

gore> :import "net/http"
gore> http.Get("http://localhost:8081/1")
gore> http.Get("http://localhost:8081/2")
gore> http.Get("http://localhost:8081/3")
gore> http.Get("http://localhost:8081/4")
gore> http.Get("http://localhost:8081/5")
gore> http.Get("http://localhost:8081/6")
gore> http.Get("http://localhost:8081/7")
gore> http.Get("http://localhost:8081/8")

Output from server:

/1
/1
/2
/1
/2
/3
/1
/2
/3
/4
/1
/2
/3
/4
/5
/1
/2
/3
/4
/5
/6
/1
/2
/3
/4
/5
/6
/7
/1
/2
/3
/4
/5
/6
/7
/8

Whereas the expected output from the server would be:

/1
/2
/3
/4
/5
/6
/7
/8

Using the Node REPL (for example) works as expected. Input:

> http = require("http")
> http.get("http://localhost:8081/1")
> http.get("http://localhost:8081/2")
> http.get("http://localhost:8081/3")
> http.get("http://localhost:8081/4")
> http.get("http://localhost:8081/5")
> http.get("http://localhost:8081/6")
> http.get("http://localhost:8081/7")
> http.get("http://localhost:8081/8")

Server output:

/1
/2                  
/3
/4
/5
/6
/7
/8

@itchyny
Copy link
Collaborator

itchyny commented Feb 21, 2019

As for fmt.Print, monkey patching library can be the saver but generally speaking we have to consider implementing a real interpreter which will cost much as reimplementation of golang compiler. Since swift has a repl based on llvm (since swift compiler itself is based on llvm, apparently), can we use llgo?

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"reflect"

	"bou.ke/monkey"
)

func patchWrite() *monkey.PatchGuard {
	var guard *monkey.PatchGuard
	guard = monkey.PatchInstanceMethod(
		reflect.TypeOf(os.Stdout), "Write",
		func(f *os.File, b []uint8) (int, error) {
			if f.Fd() == 1 || f.Fd() == 2 {
				return len(b), nil
			}
			guard.Unpatch()
			defer guard.Restore()
			return f.Write(b)
		},
	)
	return guard
}

func main() {
	writeGuard := patchWrite()
	x, err := fmt.Println(10)
	fmt.Printf("%d\n", 10)
	fmt.Fprintf(os.Stderr, "foo")
	// Should writing to a file be ignored or not?
	ioutil.WriteFile("/tmp/test.txt", []byte("hello"), os.FileMode(0600))
	writeGuard.Unpatch()
	fmt.Printf("%+v %+v\n", x, err)
	fmt.Println(20)
}

@itchyny
Copy link
Collaborator

itchyny commented Jan 20, 2020

This is unlikely to solve in this project so closing. There's another tool (yaegi) which solved this problem with much work in interpreter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants