doEval evaluates the code in the interpreter. This function captures an uncaught panic as well as the values of the last statement/expression.
(ir *interp.Interp, outerr OutErr, code string)
| 539 | // doEval evaluates the code in the interpreter. This function captures an uncaught panic |
| 540 | // as well as the values of the last statement/expression. |
| 541 | func doEval(ir *interp.Interp, outerr OutErr, code string) (val []interface{}, typ []xreflect.Type, err error) { |
| 542 | |
| 543 | // Capture a panic from the evaluation if one occurs and store it in the `err` return parameter. |
| 544 | defer func() { |
| 545 | if r := recover(); r != nil { |
| 546 | var ok bool |
| 547 | if err, ok = r.(error); !ok { |
| 548 | err = errors.New(fmt.Sprint(r)) |
| 549 | } |
| 550 | } |
| 551 | }() |
| 552 | |
| 553 | code = evalSpecialCommands(ir, outerr, code) |
| 554 | |
| 555 | // Prepare and perform the multiline evaluation. |
| 556 | compiler := ir.Comp |
| 557 | |
| 558 | // Don't show the gomacro prompt. |
| 559 | compiler.Options &^= base.OptShowPrompt |
| 560 | |
| 561 | // Don't swallow panics as they are recovered above and handled with a Jupyter `error` message instead. |
| 562 | compiler.Options &^= base.OptTrapPanic |
| 563 | |
| 564 | // Reset the error line so that error messages correspond to the lines from the cell. |
| 565 | compiler.Line = 0 |
| 566 | |
| 567 | // Parse the input code (and don't perform gomacro's macroexpansion). |
| 568 | // These may panic but this will be recovered by the deferred recover() above so that the error |
| 569 | // may be returned instead. |
| 570 | nodes := compiler.ParseBytes([]byte(code)) |
| 571 | srcAst := ast2.AnyToAst(nodes, "doEval") |
| 572 | |
| 573 | // If there is no srcAst then we must be evaluating nothing. The result must be nil then. |
| 574 | if srcAst == nil { |
| 575 | return nil, nil, nil |
| 576 | } |
| 577 | |
| 578 | // Check if the last node is an expression. If the last node is not an expression then nothing |
| 579 | // is returned as a value. For example evaluating a function declaration shouldn't return a value but |
| 580 | // just have the side effect of declaring the function. |
| 581 | // |
| 582 | // This is actually needed only for gomacro classic interpreter |
| 583 | // (the fast interpreter already returns values only for expressions) |
| 584 | // but retained for compatibility. |
| 585 | var srcEndsWithExpr bool |
| 586 | if len(nodes) > 0 { |
| 587 | _, srcEndsWithExpr = nodes[len(nodes)-1].(ast.Expr) |
| 588 | } |
| 589 | |
| 590 | // Compile the ast. |
| 591 | compiledSrc := ir.CompileAst(srcAst) |
| 592 | |
| 593 | // Evaluate the code. |
| 594 | results, types := ir.RunExpr(compiledSrc) |
| 595 | |
| 596 | // If the source ends with an expression, then the result of the execution is the value of the expression. In the |
| 597 | // event that all return values are nil, the result is also nil. |
| 598 | if srcEndsWithExpr { |
no test coverage detected