@@ -154,65 +154,103 @@ func goRun(files []string) ([]byte, bytes.Buffer, error) {
154
154
return out , stderr , err
155
155
}
156
156
157
- func (s * Session ) evalExpr (in string ) ([]ast.Expr , error ) {
158
- inLines := strings .Split (in , "\n " )
159
-
160
- var exprs []ast.Expr
161
- for _ , line := range inLines {
162
-
163
- expr , err := parser .ParseExpr (line )
164
- if err != nil {
165
- return nil , err
166
- }
167
- exprs = append (exprs , expr )
168
-
169
- stmt := & ast.ExprStmt {
170
- X : & ast.CallExpr {
171
- Fun : ast .NewIdent (printerName ),
172
- Args : []ast.Expr {expr },
173
- },
174
- }
157
+ func (s * Session ) evalExpr (in string ) (ast.Expr , error ) {
158
+ expr , err := parser .ParseExpr (in )
159
+ if err != nil {
160
+ return nil , err
161
+ }
175
162
176
- s .appendStatements (stmt )
163
+ stmt := & ast.ExprStmt {
164
+ X : & ast.CallExpr {
165
+ Fun : ast .NewIdent (printerName ),
166
+ Args : []ast.Expr {expr },
167
+ },
177
168
}
178
169
179
- return exprs , nil
170
+ s .appendStatements (stmt )
171
+
172
+ return expr , nil
180
173
}
181
174
182
175
func isNamedIdent (expr ast.Expr , name string ) bool {
183
176
ident , ok := expr .(* ast.Ident )
184
177
return ok && ident .Name == name
185
178
}
186
179
187
- func (s * Session ) evalStmt (in string ) error {
180
+ func (s * Session ) evalStmt (in string , noPrint bool ) error {
188
181
src := fmt .Sprintf ("package P; func F() { %s }" , in )
189
182
f , err := parser .ParseFile (s .Fset , "stmt.go" , src , parser .Mode (0 ))
190
183
if err != nil {
191
- return err
184
+ debugf ("stmt :: err = %s" , err )
185
+
186
+ // try to import this as a proxy function and correct for any imports
187
+ appendForImport := `package main
188
+
189
+
190
+ `
191
+
192
+ f , err := os .Create (string (filepath .Dir (s .FilePath )) + "/func_proxy.go" )
193
+ if err != nil {
194
+ return err
195
+ }
196
+
197
+ _ , err = f .Write ([]byte (appendForImport + in ))
198
+ if err != nil {
199
+ return err
200
+ }
201
+ f .Close ()
202
+
203
+ b := new (bytes.Buffer )
204
+ cmd := exec .Command ("goimports" , "-w" , string (filepath .Dir (s .FilePath ))+ "/func_proxy.go" )
205
+ cmd .Stdout = b
206
+ cmd .Stderr = b
207
+ err = cmd .Run ()
208
+ if err != nil {
209
+ os .Stderr .WriteString ("Error running goimports:\n " )
210
+ io .Copy (os .Stderr , b )
211
+ return err
212
+ }
213
+
214
+ functproxy , err := ioutil .ReadFile (string (filepath .Dir (s .FilePath )) + "/func_proxy.go" )
215
+ if err != nil {
216
+ return err
217
+ }
218
+
219
+ if err = s .importFile (functproxy ); err != nil {
220
+ errorf ("%s" , err )
221
+ if _ , ok := err .(scanner.ErrorList ); ok {
222
+ return ErrContinue
223
+ }
224
+ }
225
+
192
226
}
193
227
194
228
enclosingFunc := f .Scope .Lookup ("F" ).Decl .(* ast.FuncDecl )
195
229
stmts := enclosingFunc .Body .List
196
230
197
231
if len (stmts ) > 0 {
232
+
198
233
debugf ("evalStmt :: %s" , showNode (s .Fset , stmts ))
199
234
lastStmt := stmts [len (stmts )- 1 ]
235
+
200
236
// print last assigned/defined values
201
- if assign , ok := lastStmt .(* ast.AssignStmt ); ok {
202
- vs := []ast.Expr {}
203
- for _ , v := range assign .Lhs {
204
- if ! isNamedIdent (v , "_" ) {
205
- vs = append (vs , v )
237
+ if ! noPrint {
238
+ if assign , ok := lastStmt .(* ast.AssignStmt ); ok {
239
+ vs := []ast.Expr {}
240
+ for _ , v := range assign .Lhs {
241
+ if ! isNamedIdent (v , "_" ) {
242
+ vs = append (vs , v )
243
+ }
206
244
}
207
- }
208
- if len (vs ) > 0 {
209
- printLastValues := & ast.ExprStmt {
210
- X : & ast.CallExpr {
211
- Fun : ast .NewIdent (printerName ),
212
- Args : vs ,
213
- },
245
+ if len (vs ) > 0 {
246
+ printLastValues := & ast.ExprStmt {
247
+ X : & ast.CallExpr {
248
+ Fun : ast .NewIdent (printerName ),
249
+ Args : vs ,
250
+ },
251
+ }
252
+ stmts = append (stmts , printLastValues )
214
253
}
215
- stmts = append (stmts , printLastValues )
216
254
}
217
255
}
218
256
}
@@ -345,53 +383,9 @@ func (s *Session) Eval(in string) (string, bytes.Buffer, error) {
345
383
return "" , bytes.Buffer {}, nil
346
384
}
347
385
348
- if _ , err := s .evalExpr (in ); err != nil {
349
- debugf ("expr :: err = %s" , err )
350
-
351
- err := s .evalStmt (in )
352
- if err != nil {
353
- debugf ("stmt :: err = %s" , err )
354
-
355
- // try to import this as a proxy function and correct for any imports
356
- appendForImport := `package main
357
-
358
-
359
- `
360
-
361
- f , err := os .Create (string (filepath .Dir (s .FilePath )) + "/func_proxy.go" )
362
- if err != nil {
363
- panic (err )
364
- }
365
-
366
- _ , err = f .Write ([]byte (appendForImport + in ))
367
- if err != nil {
368
- panic (err )
369
- }
370
- f .Close ()
371
-
372
- b := new (bytes.Buffer )
373
- cmd := exec .Command ("goimports" , "-w" , string (filepath .Dir (s .FilePath ))+ "/func_proxy.go" )
374
- cmd .Stdout = b
375
- cmd .Stderr = b
376
- err = cmd .Run ()
377
- if err != nil {
378
- os .Stderr .WriteString ("Error running goimports:\n " )
379
- io .Copy (os .Stderr , b )
380
- panic (err )
381
- }
382
-
383
- functproxy , err := ioutil .ReadFile (string (filepath .Dir (s .FilePath )) + "/func_proxy.go" )
384
- if err != nil {
385
- panic (err )
386
- }
387
-
388
- if err = s .importFile (functproxy ); err != nil {
389
- errorf ("%s" , err )
390
- if _ , ok := err .(scanner.ErrorList ); ok {
391
- return "" , bytes.Buffer {}, ErrContinue
392
- }
393
- }
394
- }
386
+ // Extract statements.
387
+ if err := s .separateEvalStmt (in ); err != nil {
388
+ return "" , bytes.Buffer {}, err
395
389
}
396
390
397
391
s .doQuickFix ()
@@ -413,6 +407,54 @@ func (s *Session) Eval(in string) (string, bytes.Buffer, error) {
413
407
return string (output ), strerr , err
414
408
}
415
409
410
+ // separateEvalStmt separates what can be evaluated via evalExpr from what cannot.
411
+ func (s * Session ) separateEvalStmt (in string ) error {
412
+ var stmtLines []string
413
+ var exprCount int
414
+
415
+ inLines := strings .Split (in , "\n " )
416
+
417
+ for _ , line := range inLines {
418
+
419
+ priorLen := len (s .mainBody .List )
420
+
421
+ if _ , err := s .evalExpr (line ); err != nil {
422
+ stmtLines = append (stmtLines , line )
423
+ continue
424
+ }
425
+
426
+ if len (stmtLines ) != 0 {
427
+
428
+ currentLen := len (s .mainBody .List )
429
+ trimNum := currentLen - priorLen
430
+ s .mainBody .List = s .mainBody .List [0 : currentLen - trimNum ]
431
+
432
+ if err := s .evalStmt (strings .Join (stmtLines , "\n " ), true ); err != nil {
433
+ return err
434
+ }
435
+ stmtLines = []string {}
436
+
437
+ if _ , err := s .evalExpr (line ); err != nil {
438
+ return err
439
+ }
440
+ }
441
+
442
+ exprCount ++
443
+ }
444
+
445
+ if len (stmtLines ) != 0 {
446
+ var noPrint bool
447
+ if exprCount > 0 {
448
+ noPrint = true
449
+ }
450
+ if err := s .evalStmt (strings .Join (stmtLines , "\n " ), noPrint ); err != nil {
451
+ return err
452
+ }
453
+ }
454
+
455
+ return nil
456
+ }
457
+
416
458
// storeMainBody stores current state of code so that it can be restored
417
459
// actually it saves the length of statements inside main()
418
460
func (s * Session ) storeMainBody () {
0 commit comments