The current signature of WriteBlock looks like this:
protected abstract void WriteBlock(BlockExpression expr, object? metadata);
where metadata is language-specific information about how the block needs to be formatted.
Instead, we could create our own custom expression types which would contain this information.
When at a containing expression, we could generate an instance of the custom expression type and pass that into WriteNode. It would forward the expression to WriteExtension, which would be overridden in the formatter to handle these custom types.