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.