Running a cell: the prompt and the Jupyter kernel

The terminal prompt and the optional Xeus kernel run cells with FortranEvaluator::execute(code, verbose, io) (src/lfortran/fortran_evaluator.h). It evaluates one cell like evaluate(), with fresh diagnostics and the default passes, and also runs the %%showast, %%showasr, %%showllvm, %%showasm, %%showcpp and %%showfmt inspection cells (the magic is the first line of the cell; trailing blanks and a CRLF line ending are ignored). An inspection cell sees the session’s declarations, but it does not run, so its own declarations do not join the session. CompilerOptions::interactive must be set before the first cell; the evaluator keeps the session’s symbols across cells (see Interactive evaluation: one TranslationUnit per cell). A failed cell is not rolled back.

The returned CellResult holds the typed EvalResult (or, when inspection is set, the inspection output) and the rendered diagnostics; those of a successful cell are its warnings, which both frontends show. For a failed cell it holds an error name and message: CompilerError with the rendered diagnostics, DisplayError, or, for an internal compiler error (internal_error), the exception’s name and message, with its stack trace apart in error_traceback. CellResult::error_text() is what a frontend shows for it. The kernel sends the message as the Jupyter evalue and the stack trace as the traceback.

EvalResult::text() formats a value the way the prompt and the kernel show it: for real and complex, the shortest text that reads back as the same value (at most 9/17 significant digits), always with a decimal point or an exponent, so that 1.0 is not shown as 1; True/False; character text. EvalResult::has_value() is false for statements and empty cells.

The lfortran_display module’s display_data and clear_output call the lfortran_display_data and lfortran_clear_output C functions of the runtime library. While execute() runs a cell, it registers hooks and a context with the runtime (_lfortran_set_display_hooks) that forward to that cell’s CellIO, including in WASM; at any other time, and in compiled programs, the functions do nothing. The hooks are process-wide, so cells must not run concurrently. An exception thrown by a hook does not unwind through generated code; the cell fails with DisplayError and the exception’s message. The module is built with or without Xeus. execute() does not capture stdout/stderr; that is up to the frontend. Jupyter messages must be UTF-8, so the kernel shows any other bytes of a cell’s output as U+FFFD.

The test_lfortran cases FortranEvaluator execute: * (also run in the WASM build of the JupyterLite kernel), test_repl and, in Xeus builds, test_kernel_evaluation cover this; the display_data_01 integration test covers compiled programs. The complex-result cases of test_lfortran also exercise the JIT result ABI on Windows: there complex(4) comes back as two float bit patterns in an integer register and complex(8) through an output pointer, and FortranEvaluator calls those signatures explicitly rather than relying on the C++ std::complex return convention.