Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Gore: A Tale of Go REPL
Search
motemen
June 21, 2015
Programming
8
6.1k
Gore: A Tale of Go REPL
Go Conference Summer 2015
motemen
June 21, 2015
Tweet
Share
More Decks by motemen
See All by motemen
AIに実況させる / AI Streamer
motemen
3
1.8k
技術を育てる組織・組織を育てる技術 / technology and organization
motemen
12
4.9k
はてなのエンジニアリングマネジメント、これまでとこれから / Engineering Management in Hatena, Hatena Engineer Seminar 26
motemen
2
2.1k
入門 Bubble Tea
motemen
1
850
ソフトウェア開発と私 / Software Development and I
motemen
13
6.8k
はてなサービスプラットフォームチームにおける Mackerel / Mackerel in Hatena Platform Team
motemen
1
1.3k
はてなシステムの考古学 / History of development at Hatena
motemen
3
300k
Reading Go Tools - GoCon 2016 Spring
motemen
5
2.8k
Diff'ing Go library API changes
motemen
4
2.7k
Other Decks in Programming
See All in Programming
モバイルアプリからWebへの横展開を加速した話_Claude_Code_実践術.pdf
kazuyasakamoto
0
310
コンテキストエンジニアリング Cursor編
kinopeee
1
760
アプリの "かわいい" を支えるアニメーションツールRiveについて
uetyo
0
210
MCPとデザインシステムに立脚したデザインと実装の融合
yukukotani
4
1.4k
プロパティベーステストによるUIテスト: LLMによるプロパティ定義生成でエッジケースを捉える
tetta_pdnt
0
220
Design Foundational Data Engineering Observability
sucitw
3
180
Flutter with Dart MCP: All You Need - 박제창 2025 I/O Extended Busan
itsmedreamwalker
0
140
時間軸から考えるTerraformを使う理由と留意点
fufuhu
14
4.5k
オープンセミナー2025@広島LT技術ブログを続けるには
satoshi256kbyte
0
170
Oracle Database Technology Night 92 Database Connection control FAN-AC
oracle4engineer
PRO
1
430
旅行プランAIエージェント開発の裏側
ippo012
2
870
Ruby Parser progress report 2025
yui_knk
1
300
Featured
See All Featured
Fireside Chat
paigeccino
39
3.6k
Making Projects Easy
brettharned
117
6.4k
Scaling GitHub
holman
463
140k
Side Projects
sachag
455
43k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
1.5k
A designer walks into a library…
pauljervisheath
207
24k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
580
Speed Design
sergeychernyshev
32
1.1k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
520
GraphQLの誤解/rethinking-graphql
sonatard
71
11k
Git: the NoSQL Database
bkeepers
PRO
431
66k
Transcript
A Tale of Go REPL motemen Go Conference 2015 Summer
@ Tokyo
About Me - @motemen - Web engineer - Chief engineer
at Hatena, Kyoto
Mackerel mackerel.io
Agenda - Introduction of ! motemen/gore - Gore’s architecture -
Implementation details
Gore /gɔː/
Case: Learning New Languages - Playing with language features -
Trying libraries
My Case — Perl - perl ~/sketch.pl - Edit and
Run
My Case — Ruby - irb - pry - A
“REPL” (Read-Eval-Print-Loop)
My Case — Go? - tmp.go - “packge main” “func
main()” - Removing unused variables by hand - Question: Can gophers haz a REPL?
Go "REPL" impls (AFAIK) - ! sbinet/igo — built upon
! sbinet/go-eval, with liner - ! emicklei/rango — importing, statements, listing variables - ! vito/go-repl — importing, statements, useful commands - ! d4l3k/go-pry — attaches to running program, uses reflection - (play.golang.org)
Needed a REPL that: - Evaluates statements - Imports any
module - Pretty prints values automatically - Completes code
The Difficulties - How can we achieve Go semantics? -
No APIs provided - Re-implement Go compiler?
Solution: “go run”
Solution: “go run” - An “eval” to Go - Perfect
implementation & Always up-to-date - Dead simple - In: a program Out: the result
Gore: A REPL using “go run” go get github.com/motemen/gore
Caveats - Gore runs all code input for each run
- Code with side effects will be repeated - eg. Printing output / Sleeping
Stories Inside Gore
Overview: not a “REPL” exactly - REPL: Read-Eval-Print-Loop - No
“Eval” and “Print” phase - As we do them by “go run” - Much like: Read-Generate-Run-Loop
Read-Gen-Run-Loop 1. Read user input to evaluate 2. Generate a
.go file that prints result 3. “go run” it 4. Back to 1.
Step: Read - Codes go under AST (abstract syntax tree)
form - Syntax checking - Easier to manipulate - Input String → AST → .go → “go run”
Read: Input - ! peterh/liner - Line editing - History
- Supports Windows
Read: Input to AST - package go/parser - Go has
rich support for parsing/typing its code - Easy to generate & manipulate
Read: Input to AST - Parse input as an expression
- If failed: a statement - Otherwise: continue input (multi-line)
Read: Expression - Easy - Dedicated API - parser.ParseExpr(in)
Read: Statements - $ func (s *Session) evalStmt(in string) error
{ src := fmt.Sprintf("package P; func F() { %s }", in) f, err := parser.ParseFile(s.Fset, "stmt.go", src, 0) if err != nil { return err } enclosingFunc := f.Scope.Lookup("F").Decl. (*ast.FuncDecl) stmts := enclosingFunc.Body.List }
Generate: The Delicious Part - Append the input AST nodes
to our main() - Add the code to print the value
Printing Values - The generated program prints values (not gore)
- “New Values” should be printed - Expression: Its resulting value - Statement: Values assigned
Printing Values: Expression - User: foo.Bar(a+1) - Gore: __gore_p(foo.Bar(a+1))
Printing Values: Statements - ast.AssignStmt stands for assign/define - User:
a, b := foo() - Gore: a, b := foo(); __gore_p(a, b)
Printing Values: __gore_p() - “Pretty prints” values - Defined along
with the main() - Depends on installed packages - ! k0kubun/pp, ! davecgh/go-spew or plain old %#v
The Initial .go File (pp) package main import "github.com/k0kubun/pp" func
__gore_p(xx ...interface{}) { for _, x := range xx { pp.Println(x) } } func main() { // User input goes here }
The Initial .go File (go-spew) package main import "github.com/davecgh/go-spew/spew" func
__gore_p(xx ...interface{}) { for _, x := range xx { spew.Printf("%#v\n", x) } } func main() { // User input goes here }
The Initial .go File (%#v) package main import "fmt" func
__gore_p(xx ...interface{}) { for _, x := range xx { fmt.Printf("%#v\n", x) } } func main() { // User input goes here }
Generate: Append to main() - Just append those generated statements
s.mainBody.List = append(s.mainBody.List, stmts…) - Now we’ve got the working code! - Really? No! %
Go compiler complaints (you know) - “x declared but not
used” - “p imported but not used” - “no new variables of left side of :=“ - & Should remove these to a successful go run
Quick Fixing Erroneous Program - “x declared but not used”
- “p imported but not used” - “no new variables on left side of :=“ Use it!! Anonymize it!! Make it `=‘ !!
“declared but not used” package P func main() { s
:= "hello" } package P func main() { s := "hello" _ = s }
”imported but not used” package P import "fmt" func main()
{ } package P import _ "fmt" func main() { }
“no new variables on left side of :=“ package P
func main() { var a int a := 1 } package P func main() { var a int a = 1 }
! motemen/go-quickfix to do the work - Type check source
code using go/types.Check() - Catch errors and modify AST - Packed with a bin - goquickfix -w main.go
Gore specific quickfix - __gore_p() for non-value expressions
Running - Output the AST to file — go/printer -
Then go run - If failed to run, revert the last input
Recap: Read-Gen-Quickfix-Run-Loop 1. Read and parse the input to obtain
AST 2. Add printing function call __gore_p() 3. Append the code to main() 4. Quickfix it so that it compiles well 5. go run
PRs welcome! - ! motemen/gore - ! motemen/go-quickfix
htn.to/intern2015
A Tale Gore motemen Go Conference 2015 Summer @ Tokyo
Appendix: More Features
Code Completion - liner has support for completion - Great
tool for editors: ! nsf/gocode - Server/client model - And an interface to it: motemen/gore/gocode - If gocode binary can be located, use it
Commands - :print - :write <file> - :import <pkg> -
:doc <expr>
:import <pkg> - Imports arbitrary packages - Just append import
statement to the file - Unused imports are handled by quickfix
:doc <expr> - Invokes go doc for given expression -
Package: :doc json - Function: :doc json.Marshal - Method: :doc json.NewEncoder().Encode