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
6.2k
8
Share
Gore: A Tale of Go REPL
Go Conference Summer 2015
motemen
June 21, 2015
More Decks by motemen
See All by motemen
旧から新へ: 大規模ウェブクローラの Perl から Go への移行 / YAPC::Fukuoka 2025
motemen
3
2.3k
AIに実況させる / AI Streamer
motemen
4
8k
技術を育てる組織・組織を育てる技術 / technology and organization
motemen
13
5.2k
はてなのエンジニアリングマネジメント、これまでとこれから / Engineering Management in Hatena, Hatena Engineer Seminar 26
motemen
2
2.2k
入門 Bubble Tea
motemen
1
930
ソフトウェア開発と私 / Software Development and I
motemen
13
6.9k
はてなサービスプラットフォームチームにおける Mackerel / Mackerel in Hatena Platform Team
motemen
1
1.4k
はてなシステムの考古学 / History of development at Hatena
motemen
3
300k
Reading Go Tools - GoCon 2016 Spring
motemen
5
2.9k
Other Decks in Programming
See All in Programming
過去のレビュー知見をSkillsで資産化した話
pkshadeck
PRO
1
1.4k
How We Benchmarked Quarkus: Patterns and anti-patterns
hollycummins
1
180
Terraform言語の静的解析 / static analysis of Terraform language
wata727
1
140
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
150
「話せることがない」を乗り越える 〜日常業務から登壇テーマをつくる思考法〜
shoheimitani
4
970
Agentic Elixir
whatyouhide
0
440
決定論 vs 確率論:Gemini 3 FlashとTF-IDFを組み合わせた「法規判定エンジン」の構築
shukob
0
150
なぜあなたのコードには「コシ」がないのか?〜AI時代に問う、最後まで美味しい設計と戦略〜 #phpconkagawa / phpconkagawa2026
shogogg
0
140
Agent Skills を社内で育てる仕組み作り
jackchuka
1
1.4k
AgentCore Optimizationを始めよう!
licux
3
200
WebAssembly を読み込むベストプラクティス 2026年春版 / Best Practices for Loading WebAssembly (Spring 2026)
petamoriken
5
1.1k
mruby on C#: From VM Implementation to Game Scripting (RubyKaigi 2026)
hadashia
2
1.6k
Featured
See All Featured
Practical Orchestrator
shlominoach
191
11k
What's in a price? How to price your products and services
michaelherold
247
13k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
360
From π to Pie charts
rasagy
0
180
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
280
Being A Developer After 40
akosma
91
590k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
Paper Plane
katiecoart
PRO
1
49k
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
210
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
690
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
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