APIs
OpenTerminal,EnterTerminalScreen,GetTerminalSize,WriteTerminal,ReadTerminalEvent,TerminalCursor,TerminalColor,ShowTerminalCursor,SuspendTerminal,ResumeTerminal,Close.ReadTerminalEvent(terminal, duration)returnsOPTIONAL OF TerminalEvent: NONE is timeout; SOME with Kind 0 is EOF. Text, keys, resize and paste-boundary events have distinct kinds. Escape ambiguity has a bounded decoding timeout.TerminalTextWidthandTerminalClipTextuse checked cell ranges and pinned Unicode widths. They are scalar-width facilities, not a grapheme shaping engine.Stdin(),Stdout(),Stderr(),OpenFile(path, mode="r"),Close,Flush,ReadFileInto,WriteFile,GetFileInfo,ReadFileSnapshot,WriteFileAtomic,ReadDirectory,MakeDirectory,SetFilePermissions.StartProcess(executable, arguments, directory=".", interactive=FALSE),RunProcess,RunInteractive,ProcessExited,WaitProcess,TerminateProcess,WriteProcess,CloseProcessInput,ReadProcessInto,TryReadProcessInto.OpenPseudoTerminal,PseudoTerminalName,TryReadPseudoTerminalInto,WritePseudoTerminalsupport debugger inferior terminal I/O.
Standard streams as File values
Stdin(), Stdout() and Stderr() each return a fresh owned File, with
FAILS IoError. They duplicate the currently inherited stream handle, preserving
redirection to terminals, pipes or files. Closing or destroying that File closes
only its duplicate; the original process stream remains available to PRINT,
INPUT, ReadByte, WriteAll and WriteErrorText. Named handles require explicit TAKE
when transferred into a buffer, task or another owner. Fresh results can be
passed directly, for example BufferedWriter(Stdout()).
These are independent handle owners, not independent byte streams: duplicates share the underlying stream position, EOF and file status flags. Use one buffered reader per input stream; read-ahead can otherwise consume bytes another reader expects. Separate writers do not provide implicit synchronization or message atomicity. The factories do not change blocking flags. Read-only borrowing of a File does not freeze this external OS state.
writer = BufferedWriter(Stdout())
WriteLine(BYREF writer, "Hello, λ")
Flush(BYREF writer)
WriteFile(Stderr(), "diagnostic" + CHR(10))Buffer cleanup discards pending output. Call Flush(BYREF writer) or
Finish(TAKE writer) to send it and observe write failures. That buffer Flush
does not call fsync; Flush(file) does and may fail on a pipe or terminal.
ReadFileInto and buffered reads use the existing bounded File workers. A blocking
pipe read can require peer data/EOF before cancellation can acknowledge the
kernel operation; cleanup retains its storage and handle until then. File writes
remain synchronous.
Processes, scheduling and failures
RunProcess accepts exact UTF-8 argv elements and never inserts a shell. It pumps input, stdout and stderr together, preventing the usual full-pipe deadlock. Outputs are byte lists; UTF-8 decoding is explicit. Nonblocking reads return NONE for not-ready and SOME(0) for EOF. Captured output is currently unbounded growable storage; application limits/streaming are follow-up work. Environment inheritance reads the process’s initial Linux environment; there is no BASIL environment mutation API yet.
Terminal input/output, process pipes, pidfd completion and resize self-pipe waits park the current coroutine. The sole scheduler thread owns wait registrations. Events and timers only mark/wake tasks; BASIL resumes after polling returns. Readiness callbacks never re-enter BASIL application code inside the native poll loop. Multiple waits detach deterministically on completion, timeout and cancellation. SQLite’s bounded worker completion eventfd participates in the same idle wait (native component ABI 2), so terminal/pipe I/O cannot hide completed database work.
Regular file open/read/stat/directory/seek use a bounded worker pool and acknowledge cancellation before releasing retained buffers/handles. Writes/fsync and some mutations remain synchronous and can block the coordinator. This implementation does not claim that all filesystem work is asynchronous. See worker integration .
Recoverable syscall failures use IoError with positive Linux errno. File version conflicts use FileChanged. Allocation failure is fatal with a best-effort diagnostic, with no normal application cleanup guarantee. Native terminal cleanup restores original descriptor flags, termios and resize signal action, closes its self-pipe, and leaves the alternate screen. Abnormal external termination can still prevent application cleanup.