107 lines
3.4 KiB
C++
107 lines
3.4 KiB
C++
#pragma once
|
|
/**
|
|
* @file
|
|
* @brief Common printing functions for the Nix language
|
|
*
|
|
* While most types come with their own methods for printing, they share some
|
|
* functions that are placed here.
|
|
*/
|
|
|
|
#include <iostream>
|
|
|
|
#include "fmt.hh"
|
|
#include "print-options.hh"
|
|
#include "print-elided.hh"
|
|
|
|
namespace nix {
|
|
|
|
struct Expr;
|
|
|
|
class EvalState;
|
|
struct Value;
|
|
|
|
/** Print `true` or `false`. */
|
|
std::ostream & printLiteralBool(std::ostream & o, bool b);
|
|
|
|
/**
|
|
* Print a string as an attribute name in the Nix expression language syntax.
|
|
*
|
|
* Prints a quoted string if necessary.
|
|
*/
|
|
std::ostream & printAttributeName(std::ostream & o, std::string_view s);
|
|
|
|
/**
|
|
* Returns `true' is a string is a reserved keyword which requires quotation
|
|
* when printing attribute set field names.
|
|
*/
|
|
bool isReservedKeyword(const std::string_view str);
|
|
|
|
/**
|
|
* Print a string as an identifier in the Nix expression language syntax.
|
|
*
|
|
* FIXME: "identifier" is ambiguous. Identifiers do not have a single
|
|
* textual representation. They can be used in variable references,
|
|
* let bindings, left-hand sides or attribute names in a select
|
|
* expression, or something else entirely, like JSON. Use one of the
|
|
* `print*` functions instead.
|
|
*/
|
|
std::ostream & printIdentifier(std::ostream & o, std::string_view s);
|
|
|
|
void printValue(EvalState & state, std::ostream & str, Value & v, PrintOptions options = PrintOptions {});
|
|
|
|
/**
|
|
* A partially-applied form of `printValue` which can be formatted using `<<`
|
|
* without allocating an intermediate string.
|
|
* This class should not outlive the eval state or it will UAF.
|
|
* FIXME: This should take `nix::ref`s, to avoid that, but our eval methods all have
|
|
* EvalState &, not ref<EvalState>, and constructing a new shared_ptr to data that
|
|
* already has a shared_ptr is a much bigger footgun. In the current architecture of
|
|
* libexpr, using a ValuePrinter after an EvalState has been destroyed would be
|
|
* pretty hard.
|
|
*/
|
|
class ValuePrinter {
|
|
friend std::ostream & operator << (std::ostream & output, const ValuePrinter & printer);
|
|
private:
|
|
EvalState & state;
|
|
Value & value;
|
|
PrintOptions options;
|
|
|
|
public:
|
|
ValuePrinter(EvalState & state, Value & value, PrintOptions options = PrintOptions {})
|
|
: state(state), value(value), options(options) { }
|
|
};
|
|
|
|
std::ostream & operator<<(std::ostream & output, const ValuePrinter & printer);
|
|
|
|
|
|
/**
|
|
* `ValuePrinter` does its own ANSI formatting, so we don't color it
|
|
* magenta.
|
|
*/
|
|
template<>
|
|
fmt_internal::HintFmt & fmt_internal::HintFmt::operator%(const ValuePrinter & value);
|
|
|
|
/**
|
|
* A partially-applied form of Expr::show(), which can be formatted using `<<`
|
|
* without allocating an intermediate string.
|
|
* This class should not outlive the eval state or it will UAF.
|
|
* FIXME: This should take `nix::ref`s, to avoid that, but our eval methods all have
|
|
* EvalState &, not ref<EvalState>, and constructing a new shared_ptr to data that
|
|
* already has a shared_ptr is a much bigger footgun. In the current architecture of
|
|
* libexpr, using an ExprPrinter after an EvalState has been destroyed would be
|
|
* pretty hard.
|
|
*/
|
|
class ExprPrinter
|
|
{
|
|
/** The eval state used to get symbols. */
|
|
EvalState const & state;
|
|
/** The expression to print. */
|
|
Expr const & expr;
|
|
|
|
public:
|
|
ExprPrinter(EvalState const & state, Expr const & expr) : state(state), expr(expr) { }
|
|
friend std::ostream & operator << (std::ostream & output, ExprPrinter const & printer);
|
|
};
|
|
|
|
}
|