Skip to content

Commit e90ecb7

Browse files
committed
Output all return values from the last expression if not all nil
1 parent 8094aa5 commit e90ecb7

File tree

1 file changed

+25
-10
lines changed

1 file changed

+25
-10
lines changed

kernel.go

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
336336
io.Copy(&jupyterStdErr, rErr)
337337
}()
338338

339-
val, executionErr := doEval(ir, code)
339+
vals, executionErr := doEval(ir, code)
340340

341341
//TODO if value is a certain type like image then display it instead
342342

@@ -354,9 +354,9 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
354354
content["status"] = "ok"
355355
content["user_expressions"] = make(map[string]string)
356356

357-
if !silent && val != nil {
357+
if !silent && vals != nil {
358358
// Publish the result of the execution.
359-
if err := receipt.PublishExecutionResult(ExecCounter, fmt.Sprint(val)); err != nil {
359+
if err := receipt.PublishExecutionResult(ExecCounter, fmt.Sprint(vals...)); err != nil {
360360
log.Printf("Error publishing execution result: %v\n", err)
361361
}
362362
}
@@ -376,8 +376,8 @@ func handleExecuteRequest(ir *classic.Interp, receipt msgReceipt) error {
376376
}
377377

378378
// doEval evaluates the code in the interpreter. This function captures an uncaught panic
379-
// as well as the value of the last statement/expression.
380-
func doEval(ir *classic.Interp, code string) (_ interface{}, err error) {
379+
// as well as the values of the last statement/expression.
380+
func doEval(ir *classic.Interp, code string) (_ []interface{}, err error) {
381381
// Capture a panic from the evaluation if one occurs and store it in the `err` return parameter.
382382
defer func() {
383383
if r := recover(); r != nil {
@@ -390,8 +390,11 @@ func doEval(ir *classic.Interp, code string) (_ interface{}, err error) {
390390

391391
// Prepare and perform the multiline evaluation.
392392
env := ir.Env
393+
// Don't show the gomacro prompt.
393394
env.Options &^= base.OptShowPrompt
395+
// Don't swallow panics as they are recovered above and handled with a Jupyter `error` message instead.
394396
env.Options &^= base.OptTrapPanic
397+
// Reset the error line so that error messages correspond to the lines from the cell
395398
env.Line = 0
396399

397400
// Parse the input code (and don't preform gomacro's macroexpansion).
@@ -405,7 +408,8 @@ func doEval(ir *classic.Interp, code string) (_ interface{}, err error) {
405408
var srcEndsWithExpr bool
406409

407410
// If the parsed ast is a single node, check if the node implements `ast.Expr`. Otherwise if the is multiple
408-
// nodes then just check if the last one is an expression.
411+
// nodes then just check if the last one is an expression. These are currently the 2 cases to consider from
412+
// gomacro's `ParseOnly`.
409413
if srcAstWithNode, ok := src.(ast2.AstWithNode); ok {
410414
_, srcEndsWithExpr = srcAstWithNode.Node().(ast.Expr)
411415
} else if srcNodeSlice, ok := src.(ast2.NodeSlice); ok {
@@ -417,20 +421,31 @@ func doEval(ir *classic.Interp, code string) (_ interface{}, err error) {
417421
result, results := ir.EvalAst(src)
418422

419423
// If the source ends with an expression, then the result of the execution is the value of the expression. In the
420-
// case of multiple return values (from a function call for example), the first non-nil value is the result.
424+
// event that all return values are nil, then the
421425
if srcEndsWithExpr {
422426
// `len(results) == 0` implies a single result stored in `result`.
423427
if len(results) == 0 {
424-
return base.ValueInterface(result), nil
428+
if val := base.ValueInterface(result); val != nil {
429+
return []interface{}{val}, nil
430+
}
431+
return nil, nil
425432
}
426433

427-
// Set `val` to be the first non-nil result.
434+
// Count the number of non-nil values in the output. If they are all nil then the output is skipped.
435+
nonNilCount := 0
436+
var values []interface{}
428437
for _, result := range results {
429438
val := base.ValueInterface(result)
430439
if val != nil {
431-
return val, nil
440+
nonNilCount++
432441
}
442+
values = append(values, val)
443+
}
444+
445+
if nonNilCount > 0 {
446+
return values, nil
433447
}
448+
return nil, nil
434449
}
435450

436451
return nil, nil

0 commit comments

Comments
 (0)