2013-07-23 01:30:25 +00:00
|
|
|
/*
|
2013-07-25 00:50:51 +00:00
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
2013-07-23 01:30:25 +00:00
|
|
|
|
2013-07-25 00:50:51 +00:00
|
|
|
Author: Soonho Kong
|
2013-07-23 01:30:25 +00:00
|
|
|
*/
|
2013-08-09 01:35:49 +00:00
|
|
|
#include <sstream>
|
2013-09-13 10:35:29 +00:00
|
|
|
#include <string>
|
|
|
|
#include <utility>
|
2013-09-13 03:04:10 +00:00
|
|
|
#include "util/escaped.h"
|
|
|
|
#include "util/sexpr/sexpr.h"
|
|
|
|
#include "util/sexpr/format.h"
|
|
|
|
#include "util/sexpr/sexpr_fn.h"
|
|
|
|
#include "util/sexpr/options.h"
|
2013-08-09 01:35:49 +00:00
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
#ifndef LEAN_DEFAULT_PP_INDENTATION
|
|
|
|
#define LEAN_DEFAULT_PP_INDENTATION 4
|
2013-08-09 01:35:49 +00:00
|
|
|
#endif
|
|
|
|
|
2013-09-03 17:09:19 +00:00
|
|
|
#ifndef LEAN_DEFAULT_PP_UNICODE
|
|
|
|
#define LEAN_DEFAULT_PP_UNICODE true
|
|
|
|
#endif
|
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
#ifndef LEAN_DEFAULT_PP_WIDTH
|
|
|
|
#define LEAN_DEFAULT_PP_WIDTH 120
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LEAN_DEFAULT_PP_COLORS
|
|
|
|
#define LEAN_DEFAULT_PP_COLORS true
|
2013-08-09 01:35:49 +00:00
|
|
|
#endif
|
2013-07-23 01:30:25 +00:00
|
|
|
|
2013-08-15 15:32:13 +00:00
|
|
|
#ifndef LEAN_KEYWORD_HIGHLIGHT_COLOR
|
|
|
|
#define LEAN_KEYWORD_HIGHLIGHT_COLOR format::ORANGE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LEAN_BUILTIN_HIGHLIGHT_COLOR
|
|
|
|
#define LEAN_BUILTIN_HIGHLIGHT_COLOR format::CYAN
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LEAN_COMMAND_HIGHLIGHT_COLOR
|
|
|
|
#define LEAN_COMMAND_HIGHLIGHT_COLOR format::BLUE
|
|
|
|
#endif
|
|
|
|
|
2013-07-23 01:30:25 +00:00
|
|
|
namespace lean {
|
2013-08-13 23:19:30 +00:00
|
|
|
static name g_pp_indent{"pp", "indent"};
|
2013-09-03 17:09:19 +00:00
|
|
|
static name g_pp_unicode{"pp", "unicode"};
|
2013-08-13 23:19:30 +00:00
|
|
|
static name g_pp_colors{"pp", "colors"};
|
|
|
|
static name g_pp_width{"pp", "width"};
|
|
|
|
|
2013-08-21 23:43:59 +00:00
|
|
|
RegisterUnsignedOption(g_pp_indent, LEAN_DEFAULT_PP_INDENTATION, "(pretty printer) default indentation");
|
2013-09-03 17:09:19 +00:00
|
|
|
RegisterBoolOption(g_pp_unicode, LEAN_DEFAULT_PP_UNICODE, "(pretty printer) use unicode characters");
|
2013-08-21 23:43:59 +00:00
|
|
|
RegisterBoolOption(g_pp_colors, LEAN_DEFAULT_PP_COLORS, "(pretty printer) use colors");
|
|
|
|
RegisterUnsignedOption(g_pp_width, LEAN_DEFAULT_PP_WIDTH, "(pretty printer) line width");
|
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
unsigned get_pp_indent(options const & o) {
|
2013-08-16 01:54:01 +00:00
|
|
|
return o.get_unsigned(g_pp_indent, LEAN_DEFAULT_PP_INDENTATION);
|
2013-08-13 23:19:30 +00:00
|
|
|
}
|
|
|
|
|
2013-09-03 17:09:19 +00:00
|
|
|
bool get_pp_unicode(options const & o) {
|
|
|
|
return o.get_bool(g_pp_unicode, LEAN_DEFAULT_PP_UNICODE);
|
|
|
|
}
|
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
bool get_pp_colors(options const & o) {
|
|
|
|
return o.get_bool(g_pp_colors, LEAN_DEFAULT_PP_COLORS);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned get_pp_width(options const & o) {
|
2013-08-16 01:54:01 +00:00
|
|
|
return o.get_unsigned(g_pp_width, LEAN_DEFAULT_PP_WIDTH);
|
2013-08-13 23:19:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream & layout(std::ostream & out, bool colors, sexpr const & s) {
|
2013-07-25 00:50:51 +00:00
|
|
|
lean_assert(!is_nil(s));
|
|
|
|
switch (format::sexpr_kind(s)) {
|
|
|
|
case format::format_kind::NEST:
|
|
|
|
case format::format_kind::CHOICE:
|
|
|
|
case format::format_kind::COMPOSE:
|
2013-08-22 05:45:48 +00:00
|
|
|
case format::format_kind::FLAT_COMPOSE:
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-25 00:50:51 +00:00
|
|
|
|
|
|
|
case format::format_kind::NIL:
|
|
|
|
out << "";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case format::format_kind::LINE:
|
|
|
|
out << std::endl;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case format::format_kind::TEXT:
|
|
|
|
{
|
|
|
|
sexpr const & v = cdr(s);
|
2013-09-13 23:14:24 +00:00
|
|
|
if (is_string(v)) {
|
2013-07-25 00:50:51 +00:00
|
|
|
out << to_string(v);
|
|
|
|
} else {
|
|
|
|
out << v;
|
2013-07-23 23:21:04 +00:00
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case format::format_kind::COLOR_BEGIN:
|
2013-08-13 23:19:30 +00:00
|
|
|
if (colors) {
|
|
|
|
format::format_color c = static_cast<format::format_color>(to_int(cdr(s)));
|
|
|
|
out << "\e[" << (31 + c % 7) << "m";
|
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
break;
|
|
|
|
case format::format_kind::COLOR_END:
|
2013-08-13 23:19:30 +00:00
|
|
|
if (colors) {
|
|
|
|
out << "\e[0m";
|
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
break;
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
2013-07-23 23:21:04 +00:00
|
|
|
return out;
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
std::ostream & layout_list(std::ostream & out, bool colors, sexpr const & s) {
|
|
|
|
for_each(s, [&](sexpr const & s) {
|
|
|
|
layout(out, colors, s);
|
2013-07-25 00:50:51 +00:00
|
|
|
});
|
|
|
|
return out;
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-07-25 00:50:51 +00:00
|
|
|
format compose(format const & f1, format const & f2) {
|
|
|
|
return format(format::sexpr_compose({f1.m_value, f2.m_value}));
|
|
|
|
}
|
|
|
|
format nest(int i, format const & f) {
|
|
|
|
return format(format::sexpr_nest(i, f.m_value));
|
|
|
|
}
|
|
|
|
format highlight(format const & f, format::format_color const c) {
|
|
|
|
return format(format::sexpr_highlight(f.m_value, c));
|
|
|
|
}
|
2013-08-15 15:32:13 +00:00
|
|
|
format highlight_keyword(format const & f) {
|
|
|
|
return highlight(f, LEAN_KEYWORD_HIGHLIGHT_COLOR);
|
|
|
|
}
|
|
|
|
format highlight_builtin(format const & f) {
|
|
|
|
return highlight(f, LEAN_BUILTIN_HIGHLIGHT_COLOR);
|
|
|
|
}
|
|
|
|
format highlight_command(format const & f) {
|
|
|
|
return highlight(f, LEAN_COMMAND_HIGHLIGHT_COLOR);
|
|
|
|
}
|
2013-08-09 01:35:49 +00:00
|
|
|
// Commonly used format objects
|
|
|
|
format mk_line() {
|
2013-07-25 00:50:51 +00:00
|
|
|
return format(format::sexpr_line());
|
|
|
|
}
|
2013-08-09 01:35:49 +00:00
|
|
|
static format g_line(mk_line());
|
|
|
|
static format g_space(" ");
|
|
|
|
static format g_lp("(");
|
|
|
|
static format g_rp(")");
|
2013-09-13 01:25:38 +00:00
|
|
|
static format g_lsb("[");
|
|
|
|
static format g_rsb("]");
|
2013-08-27 01:46:16 +00:00
|
|
|
static format g_lcurly("{");
|
|
|
|
static format g_rcurly("}");
|
2013-08-09 01:35:49 +00:00
|
|
|
static format g_comma(",");
|
2013-08-14 02:12:23 +00:00
|
|
|
static format g_colon(":");
|
2013-08-09 01:35:49 +00:00
|
|
|
static format g_dot(".");
|
2013-08-27 01:46:16 +00:00
|
|
|
format const & line() { return g_line; }
|
|
|
|
format const & space() { return g_space; }
|
|
|
|
format const & lp() { return g_lp; }
|
|
|
|
format const & rp() { return g_rp; }
|
2013-09-13 01:25:38 +00:00
|
|
|
format const & lsb() { return g_lsb; }
|
|
|
|
format const & rsb() { return g_rsb; }
|
2013-08-27 01:46:16 +00:00
|
|
|
format const & lcurly() { return g_lcurly; }
|
|
|
|
format const & rcurly() { return g_rcurly; }
|
|
|
|
format const & comma() { return g_comma; }
|
|
|
|
format const & colon() { return g_colon; }
|
|
|
|
format const & dot() { return g_dot; }
|
2013-08-22 05:54:58 +00:00
|
|
|
// Auxiliary flag used to mark whether flatten
|
|
|
|
// produce a different sexpr
|
|
|
|
static bool thread_local g_diff_flatten = false;
|
2013-08-09 01:35:49 +00:00
|
|
|
//
|
2013-07-25 00:50:51 +00:00
|
|
|
sexpr format::flatten(sexpr const & s) {
|
|
|
|
lean_assert(is_cons(s));
|
|
|
|
switch (sexpr_kind(s)) {
|
|
|
|
case format_kind::NIL:
|
|
|
|
/* flatten NIL = NIL */
|
|
|
|
return s;
|
|
|
|
case format_kind::NEST:
|
|
|
|
/* flatten (NEST i x) = flatten x */
|
|
|
|
return flatten(sexpr_nest_s(s));
|
|
|
|
case format_kind::COMPOSE:
|
|
|
|
/* flatten (s_1 <> ... <> s_n ) = flatten s_1 <> ... <> flatten s_n */
|
2013-08-22 05:45:48 +00:00
|
|
|
return sexpr_flat_compose(map(sexpr_compose_list(s),
|
|
|
|
[](sexpr const & s) {
|
|
|
|
return flatten(s);
|
|
|
|
}));
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::CHOICE:
|
|
|
|
/* flatten (x <|> y) = flatten x */
|
2013-08-22 05:54:58 +00:00
|
|
|
g_diff_flatten = true;
|
2013-07-25 00:50:51 +00:00
|
|
|
return flatten(sexpr_choice_1(s));
|
|
|
|
case format_kind::LINE:
|
2013-08-22 05:54:58 +00:00
|
|
|
g_diff_flatten = true;
|
2013-08-03 02:16:19 +00:00
|
|
|
return sexpr_text(sexpr(" "));
|
2013-08-22 05:45:48 +00:00
|
|
|
case format_kind::FLAT_COMPOSE:
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::TEXT:
|
|
|
|
case format_kind::COLOR_BEGIN:
|
|
|
|
case format_kind::COLOR_END:
|
|
|
|
return s;
|
|
|
|
}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
format format::flatten(format const & f){
|
|
|
|
return format(flatten(f.m_value));
|
|
|
|
}
|
|
|
|
format group(format const & f) {
|
2013-08-22 05:54:58 +00:00
|
|
|
g_diff_flatten = false;
|
|
|
|
format flat_f = format::flatten(f);
|
|
|
|
if (g_diff_flatten) {
|
|
|
|
return choice(flat_f, f);
|
|
|
|
} else {
|
|
|
|
// flat_f and f are essentially the same format object.
|
|
|
|
// So, we don't need to create a choice.
|
|
|
|
return flat_f;
|
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
format above(format const & f1, format const & f2) {
|
|
|
|
return format{f1, line(), f2};
|
|
|
|
}
|
2013-10-01 04:36:56 +00:00
|
|
|
format bracket(std::string const & l, format const & x, std::string const & r) {
|
2013-09-13 01:25:38 +00:00
|
|
|
return group(nest(l.size(), format{format(l), x, format(r)}));
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
2013-08-02 01:03:51 +00:00
|
|
|
format paren(format const & x) {
|
2013-09-04 20:21:57 +00:00
|
|
|
return group(nest(1, format{lp(), x, rp()}));
|
2013-08-02 01:03:51 +00:00
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
|
|
|
|
// wrap = <+/>
|
|
|
|
// wrap x y = x <> (text " " :<|> line) <> y
|
|
|
|
format wrap(format const & f1, format const & f2) {
|
|
|
|
return format{f1,
|
|
|
|
choice(format(" "), line()),
|
|
|
|
f2};
|
|
|
|
}
|
2013-08-08 17:34:15 +00:00
|
|
|
|
2013-09-13 20:46:22 +00:00
|
|
|
/**
|
|
|
|
\brief Auxiliary exception used to sign that the amount of
|
|
|
|
available space was exhausted. It is used in \c space_upto_line_break and
|
|
|
|
\c space_upto_line_break_list_exceeded
|
|
|
|
*/
|
2013-08-22 05:45:48 +00:00
|
|
|
struct space_exceeded {};
|
|
|
|
|
|
|
|
// Return true iff the space upto line break fits in the available space.
|
|
|
|
bool format::space_upto_line_break_list_exceeded(sexpr const & r, int available) {
|
2013-08-08 17:34:15 +00:00
|
|
|
// r : list of (int * format)
|
2013-08-22 05:45:48 +00:00
|
|
|
try {
|
|
|
|
lean_assert(is_list(r));
|
|
|
|
sexpr list = r;
|
|
|
|
bool found_newline = false;
|
|
|
|
while (!is_nil(list) && !found_newline) {
|
|
|
|
if (available < 0)
|
|
|
|
return true;
|
|
|
|
sexpr const & h = cdr(car(list));
|
|
|
|
available -= space_upto_line_break(h, available, found_newline);
|
|
|
|
list = cdr(list);
|
|
|
|
}
|
|
|
|
return available < 0;
|
|
|
|
} catch (space_exceeded) {
|
|
|
|
return true;
|
2013-08-08 17:34:15 +00:00
|
|
|
}
|
2013-08-22 05:45:48 +00:00
|
|
|
return false;
|
2013-08-08 17:34:15 +00:00
|
|
|
}
|
|
|
|
|
2013-08-22 05:45:48 +00:00
|
|
|
/**
|
|
|
|
\brief Return the space upto line break. If the space exceeds available, then throw an exception.
|
|
|
|
*/
|
|
|
|
int format::space_upto_line_break(sexpr const & s, int available, bool & found_newline) {
|
2013-08-08 17:34:15 +00:00
|
|
|
// s : format
|
2013-08-08 18:45:06 +00:00
|
|
|
lean_assert(!found_newline);
|
|
|
|
lean_assert(sexpr_kind(s) <= format_kind::COLOR_END);
|
2013-07-23 23:21:04 +00:00
|
|
|
|
2013-08-08 17:34:15 +00:00
|
|
|
switch (sexpr_kind(s)) {
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::NIL:
|
|
|
|
case format_kind::COLOR_BEGIN:
|
|
|
|
case format_kind::COLOR_END:
|
2013-08-08 18:45:06 +00:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2013-08-08 17:34:15 +00:00
|
|
|
case format_kind::COMPOSE:
|
2013-08-22 05:45:48 +00:00
|
|
|
case format_kind::FLAT_COMPOSE:
|
2013-07-25 00:50:51 +00:00
|
|
|
{
|
2013-08-08 17:34:15 +00:00
|
|
|
sexpr list = sexpr_compose_list(s);
|
2013-08-22 05:45:48 +00:00
|
|
|
int len = 0;
|
2013-09-13 23:14:24 +00:00
|
|
|
while (!is_nil(list) && !found_newline) {
|
2013-08-08 17:34:15 +00:00
|
|
|
sexpr const & h = car(list);
|
|
|
|
list = cdr(list);
|
2013-08-22 05:45:48 +00:00
|
|
|
len += space_upto_line_break(h, available, found_newline);
|
|
|
|
if (len > available)
|
|
|
|
throw space_exceeded();
|
2013-08-02 01:03:51 +00:00
|
|
|
}
|
2013-08-08 18:45:06 +00:00
|
|
|
return len;
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
case format_kind::NEST:
|
2013-08-08 17:34:15 +00:00
|
|
|
{
|
|
|
|
sexpr const & x = sexpr_nest_s(s);
|
2013-08-22 05:45:48 +00:00
|
|
|
return space_upto_line_break(x, available, found_newline);
|
2013-08-08 18:45:06 +00:00
|
|
|
}
|
|
|
|
case format_kind::TEXT: {
|
|
|
|
return sexpr_text_length(s);
|
2013-08-08 17:34:15 +00:00
|
|
|
}
|
|
|
|
case format_kind::LINE:
|
2013-08-08 18:45:06 +00:00
|
|
|
found_newline = true;
|
2013-08-08 17:34:15 +00:00
|
|
|
return 0;
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::CHOICE:
|
2013-08-08 17:34:15 +00:00
|
|
|
{
|
2013-08-08 18:45:06 +00:00
|
|
|
sexpr const & x = sexpr_choice_2(s);
|
2013-08-22 05:45:48 +00:00
|
|
|
return space_upto_line_break(x, available, found_newline);
|
2013-08-08 17:34:15 +00:00
|
|
|
}
|
2013-07-23 23:21:04 +00:00
|
|
|
}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-08-08 18:45:06 +00:00
|
|
|
sexpr format::be(unsigned w, unsigned k, sexpr const & s) {
|
|
|
|
/* s = (i, v) :: z, where h has the type int x format */
|
|
|
|
/* ret = list of format */
|
|
|
|
|
2013-09-13 23:14:24 +00:00
|
|
|
if (is_nil(s)) {
|
2013-08-08 18:45:06 +00:00
|
|
|
return sexpr{};
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sexpr const & h = car(s);
|
|
|
|
sexpr const & z = cdr(s);
|
|
|
|
int i = to_int(car(h));
|
|
|
|
sexpr const & v = cdr(h);
|
|
|
|
|
|
|
|
switch (sexpr_kind(v)) {
|
|
|
|
case format_kind::NIL:
|
2013-08-08 18:45:06 +00:00
|
|
|
return be(w, k, z);
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::COLOR_BEGIN:
|
|
|
|
case format_kind::COLOR_END:
|
2013-08-08 18:45:06 +00:00
|
|
|
return sexpr(v, be(w, k, z));
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::COMPOSE:
|
2013-08-22 05:45:48 +00:00
|
|
|
case format_kind::FLAT_COMPOSE:
|
2013-07-25 00:50:51 +00:00
|
|
|
{
|
|
|
|
sexpr const & list = sexpr_compose_list(v);
|
2013-08-08 18:45:06 +00:00
|
|
|
sexpr const & list_ = foldr(list, z, [i](sexpr const & s, sexpr const & res) {
|
|
|
|
return sexpr(sexpr(i, s), res);
|
|
|
|
});
|
|
|
|
return be(w, k, list_);
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
case format_kind::NEST:
|
|
|
|
{
|
|
|
|
int j = sexpr_nest_i(v);
|
|
|
|
sexpr const & x = sexpr_nest_s(v);
|
2013-08-08 18:45:06 +00:00
|
|
|
return be(w, k, sexpr(sexpr(i + j, x), z));
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
case format_kind::TEXT:
|
2013-08-08 18:45:06 +00:00
|
|
|
return sexpr(v, be(w, k + sexpr_text_length(v), z));
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::LINE:
|
2013-08-08 18:45:06 +00:00
|
|
|
return sexpr(v, sexpr(sexpr_text(std::string(i, ' ')), be(w, i, z)));
|
2013-07-25 00:50:51 +00:00
|
|
|
case format_kind::CHOICE:
|
|
|
|
{
|
|
|
|
sexpr const & x = sexpr_choice_1(v);
|
|
|
|
sexpr const & y = sexpr_choice_2(v);;
|
2013-08-22 05:45:48 +00:00
|
|
|
int available = static_cast<int>(w) - static_cast<int>(k);
|
|
|
|
if (!space_upto_line_break_list_exceeded(sexpr(sexpr(i, x), z), available)) {
|
2013-08-08 18:45:06 +00:00
|
|
|
sexpr const & s1 = be(w, k, sexpr(sexpr(i, x), z));
|
2013-08-08 17:34:15 +00:00
|
|
|
return s1;
|
2013-08-22 05:45:48 +00:00
|
|
|
} else {
|
|
|
|
sexpr const & s2 = be(w, k, sexpr(sexpr(i, y), z));
|
|
|
|
return s2;
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-08-01 22:41:45 +00:00
|
|
|
sexpr format::best(unsigned w, unsigned k, sexpr const & s) {
|
2013-08-08 18:45:06 +00:00
|
|
|
return be(w, k, sexpr{sexpr(0, s)});
|
2013-07-23 01:30:25 +00:00
|
|
|
}
|
|
|
|
|
2013-07-25 00:50:51 +00:00
|
|
|
format operator+(format const & f1, format const & f2) {
|
2013-08-01 22:41:45 +00:00
|
|
|
return format{f1, f2};
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
2013-07-23 23:21:04 +00:00
|
|
|
|
2013-08-03 02:17:29 +00:00
|
|
|
format operator^(format const & f1, format const & f2) {
|
2013-09-13 10:35:29 +00:00
|
|
|
return format {f1, format(" "), f2};
|
2013-08-03 02:17:29 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
std::ostream & pretty(std::ostream & out, unsigned w, bool colors, format const & f) {
|
2013-07-25 00:50:51 +00:00
|
|
|
sexpr const & b = format::best(w, 0, f.m_value);
|
2013-08-13 23:19:30 +00:00
|
|
|
return layout_list(out, colors, b);
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|
2013-08-09 01:35:49 +00:00
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
std::ostream & pretty(std::ostream & out, unsigned w, format const & f) {
|
|
|
|
return pretty(out, w, LEAN_DEFAULT_PP_COLORS, f);
|
|
|
|
}
|
2013-08-09 01:35:49 +00:00
|
|
|
|
2013-08-13 23:19:30 +00:00
|
|
|
std::ostream & pretty(std::ostream & out, options const & opts, format const & f) {
|
|
|
|
return pretty(out, get_pp_width(opts), get_pp_colors(opts), f);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream & operator<<(std::ostream & out, format const & f) {
|
|
|
|
return pretty(out, LEAN_DEFAULT_PP_WIDTH, LEAN_DEFAULT_PP_COLORS, f);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ostream & operator<<(std::ostream & out, std::pair<format const &, options const &> const & p) {
|
|
|
|
return pretty(out, p.second, p.first);
|
2013-08-09 01:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
format pp(name const & n) {
|
2013-08-13 15:18:01 +00:00
|
|
|
return format(n.to_string());
|
2013-08-09 01:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sexpr_pp_fn {
|
|
|
|
format apply(sexpr const & s) {
|
|
|
|
switch (s.kind()) {
|
|
|
|
case sexpr_kind::NIL: return format("nil");
|
|
|
|
case sexpr_kind::STRING: {
|
|
|
|
std::ostringstream ss;
|
|
|
|
ss << "\"" << escaped(to_string(s).c_str()) << "\"";
|
|
|
|
return format(ss.str());
|
|
|
|
}
|
|
|
|
case sexpr_kind::BOOL: return format(to_bool(s) ? "true" : "false");
|
|
|
|
case sexpr_kind::INT: return format(to_int(s));
|
|
|
|
case sexpr_kind::DOUBLE: return format(to_double(s));
|
2013-08-13 15:18:01 +00:00
|
|
|
case sexpr_kind::NAME: return pp(to_name(s));
|
2013-08-09 01:35:49 +00:00
|
|
|
case sexpr_kind::MPZ: return format(to_mpz(s));
|
|
|
|
case sexpr_kind::MPQ: return format(to_mpq(s));
|
|
|
|
case sexpr_kind::CONS: {
|
|
|
|
sexpr const * curr = &s;
|
|
|
|
format r;
|
|
|
|
while (true) {
|
|
|
|
r += apply(head(*curr));
|
|
|
|
curr = &tail(*curr);
|
|
|
|
if (is_nil(*curr)) {
|
2013-09-04 20:21:57 +00:00
|
|
|
return paren(r);
|
2013-08-09 01:35:49 +00:00
|
|
|
} else if (!is_cons(*curr)) {
|
|
|
|
return group(nest(1, format{lp(), r, space(), dot(), line(), apply(*curr), rp()}));
|
|
|
|
} else {
|
|
|
|
r += line();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
2013-11-11 17:19:38 +00:00
|
|
|
lean_unreachable(); // LCOV_EXCL_LINE
|
2013-08-09 01:35:49 +00:00
|
|
|
}
|
|
|
|
|
2013-08-13 15:18:01 +00:00
|
|
|
format operator()(sexpr const & s) {
|
2013-08-09 01:35:49 +00:00
|
|
|
return apply(s);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
format pp(sexpr const & s) {
|
2013-08-13 15:18:01 +00:00
|
|
|
return sexpr_pp_fn()(s);
|
2013-08-09 01:35:49 +00:00
|
|
|
}
|
2013-07-25 00:50:51 +00:00
|
|
|
}
|