@@ -154,65 +154,103 @@ func goRun(files []string) ([]byte, bytes.Buffer, error) {
154154 return out , stderr , err
155155}
156156
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+ }
175162
176- s .appendStatements (stmt )
163+ stmt := & ast.ExprStmt {
164+ X : & ast.CallExpr {
165+ Fun : ast .NewIdent (printerName ),
166+ Args : []ast.Expr {expr },
167+ },
177168 }
178169
179- return exprs , nil
170+ s .appendStatements (stmt )
171+
172+ return expr , nil
180173}
181174
182175func isNamedIdent (expr ast.Expr , name string ) bool {
183176 ident , ok := expr .(* ast.Ident )
184177 return ok && ident .Name == name
185178}
186179
187- func (s * Session ) evalStmt (in string ) error {
180+ func (s * Session ) evalStmt (in string , noPrint bool ) error {
188181 src := fmt .Sprintf ("package P; func F() { %s }" , in )
189182 f , err := parser .ParseFile (s .Fset , "stmt.go" , src , parser .Mode (0 ))
190183 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+
192226 }
193227
194228 enclosingFunc := f .Scope .Lookup ("F" ).Decl .(* ast.FuncDecl )
195229 stmts := enclosingFunc .Body .List
196230
197231 if len (stmts ) > 0 {
232+
198233 debugf ("evalStmt :: %s" , showNode (s .Fset , stmts ))
199234 lastStmt := stmts [len (stmts )- 1 ]
235+
200236 // 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+ }
206244 }
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 )
214253 }
215- stmts = append (stmts , printLastValues )
216254 }
217255 }
218256 }
@@ -345,53 +383,9 @@ func (s *Session) Eval(in string) (string, bytes.Buffer, error) {
345383 return "" , bytes.Buffer {}, nil
346384 }
347385
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
395389 }
396390
397391 s .doQuickFix ()
@@ -413,6 +407,54 @@ func (s *Session) Eval(in string) (string, bytes.Buffer, error) {
413407 return string (output ), strerr , err
414408}
415409
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+
416458// storeMainBody stores current state of code so that it can be restored
417459// actually it saves the length of statements inside main()
418460func (s * Session ) storeMainBody () {
0 commit comments