pretty printing -- copmlete for xo::ast::GeneralizedExpression
This commit is contained in:
parent
96aa415920
commit
2e0846823b
67 changed files with 1230 additions and 478 deletions
|
|
@ -101,7 +101,7 @@ namespace xo {
|
|||
virtual void attach_envs(bp<Environment> p) override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(ppstate * pps, bool upto) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
Apply(TypeDescr apply_valuetype,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ namespace xo {
|
|||
virtual void attach_envs(bp<Environment> p) override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
AssignExpr(const rp<Variable> & lhs,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "ConstantInterface.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -70,11 +71,17 @@ namespace xo {
|
|||
if (value_td_)
|
||||
os << xtag("type", value_td_->short_name());
|
||||
else
|
||||
os << xtag("type", "nullptr");;
|
||||
os << xtag("type", "nullptr");
|
||||
os << xtag("value", value_);
|
||||
os << ">";
|
||||
}
|
||||
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override {
|
||||
return ppii.pps()->pretty_struct(ppii, "Constant",
|
||||
rtag("type", print::quot(this->valuetype()->short_name())),
|
||||
refrtag("value", value_));
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Constant(TypeDescr x_type, const T & x)
|
||||
: ConstantInterface(exprtype::constant, x_type),
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
protected:
|
||||
ConvertExpr(TypeDescr dest_type,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(ppstate * pps, bool upto) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@
|
|||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "binding_path.hpp"
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
|
||||
namespace xo {
|
||||
|
||||
namespace ast {
|
||||
class Expression;
|
||||
|
||||
|
|
@ -35,6 +37,7 @@ namespace xo {
|
|||
virtual bp<Expression> lookup_var(const std::string & vname) const = 0;
|
||||
|
||||
virtual void print(std::ostream & os) const = 0;
|
||||
virtual std::uint32_t pretty_print(const xo::print::ppindentinfo & ppii) const = 0;
|
||||
};
|
||||
|
||||
inline std::ostream &
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ namespace xo {
|
|||
**/
|
||||
class GeneralizedExpression : public ref::Refcount {
|
||||
public:
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
using ppstate = xo::print::ppstate;
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
using ppstate = xo::print::ppstate;
|
||||
using ppindentinfo = xo::print::ppindentinfo;
|
||||
|
||||
public:
|
||||
GeneralizedExpression(exprtype extype, TypeDescr valuetype)
|
||||
|
|
@ -35,7 +36,7 @@ namespace xo {
|
|||
/** human-readable string representation **/
|
||||
virtual std::string display_string() const;
|
||||
/** pretty printing support. See [xo-indentlog/xo/indentlog/pretty.hpp] **/
|
||||
virtual std::uint32_t pretty_print(ppstate * pps, bool upto) const;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const = 0;
|
||||
|
||||
protected:
|
||||
/** useful when scaffolding expressions in a parser **/
|
||||
|
|
@ -59,4 +60,4 @@ namespace xo {
|
|||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end GeneralizedExpression.hpp **/
|
||||
/* end GeneralizedExpression.hpp */
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
virtual void print(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const xo::print::ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
GlobalEnv();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Expression.hpp"
|
||||
#include <vector>
|
||||
//#include <vector>
|
||||
#include <string>
|
||||
//#include <cstdint>
|
||||
|
||||
|
|
@ -102,6 +102,7 @@ namespace xo {
|
|||
#endif
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppi) const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ namespace xo {
|
|||
virtual void attach_envs(bp<Environment> p) override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(ppstate * pps, bool upto) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
protected:
|
||||
/** create type description for lambda with arguments @p argv
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
virtual void print(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const print::ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
LocalEnv(const std::vector<rp<Variable>> & argv, const rp<Environment> & parent_env);
|
||||
|
|
@ -103,12 +104,6 @@ namespace xo {
|
|||
};
|
||||
|
||||
} /*namespace ast*/
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
PPDETAIL_ATOMIC(xo::ast::LocalEnv);
|
||||
}
|
||||
#endif
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "PrimitiveInterface.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "llvmintrinsic.hpp"
|
||||
#include "xo/reflect/Reflect.hpp"
|
||||
//#include <cstdint>
|
||||
#include "xo/indentlog/print/quoted.hpp"
|
||||
|
||||
extern "C" {
|
||||
/* these symbols needed to link primitives */
|
||||
|
|
@ -90,6 +91,53 @@ namespace xo {
|
|||
<< ">";
|
||||
}
|
||||
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override {
|
||||
/* 1. rtag instead of refrtag:
|
||||
* print::quot() is a temporary rvalue; lifetime ends before control enters pretty_struct()
|
||||
*
|
||||
* 2. value cast to void*:
|
||||
* we don't have pretty printer for native function pointers anyway
|
||||
* + simplifies ppdetail_atomic
|
||||
*/
|
||||
return ppii.pps()->pretty_struct(ppii, "Primitive",
|
||||
refrtag("name", name_),
|
||||
rtag("type", print::quot(this->valuetype()->short_name())),
|
||||
refrtag("value", (void*)(this->value())));
|
||||
|
||||
#ifdef OBSOLETE
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Primitive"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("name", name_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("type", print::quot(this->value_td()->short_name())))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("value", (void*)(this->value())))
|
||||
return false;
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<Primitive");
|
||||
pps->newline_pretty_tag(ppii.ci1(), "name", name_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "type", print::quot(this->value_td()->short_name()));
|
||||
/* don't have pretty printer for native function pointers anyway
|
||||
* + simplifies ppdetail_atomic
|
||||
*/
|
||||
pps->newline_pretty_tag(ppii.ci1(), "value", (void*)this->value());
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
Primitive(TypeDescr fn_type,
|
||||
const std::string & name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Expression.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
|
@ -38,7 +37,7 @@ namespace xo {
|
|||
// ----- from GeneralizedExpression ----
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(ppstate * pps, bool upto) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
/** sequence of expressions; evaluate in left-to-right order.
|
||||
|
|
@ -49,5 +48,4 @@ namespace xo {
|
|||
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end Sequence.hpp **/
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace xo {
|
|||
virtual void attach_envs(bp<Environment> /*p*/) override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
virtual std::uint32_t pretty_print(const ppindentinfo & ppii) const override;
|
||||
|
||||
private:
|
||||
Variable(const std::string & name,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
#include "xo/indentlog/print/pretty_tag.hpp"
|
||||
#include "xo/refcnt/pretty_refcnt.hpp"
|
||||
#include "Expression.hpp"
|
||||
|
||||
|
|
@ -14,23 +13,17 @@ namespace xo {
|
|||
namespace print {
|
||||
template<>
|
||||
struct ppdetail<xo::ast::GeneralizedExpression> {
|
||||
static bool print_upto(ppstate * pps, const xo::ast::GeneralizedExpression & x) {
|
||||
return x.pretty_print(pps, true);
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const xo::ast::GeneralizedExpression & x) {
|
||||
x.pretty_print(pps, false);
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const xo::ast::GeneralizedExpression & x) {
|
||||
return x.pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ppdetail<xo::ast::Expression> {
|
||||
static bool print_upto(ppstate * pps, const xo::ast::Expression & x) {
|
||||
return x.pretty_print(pps, true);
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const xo::ast::Expression & x) {
|
||||
x.pretty_print(pps, false);
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const xo::ast::Expression & x) {
|
||||
return x.pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
18
xo-expression/include/xo/expression/pretty_localenv.hpp
Normal file
18
xo-expression/include/xo/expression/pretty_localenv.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* @file pretty_localenv.hpp */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
#include "xo/refcnt/pretty_refcnt.hpp"
|
||||
#include "LocalEnv.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <>
|
||||
struct ppdetail<xo::ast::LocalEnv> {
|
||||
static bool print_pretty(const ppindentinfo & ppii, const xo::ast::LocalEnv & x) {
|
||||
return x.pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
20
xo-expression/include/xo/expression/pretty_variable.hpp
Normal file
20
xo-expression/include/xo/expression/pretty_variable.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* file pretty_variable.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pretty_expression.hpp"
|
||||
#include "Variable.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <>
|
||||
struct ppdetail<xo::ast::Variable> {
|
||||
static bool print_pretty(const ppindentinfo & ppii, const xo::ast::Expression & x) {
|
||||
return x.pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,9 @@
|
|||
#include "Apply.hpp"
|
||||
#include "Primitive.hpp"
|
||||
#include "exprtype.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
#include "xo/indentlog/print/pretty_vector.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -77,39 +79,35 @@ namespace xo {
|
|||
}
|
||||
|
||||
std::uint32_t
|
||||
Apply::pretty_print(ppstate * pps, bool upto) const
|
||||
Apply::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
if (upto) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
return ppii.pps()->pretty_struct(ppii, "Apply",
|
||||
refrtag("fn", fn_),
|
||||
refrtag("argv", argv_));
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
#ifdef OBSOLETE
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Apply"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("fn", fn_)))
|
||||
if (!pps->print_upto_tag("fn", fn_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("argv", argv_)))
|
||||
if (!pps->print_upto_tag("argv", argv_))
|
||||
return false;
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
return true;
|
||||
} else {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
|
||||
pps->write("<Apply");
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("fn", fn_));
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("argv", argv_));
|
||||
pps->newline_pretty_tag(ppii.ci1(), "fn", fn_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "argv", argv_);
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} /*namespace ast*/
|
||||
|
|
|
|||
|
|
@ -4,7 +4,10 @@
|
|||
*/
|
||||
|
||||
#include "AssignExpr.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "pretty_variable.hpp"
|
||||
#include "xo/indentlog/print/tag.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
|
@ -86,6 +89,13 @@ namespace xo {
|
|||
<< xtag("rhs", rhs_)
|
||||
<< ">";
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
AssignExpr::pretty_print(const ppindentinfo & ppii) const {
|
||||
return ppii.pps()->pretty_struct(ppii, "AssignExpr",
|
||||
refrtag("lhs", lhs_),
|
||||
refrtag("rhs", rhs_));
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "ConvertExpr.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
|
@ -31,6 +32,13 @@ namespace xo {
|
|||
<< ">";
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
ConvertExpr::pretty_print(const ppindentinfo & ppii) const {
|
||||
return ppii.pps()->pretty_struct(ppii, "Convert",
|
||||
rtag("dest_type", print::quot(this->valuetype()->short_name())),
|
||||
refrtag("arg", arg_));
|
||||
}
|
||||
|
||||
// ----- ConvertExprAccess -----
|
||||
|
||||
rp<ConvertExprAccess>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include "DefineExpr.hpp"
|
||||
#include "Variable.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "xo/indentlog/print/pretty_tag.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -65,39 +64,33 @@ namespace xo {
|
|||
} /*display*/
|
||||
|
||||
std::uint32_t
|
||||
DefineExpr::pretty_print(ppstate * pps, bool upto) const
|
||||
DefineExpr::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
if (upto) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
return ppii.pps()->pretty_struct(ppii, "Define",
|
||||
refrtag("name", lhs_name_),
|
||||
refrtag("rhs", rhs_));
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
#ifdef OBSOLETE
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Define"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("name", lhs_name_)))
|
||||
if (!pps->print_upto_tag("name", lhs_name_))
|
||||
return false;
|
||||
if (!pps->print_upto_tag("rhs", rhs_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("rhs", rhs_)))
|
||||
return false;
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
return true;
|
||||
} else {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
|
||||
pps->write("<Define");
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("name", lhs_name_));
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("rhs", rhs_));
|
||||
pps->newline_pretty_tag(ppii.ci1(), "name", lhs_name_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "rhs", rhs_);
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----- DefineExprAccess -----
|
||||
|
|
|
|||
|
|
@ -11,19 +11,28 @@ namespace xo {
|
|||
return tostr(*this);
|
||||
}
|
||||
|
||||
#ifdef SUPERSEDED // currently all derived expression types support pretty printing
|
||||
std::uint32_t
|
||||
GeneralizedExpression::pretty_print(ppstate * pps, bool upto) const {
|
||||
GeneralizedExpression::pretty_print(const ppindentinfo & ppii) const {
|
||||
// Slooooow fallback for subtypes that don't implement pretty printing support
|
||||
// Currently have support for:
|
||||
// - Variable
|
||||
// - Lambda
|
||||
// - DefineExpr
|
||||
// - Sequence
|
||||
// - Apply
|
||||
// - Primitive
|
||||
// - IfExpr
|
||||
|
||||
ppstate * pps = ppii.pps();
|
||||
std::uint32_t saved = pps->pos();
|
||||
pps->write(display_string());
|
||||
if (upto && !pps->has_margin())
|
||||
if (ppii.upto() && !pps->has_margin())
|
||||
return false;
|
||||
|
||||
return upto ? pps->scan_no_newline(saved) : true;
|
||||
return ppii.upto() ? pps->scan_no_newline(saved) : true;
|
||||
}
|
||||
#endif
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,33 @@ namespace xo {
|
|||
|
||||
void
|
||||
GlobalEnv::print(std::ostream & os) const {
|
||||
os << "<globalenv" << xtag("size", global_map_.size()) << ">";
|
||||
os << "<GlobalEnv"
|
||||
<< xtag("size", global_map_.size())
|
||||
<< ">";
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
GlobalEnv::pretty_print(const xo::print::ppindentinfo & ppii) const
|
||||
{
|
||||
using xo::print::ppstate;
|
||||
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<GlobalEnv"))
|
||||
return false;
|
||||
if (!pps->print_upto_tag("size", global_map_.size()))
|
||||
return false;
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<GlobalEnv");
|
||||
pps->newline_pretty_tag(ppii.ci1(), "size", global_map_.size());
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/* @file IfExpr.cpp */
|
||||
|
||||
#include "IfExpr.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "pretty_variable.hpp"
|
||||
//#include "xo/indentlog/print/vector.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
|
@ -38,6 +40,14 @@ namespace xo {
|
|||
<< xtag("when_false", when_false_)
|
||||
<< ">";
|
||||
} /*display*/
|
||||
|
||||
std::uint32_t
|
||||
IfExpr::pretty_print(const ppindentinfo & ppii) const {
|
||||
return ppii.pps()->pretty_struct(ppii, "IfExpr",
|
||||
refrtag("test", test_),
|
||||
refrtag("when_true", when_true_),
|
||||
refrtag("when_false", when_false_));
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
#include "Lambda.hpp"
|
||||
#include "exprtype.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
#include "pretty_variable.hpp"
|
||||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "xo/reflect/function/FunctionTdx.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
#include "xo/indentlog/print/pretty_vector.hpp"
|
||||
#include "xo/indentlog/print/pretty_tag.hpp"
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -322,47 +322,38 @@ namespace xo {
|
|||
} /*display*/
|
||||
|
||||
std::uint32_t
|
||||
Lambda::pretty_print(ppstate * pps, bool upto) const
|
||||
Lambda::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
if (upto) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
return ppii.pps()->pretty_struct(ppii, "Lambda",
|
||||
refrtag("name", name_),
|
||||
refrtag("argv", local_env_->argv()),
|
||||
refrtag("body", body_));
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
#ifdef OBSOLETE
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Lambda"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("name", name_)))
|
||||
if (!pps->print_upto_tag("name", name_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("argv", local_env_->argv())))
|
||||
if (!pps->print_upto_tag("argv", local_env_->argv()))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(xtag("body", body_)))
|
||||
if (!pps->print_upto_tag("body", body_))
|
||||
return false;
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
return true;
|
||||
} else {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
|
||||
pps->write("<Lambda");
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("name", name_));
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("argv", local_env_->argv()));
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag("body", body_));
|
||||
pps->newline_pretty_tag(ppii.ci1(), "name", name_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "argv", local_env_->argv());
|
||||
pps->newline_pretty_tag(ppii.ci1(), "body", body_);
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----- Lambda Access -----
|
||||
|
|
@ -413,5 +404,4 @@ namespace xo {
|
|||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end Lambda.cpp */
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@
|
|||
*/
|
||||
|
||||
#include "LocalEnv.hpp"
|
||||
#include "pretty_variable.hpp"
|
||||
#include "xo/indentlog/print/pretty_vector.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
rp<LocalEnv>
|
||||
|
|
@ -112,6 +115,33 @@ namespace xo {
|
|||
<< xtag("argv", argv_)
|
||||
<< ">";
|
||||
}
|
||||
|
||||
std::uint32_t
|
||||
LocalEnv::pretty_print(const xo::print::ppindentinfo & ppii) const {
|
||||
using xo::print::ppstate;
|
||||
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<LocalEnv"))
|
||||
return false;
|
||||
if (!pps->print_upto_tag("this", (void*)this))
|
||||
return false;
|
||||
if (!pps->print_upto_tag("argv", argv_))
|
||||
return false;
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<LocalEnv");
|
||||
pps->newline_pretty_tag(ppii.ci1(), "this", (void*)this);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "argv", argv_);
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -74,14 +74,11 @@ namespace xo {
|
|||
}
|
||||
|
||||
std::uint32_t
|
||||
Sequence::pretty_print(ppstate * pps, bool upto) const
|
||||
Sequence::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
if (upto) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Sequence"))
|
||||
return false;
|
||||
|
||||
|
|
@ -91,8 +88,7 @@ namespace xo {
|
|||
return false;
|
||||
|
||||
std::string i_str = tostr("[", i, "]");
|
||||
|
||||
if (!pps->print_upto(xtag(i_str.c_str(), expr_i)))
|
||||
if (!pps->print_upto_tag(i_str.c_str(), expr_i))
|
||||
return false;
|
||||
++i;
|
||||
}
|
||||
|
|
@ -100,19 +96,18 @@ namespace xo {
|
|||
if (!pps->has_margin())
|
||||
return false;
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
} else {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<Sequence");
|
||||
|
||||
std::size_t i = 0;
|
||||
for (const auto & expr_i : expr_v_) {
|
||||
std::string i_str = tostr("[", i, "]");
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(xtag(i_str.c_str(), expr_i));
|
||||
pps->newline_pretty_tag(ppii.ci1(),
|
||||
i_str.c_str(),
|
||||
expr_i);
|
||||
++i;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "Variable.hpp"
|
||||
#include "Environment.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
|
@ -37,6 +38,59 @@ namespace xo {
|
|||
os << xtag("type", "nullptr");
|
||||
os << ">";
|
||||
} /*display*/
|
||||
|
||||
std::uint32_t
|
||||
Variable::pretty_print(const ppindentinfo & ppii) const {
|
||||
/* 1. rtag instead of refrtag:
|
||||
* print::quot() is a temporary rvalue; lifetime ends before control enters pretty_struct()
|
||||
*/
|
||||
return ppii.pps()->pretty_struct(ppii, "Variable",
|
||||
refrtag("name", name_),
|
||||
rtag("type", print::quot(this->valuetype()
|
||||
? this->valuetype()->short_name()
|
||||
: "nullptr")));
|
||||
|
||||
#ifdef OBSOLETE
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<Variable"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("name", name_))
|
||||
return false;
|
||||
|
||||
if (this->valuetype()) {
|
||||
if (!pps->print_upto_tag("type", this->valuetype()->short_name()))
|
||||
return false;
|
||||
} else {
|
||||
if (!pps->print_upto_tag("type", "nullptr"))
|
||||
return false;
|
||||
}
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<Variable");
|
||||
|
||||
pps->newline_pretty_tag(ppii.ci1(), "name", name_);
|
||||
|
||||
/* use tag instead of rtag for type,
|
||||
* since not guaranteed to print machine-readably
|
||||
*/
|
||||
if (this->valuetype()) {
|
||||
pps->newline_indent(ppii.ci1());
|
||||
pps->pretty(xtag("type", this->valuetype()->short_name()));
|
||||
} else {
|
||||
pps->newline_pretty_tag(ppii.ci1(), "type", "nullptr");
|
||||
}
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -636,6 +636,7 @@ namespace xo {
|
|||
return ((s1 <=> s2) == std::strong_ordering::equal);
|
||||
}
|
||||
///@}
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
/** end flatstring.hpp **/
|
||||
|
|
|
|||
28
xo-flatstring/include/xo/flatstring/flatstring_pretty.hpp
Normal file
28
xo-flatstring/include/xo/flatstring/flatstring_pretty.hpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/** @file flatstring_pretty.hpp
|
||||
*
|
||||
* Author: Roland Conybeare, Jul 2025
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "flatstring.hpp"
|
||||
#include "flatstring_iostream.hpp"
|
||||
#include "xo/indentlog/print/ppdetail_atomic.hpp"
|
||||
|
||||
namespace xo {
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
struct ppindentinfo;
|
||||
|
||||
template <std::size_t N>
|
||||
struct ppdetail<flatstring<N>> {
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const flatstring<N> & x) {
|
||||
return ppdetail_atomic<flatstring<N>>::print_pretty(ppii, x);
|
||||
};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** end flatstring_pretty.hpp **/
|
||||
|
|
@ -4,8 +4,23 @@ Glossary
|
|||
--------
|
||||
|
||||
.. glossary::
|
||||
iff
|
||||
| Short for "if and only if"
|
||||
|
||||
pp
|
||||
| Short for `pretty printer`. For example in `ppdetail`, `toppstr`.
|
||||
| Short for "pretty printer". For example in `ppdetail`, `toppstr`.
|
||||
|
||||
ppii
|
||||
| Short for "pretty-print indent info"
|
||||
|
||||
pps
|
||||
| Short for "pretty-print state"
|
||||
|
||||
rtag
|
||||
| Shorthand for "raw tag"
|
||||
|
||||
xtag
|
||||
| Shorthand for `tag with preceding space`
|
||||
| Shorthand for "tag with preceding space"
|
||||
|
||||
xrtag
|
||||
| Shorthand for "raw tag with preceding space"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,16 @@ namespace xo {
|
|||
**/
|
||||
template <typename CharT, typename Traits = std::char_traits<CharT>>
|
||||
class log_streambuf : public std::streambuf {
|
||||
public:
|
||||
struct rewind_state {
|
||||
explicit rewind_state(std::size_t solpos, std::size_t color_esc, std::uint32_t p)
|
||||
: solpos{solpos}, color_escape_chars{color_esc}, pos{p} {}
|
||||
|
||||
std::size_t solpos = 0;
|
||||
std::size_t color_escape_chars = 0;
|
||||
std::uint32_t pos = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
log_streambuf(std::uint32_t buf_z, bool debug_flag = false) : debug_flag_{debug_flag} {
|
||||
this->buf_v_.resize(buf_z);
|
||||
|
|
@ -27,8 +37,15 @@ namespace xo {
|
|||
char const * hi() const { return this->lo() + this->capacity(); }
|
||||
std::uint32_t pos() const { return this->pptr() - this->pbase(); }
|
||||
|
||||
/** number of characters since start of line (last \n or \r) **/
|
||||
std::uint32_t lpos() const { return pos() - solpos_; }
|
||||
/** number of visible characters since start of line (last \n or \r) **/
|
||||
std::uint32_t lpos() const {
|
||||
assert(pos() >= solpos_ + color_escape_chars_);
|
||||
return pos() - solpos_ - color_escape_chars_;
|
||||
}
|
||||
|
||||
rewind_state checkpoint() const {
|
||||
return rewind_state(solpos_, color_escape_chars_, pos());
|
||||
}
|
||||
|
||||
bool debug_flag() const { return debug_flag_; }
|
||||
|
||||
|
|
@ -40,12 +57,24 @@ namespace xo {
|
|||
this->setp(p_lo, p_hi);
|
||||
|
||||
this->solpos_ = 0;
|
||||
this->color_escape_chars_ = 0;
|
||||
this->color_escape_start_ = nullptr;
|
||||
} /*reset_stream*/
|
||||
|
||||
void rewind_to(std::uint32_t p) {
|
||||
void rewind_to(rewind_state s) {
|
||||
if (debug_flag_) {
|
||||
std::cout << "rewind_to: pos " << pos() << "->" << s.pos
|
||||
<< " solpos " << solpos_ << "->" << s.solpos
|
||||
<< " color_esc " << color_escape_chars_ << "->" << s.color_escape_chars
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
/* .setp(): using for side effect: sets .pptr to .pbase */
|
||||
this->setp(this->pbase(), this->epptr());
|
||||
this->pbump(p);
|
||||
this->pbump(s.pos);
|
||||
|
||||
this->solpos_ = s.solpos;
|
||||
this->color_escape_chars_ = s.color_escape_chars;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -65,7 +94,7 @@ namespace xo {
|
|||
|
||||
this->setp(p_base, p_hi);
|
||||
this->pbump(old_n);
|
||||
} /*expand*/
|
||||
}
|
||||
|
||||
virtual std::streamsize
|
||||
xsputn(char const * s, std::streamsize n) override {
|
||||
|
|
@ -94,7 +123,7 @@ namespace xo {
|
|||
ncopied = n;
|
||||
}
|
||||
|
||||
if (debug_flag_) {
|
||||
if (false /*debug_flag_*/) {
|
||||
std::cout << "xsputn: copying ncopied=" << ncopied << " (/n=" << n << ") bytes into range [lo,hi)"
|
||||
<< ", lo=" << (void*)this->pptr()
|
||||
<< ", hi=" << (void*)(this->pptr() + n)
|
||||
|
|
@ -103,11 +132,39 @@ namespace xo {
|
|||
|
||||
std::memcpy(this->pptr(), s, ncopied);
|
||||
|
||||
/* scan range [pptr, pptr+n] backwards, to account for newline (if any) */
|
||||
for (char const * p_lo = this->pptr(), * p_hi = p_lo + n - 1, * p = p_hi; p >= p_lo; --p) {
|
||||
/* scan range [pptr, pptr+n] for:
|
||||
* 1. completed color escape sequences \033..m
|
||||
* - account for chars in these sequences, since non-printing
|
||||
* 2. newlines (and carriage returns)
|
||||
* - remember position of last {newline or carriage return)
|
||||
*/
|
||||
for (char const * p_lo = this->pptr(), * p_hi = p_lo + n, * p = p_lo; p < p_hi; ++p) {
|
||||
if (*p == '\n' || *p == '\r') {
|
||||
this->solpos_ = (p+1 - this->pbase());
|
||||
break;
|
||||
/* reset, since these chars relevant as correction to solpos */
|
||||
this->color_escape_chars_ = 0;
|
||||
/* -> incomplete color escape, broken by newline */
|
||||
this->color_escape_start_ = nullptr;
|
||||
} else if (*p == '\033') {
|
||||
if (debug_flag_) {
|
||||
std::cout << "xsputn: \\033 at p-p_lo=" << (p - p_lo) << std::endl;
|
||||
}
|
||||
this->color_escape_start_ = p;
|
||||
} else if (this->color_escape_start_ != nullptr) {
|
||||
if (*p == 'm') {
|
||||
/* escape seq non-printing including both endpoints */
|
||||
std::int64_t esc_chars = (p+1 - color_escape_start_);
|
||||
this->color_escape_chars_ += esc_chars;
|
||||
|
||||
if (debug_flag_) {
|
||||
std::cout << "xsputn: m at p-p_lo" << (p - p_lo) << " +" << esc_chars
|
||||
<< " -> color_escape_chars=" << color_escape_chars_ << std::endl;
|
||||
}
|
||||
this->color_escape_start_ = nullptr;
|
||||
} else if (!isdigit(*p) && (*p != '[') && (*p != ';')) {
|
||||
/* not color escape after all */
|
||||
this->color_escape_start_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,32 +174,32 @@ namespace xo {
|
|||
} /*xsputn*/
|
||||
|
||||
virtual int_type
|
||||
overflow(int_type new_ch) override
|
||||
{
|
||||
char * old_pptr = this->pptr();
|
||||
std::streamsize old_n = old_pptr - this->pbase();
|
||||
overflow(int_type new_ch) override {
|
||||
char * old_pptr = this->pptr();
|
||||
std::streamsize old_n = old_pptr - this->pbase();
|
||||
|
||||
assert(old_n <= static_cast<std::streamsize>(this->buf_v_.size()));
|
||||
assert(old_n <= static_cast<std::streamsize>(this->buf_v_.size()));
|
||||
|
||||
if (debug_flag_) {
|
||||
std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl;
|
||||
}
|
||||
if (debug_flag_) {
|
||||
std::cout << "overflow: new_ch=" << quoted_char(new_ch) << std::endl;
|
||||
}
|
||||
|
||||
this->expand_to(2 * buf_v_.size());
|
||||
this->expand_to(2 * buf_v_.size());
|
||||
|
||||
this->buf_v_[old_n] = new_ch;
|
||||
this->pbump(1);
|
||||
this->buf_v_[old_n] = new_ch;
|
||||
this->pbump(1);
|
||||
|
||||
if ((new_ch == static_cast<int_type>('\n')) || (new_ch == static_cast<int_type>('\r')))
|
||||
this->solpos_ = this->pos();
|
||||
if ((new_ch == static_cast<int_type>('\n')) || (new_ch == static_cast<int_type>('\r'))) {
|
||||
this->solpos_ = this->pos();
|
||||
}
|
||||
|
||||
if (new_ch == Traits::eof()) {
|
||||
/* reminder: returning eof sets badbit on ostream */
|
||||
return Traits::not_eof(new_ch);
|
||||
} else {
|
||||
return new_ch;
|
||||
}
|
||||
} /*overflow*/
|
||||
if (new_ch == Traits::eof()) {
|
||||
/* reminder: returning eof sets badbit on ostream */
|
||||
return Traits::not_eof(new_ch);
|
||||
} else {
|
||||
return new_ch;
|
||||
}
|
||||
} /*overflow*/
|
||||
|
||||
/* off. offset, relative to starting point dir.
|
||||
* dir.
|
||||
|
|
@ -154,6 +211,9 @@ namespace xo {
|
|||
std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode which) override {
|
||||
//std::cout << "seekoff: off=" << off << ", dir=" << dir << ", which=" << which << std::endl;
|
||||
if (debug_flag_) {
|
||||
std::cout << "seekoff(off,dir,which)" << std::endl;
|
||||
}
|
||||
|
||||
// Only output stream is supported
|
||||
if (which != std::ios_base::out)
|
||||
|
|
@ -179,6 +239,13 @@ namespace xo {
|
|||
* Use to drive @ref lpos
|
||||
**/
|
||||
std::size_t solpos_ = 0;
|
||||
/** number of non-printing chars after @ref solpos_, from
|
||||
* completed color escape sequences.
|
||||
* (ansi color escapes = text between '\033' and 'm')
|
||||
**/
|
||||
std::size_t color_escape_chars_ = 0;
|
||||
/** non-null: start of incomplete color escape sequence **/
|
||||
char const * color_escape_start_ = nullptr;
|
||||
/** buffered output stored here **/
|
||||
std::vector<char> buf_v_;
|
||||
/** true to debug log_streambuf itself **/
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ppdetail_atomic.hpp"
|
||||
#include <ostream>
|
||||
//#include <utility> // for std::move
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
|
|
@ -17,11 +17,11 @@ namespace xo {
|
|||
inline std::ostream &
|
||||
operator<< (std::ostream & os, color_encoding x) {
|
||||
switch(x) {
|
||||
case color_encoding::none: os << "none"; break;
|
||||
case color_encoding::ansi: os << "ansi"; break;
|
||||
case color_encoding::none: os << "none"; break;
|
||||
case color_encoding::ansi: os << "ansi"; break;
|
||||
case color_encoding::xterm: os << "xterm"; break;
|
||||
case color_encoding::rgb: os << "rgb"; break;
|
||||
default: os << "???"; break;
|
||||
case color_encoding::rgb: os << "rgb"; break;
|
||||
default: os << "???"; break;
|
||||
}
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
|
|
@ -125,11 +125,11 @@ namespace xo {
|
|||
} /*operator<<*/
|
||||
|
||||
enum class coloring_control_flags : std::uint8_t {
|
||||
none = 0x0,
|
||||
color_on = 0x01,
|
||||
contents = 0x02,
|
||||
none = 0x0,
|
||||
color_on = 0x01,
|
||||
contents = 0x02,
|
||||
color_off = 0x04,
|
||||
all = 0x07
|
||||
all = 0x07
|
||||
};
|
||||
|
||||
inline std::uint8_t operator& (coloring_control_flags x, coloring_control_flags y) {
|
||||
|
|
@ -177,25 +177,42 @@ namespace xo {
|
|||
template <typename Contents>
|
||||
color_impl<Contents> with_color(color_spec_type const & spec, Contents && contents) {
|
||||
return color_impl<Contents>(coloring_control_flags::all, spec, std::forward<Contents>(contents));
|
||||
} /*with_color*/
|
||||
}
|
||||
|
||||
inline color_impl<int>
|
||||
color_on(color_spec_type const & spec) {
|
||||
return color_impl<int>(coloring_control_flags::color_on, spec, 0);
|
||||
} /*color_on*/
|
||||
}
|
||||
|
||||
inline color_impl<int>
|
||||
color_off(color_spec_type const & spec) {
|
||||
/* any spec other than color_spec_type::none() works here */
|
||||
return color_impl<int>(coloring_control_flags::color_off, spec, 0);
|
||||
} /*color_off*/
|
||||
}
|
||||
|
||||
template <typename Contents>
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream & os, color_impl<Contents> const & x) {
|
||||
x.print(os);
|
||||
return os;
|
||||
} /*operator<<*/
|
||||
}
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
/* concat expected to be used on short string-like things.
|
||||
* i.e. don't want structure visible to pretty-printer.
|
||||
* could be using it like concat("boeing", 777)
|
||||
*/
|
||||
template <typename Contents>
|
||||
struct ppdetail<color_impl<Contents>> {
|
||||
using target_type = color_impl<Contents>;
|
||||
|
||||
static bool print_pretty(const ppindentinfo & ppii, const target_type & x) {
|
||||
return ppdetail_atomic<target_type>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -48,11 +48,8 @@ namespace xo {
|
|||
struct ppdetail<concat_impl<T1,T2>> {
|
||||
using target_type = concat_impl<T1,T2>;
|
||||
|
||||
static bool print_upto(ppstate * pps, const target_type & x) {
|
||||
return ppdetail_atomic<target_type>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const target_type & x) {
|
||||
ppdetail_atomic<target_type>::print_pretty(pps, x);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const target_type & x) {
|
||||
return ppdetail_atomic<target_type>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,14 @@ namespace xo {
|
|||
* Pretty-printer will introduce newlines if needed
|
||||
* to stay to the left of this margin
|
||||
**/
|
||||
std::uint32_t right_margin_ = 135;
|
||||
std::uint32_t right_margin_ = 80;
|
||||
|
||||
/** amount of additional indent per nesting level **/
|
||||
std::uint32_t indent_width_ = 2;
|
||||
|
||||
/** assert if attempting this much indent **/
|
||||
std::uint32_t assert_indent_threshold = 10000;
|
||||
|
||||
///@}
|
||||
};
|
||||
} /*namespace print*/
|
||||
|
|
|
|||
|
|
@ -11,13 +11,34 @@
|
|||
namespace xo {
|
||||
namespace print {
|
||||
struct ppstate; // see pretty.hpp
|
||||
struct ppindentinfo;
|
||||
|
||||
// Defining this means ppdetail_atomic is not used.
|
||||
// In that case where not explicitly specialized ppdetail will revert to ordinary printing for a type,
|
||||
// instead of giving compile-time error about missing template specialization of ppdetail
|
||||
|
||||
// instead of giving compile-time error about missing template specialization of ppdetail.
|
||||
#define ppdetail_atomic ppdetail
|
||||
|
||||
struct ppindentinfo {
|
||||
ppindentinfo(ppstate * pps, std::uint32_t ci0, std::uint32_t indent_width, bool upto)
|
||||
: pps_{pps}, ci0_{ci0}, ci1_{ci0 + indent_width}, upto_{upto} {}
|
||||
|
||||
ppstate * pps() const { return pps_; }
|
||||
std::uint32_t ci1() const { return ci1_; }
|
||||
bool upto() const { return upto_; }
|
||||
|
||||
private:
|
||||
ppstate * pps_ = nullptr;
|
||||
/** current indent **/
|
||||
std::uint32_t ci0_ = 0;
|
||||
/** ci0 +1 indent level **/
|
||||
std::uint32_t ci1_ = 0;
|
||||
/**
|
||||
* true -> print on remainder of current line, unless past right margin
|
||||
* false -> pretty across across multiple lines
|
||||
**/
|
||||
bool upto_;
|
||||
};
|
||||
|
||||
/** @class ppdetail
|
||||
* @brief template for opt-in to pretty-printer
|
||||
*
|
||||
|
|
@ -32,88 +53,76 @@ namespace xo {
|
|||
template <typename T>
|
||||
struct ppdetail;
|
||||
|
||||
template <typename T>
|
||||
struct ppdetail_atomic;
|
||||
|
||||
template <typename T>
|
||||
struct ppdetail_atomic {
|
||||
/** 1. print @p x to private stream @ref scratch_ss_
|
||||
/** upto=true:
|
||||
* 1. print @p x to private stream @ref scratch_ss_
|
||||
* 2. return true iff N = number of characters printed satisfies N <= @p budget.
|
||||
* content actually printed to *sbuf may be used as-is in this case
|
||||
* 3. return false otherwise. Will trigger non-degenerate pretty-printing.
|
||||
* 4. in any case consume some of @ref scratch_sbuf_
|
||||
*
|
||||
* upto=false:
|
||||
* print @p x to private stream @ref scratch_ss_
|
||||
**/
|
||||
static bool print_upto(ppstate * pps, const T & x);
|
||||
/** print @p x to private stream @ref scratch_ss_ **/
|
||||
static void print_pretty(ppstate * pps, const T & x);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const T & x);
|
||||
};
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
template <int N>
|
||||
struct ppdetail<const char[N]> {
|
||||
using target_type = const char[N];
|
||||
|
||||
static bool print_upto(ppstate * pps, const target_type & x) {
|
||||
return ppdetail_atomic<target_type>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const target_type & x) {
|
||||
ppdetail_atomic<target_type>::print_pretty(pps, x);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const target_type & x) {
|
||||
return ppdetail_atomic<target_type>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ppdetail<const char *> {
|
||||
static bool print_upto(ppstate * pps, const char * x) {
|
||||
return ppdetail_atomic<const char *>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const char * x) {
|
||||
ppdetail_atomic<const char *>::print_pretty(pps, x);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const char * x) {
|
||||
return ppdetail_atomic<const char *>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define PPDETAIL_ATOMIC_BODY(target_type) \
|
||||
struct ppdetail<target_type> { \
|
||||
static bool print_upto(ppstate * pps, const target_type & x) { \
|
||||
return ppdetail_atomic<target_type>::print_upto(pps, x); \
|
||||
} \
|
||||
\
|
||||
static void print_pretty(ppstate * pps, const target_type & x) { \
|
||||
ppdetail_atomic<target_type>::print_pretty(pps, x); \
|
||||
} \
|
||||
#define PPDETAIL_ATOMIC_BODY(target_type) \
|
||||
struct ppdetail<target_type> { \
|
||||
static bool print_pretty(const ppindentinfo & ppii, \
|
||||
const target_type & x) { \
|
||||
return ppdetail_atomic<target_type>::print_pretty(ppii, x); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PPDETAIL_ATOMIC_BODY_CONST(target_type) \
|
||||
struct ppdetail<const target_type> { \
|
||||
static bool print_upto(ppstate * pps, const target_type & x) { \
|
||||
return ppdetail_atomic<target_type>::print_upto(pps, x); \
|
||||
} \
|
||||
\
|
||||
static void print_pretty(ppstate * pps, const target_type & x) { \
|
||||
ppdetail_atomic<target_type>::print_pretty(pps, x); \
|
||||
} \
|
||||
#define PPDETAIL_ATOMIC_BODY_CONST(target_type) \
|
||||
struct ppdetail<const target_type> { \
|
||||
static bool print_pretty(const ppindentinfo & ppii, \
|
||||
const target_type & x) { \
|
||||
return ppdetail_atomic<target_type>::print_pretty(ppii, x); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PPDETAIL_ATOMIC(target_type) \
|
||||
template<> \
|
||||
#define PPDETAIL_ATOMIC(target_type) \
|
||||
template<> \
|
||||
PPDETAIL_ATOMIC_BODY(target_type)
|
||||
|
||||
#define PPDETAIL_ATOMIC_CONST(target_type) \
|
||||
template<> \
|
||||
#define PPDETAIL_ATOMIC_CONST(target_type) \
|
||||
template<> \
|
||||
PPDETAIL_ATOMIC_BODY_CONST(target_type)
|
||||
|
||||
PPDETAIL_ATOMIC(bool);
|
||||
PPDETAIL_ATOMIC(char);
|
||||
// PPDETAIL_ATOMIC_CONST(char);
|
||||
PPDETAIL_ATOMIC(std::int64_t);
|
||||
PPDETAIL_ATOMIC(std::uint64_t);
|
||||
PPDETAIL_ATOMIC(std::int32_t);
|
||||
PPDETAIL_ATOMIC(std::uint32_t);
|
||||
PPDETAIL_ATOMIC(float);
|
||||
PPDETAIL_ATOMIC(double);
|
||||
PPDETAIL_ATOMIC(std::string);
|
||||
PPDETAIL_ATOMIC(std::string_view);
|
||||
|
||||
using voidptr = void*;
|
||||
PPDETAIL_ATOMIC(voidptr);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -94,44 +94,45 @@ namespace xo {
|
|||
/** implement pretty-printing for template @c ppconcat r**/
|
||||
template <typename... Args>
|
||||
struct ppdetail<ppconcat<Args...>> {
|
||||
/** try to print @p target on one line.
|
||||
/** upto=true:
|
||||
* try to print @p target on one line.
|
||||
* return false if budget (space until right margin) exhausted
|
||||
* or if an embedded newline appears
|
||||
*
|
||||
* @return true on success, otherwise false.
|
||||
*
|
||||
* upto=false:
|
||||
* pretty-print @p target using multiple lines
|
||||
**/
|
||||
static bool print_upto(ppstate * pps, ppconcat<Args...> target) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
static bool print_pretty(const ppindentinfo & ppii, ppconcat<Args...> target) {
|
||||
if (ppii.upto()) {
|
||||
std::uint32_t saved = ppii.pps()->pos();
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
if (!ppii.pps()->has_margin())
|
||||
return false;
|
||||
|
||||
if (std::apply(
|
||||
[pps](auto &&... args) {
|
||||
return detail::ppconcat_printupto_aux(pps, std::forward<decltype(args)>(args)...);
|
||||
if (std::apply(
|
||||
[ppii](auto &&... args) {
|
||||
return detail::ppconcat_printupto_aux(ppii.pps(), std::forward<decltype(args)>(args)...);
|
||||
},
|
||||
std::forward<std::tuple<Args...>>(target.contents_)
|
||||
) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ppii.pps()->scan_no_newline(saved);
|
||||
} else {
|
||||
std::apply(
|
||||
[ppii](auto &&... args) {
|
||||
detail::ppconcat_print_pretty_aux(ppii.pps(), ppii.ci1(),
|
||||
std::forward<decltype(args)>(args)...);
|
||||
},
|
||||
std::forward<std::tuple<Args...>>(target.contents_)
|
||||
) == false)
|
||||
{
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
}
|
||||
|
||||
/** pretty-print @p target using multiple lines
|
||||
**/
|
||||
static void print_pretty(ppstate * pps, ppconcat<Args...> target) {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
|
||||
std::apply(
|
||||
[pps, ci1](auto &&... args) {
|
||||
detail::ppconcat_print_pretty_aux(pps, ci1,
|
||||
std::forward<decltype(args)>(args)...);
|
||||
},
|
||||
std::forward<std::tuple<Args...>>(target.contents_)
|
||||
);
|
||||
}
|
||||
};
|
||||
} /*namespace print*/
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "xo/indentlog/print/ppconfig.hpp"
|
||||
#include "xo/indentlog/log_streambuf.hpp"
|
||||
#include "ppdetail_atomic.hpp"
|
||||
#include "tag.hpp"
|
||||
#include "pad.hpp"
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
|
@ -16,12 +17,10 @@
|
|||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
|
||||
/** @class ppstate
|
||||
* @brief hold pretty-printer state
|
||||
*
|
||||
* Use:
|
||||
*
|
||||
* ppconfig ppc;
|
||||
* ppstate pps(&cout, 0, &ppc);
|
||||
*
|
||||
|
|
@ -31,14 +30,19 @@ namespace xo {
|
|||
struct ppstate {
|
||||
using streambuf_type = log_streambuf<char, std::char_traits<char>>;
|
||||
|
||||
explicit ppstate(std::uint32_t ci, const ppconfig * config, std::ostream * scratch_ss, streambuf_type * scratch_sbuf)
|
||||
explicit ppstate(std::uint32_t ci, const ppconfig * config,
|
||||
std::ostream * scratch_ss, streambuf_type * scratch_sbuf)
|
||||
: scratch_sbuf_{scratch_sbuf}, scratch_ss_{scratch_ss},
|
||||
current_indent_{ci}, config_{config}
|
||||
{}
|
||||
|
||||
uint32_t indent_width() const { return config_->indent_width_; }
|
||||
ppindentinfo indent_info(bool upto) { return ppindentinfo(this, lpos(), indent_width(), upto); }
|
||||
|
||||
std::uint32_t pos() const { return scratch_sbuf_->pos(); }
|
||||
/** current position relative to start of line (last \n or \r),
|
||||
* excluding color escape sequences
|
||||
**/
|
||||
std::uint32_t lpos() const { return scratch_sbuf_->lpos(); }
|
||||
|
||||
/** space available from current position until @c ppconfig.right_margin_
|
||||
|
|
@ -60,8 +64,8 @@ namespace xo {
|
|||
return avail_margin() >= budget;
|
||||
}
|
||||
|
||||
/** true if no newlines in range [@p lo, pos),
|
||||
* where pos is current position
|
||||
/** true if no newlines in range [s, pos),
|
||||
* where s is @p start and pos is current position
|
||||
**/
|
||||
bool scan_no_newline(std::uint32_t start) const {
|
||||
char const * p = scratch_sbuf_->lo() + start;
|
||||
|
|
@ -76,10 +80,13 @@ namespace xo {
|
|||
}
|
||||
|
||||
void indent(std::uint32_t tab) {
|
||||
assert(tab < config_->assert_indent_threshold);
|
||||
(*scratch_ss_) << spaces(tab);
|
||||
}
|
||||
|
||||
/** write (to scratch stream) newline followed by @p tab spaces **/
|
||||
void newline_indent(std::uint32_t tab) {
|
||||
|
||||
(*scratch_ss_) << "\n";
|
||||
this->indent(tab);
|
||||
}
|
||||
|
|
@ -94,12 +101,50 @@ namespace xo {
|
|||
|
||||
virtual void commit() {}
|
||||
|
||||
// pretty-printing helpers
|
||||
|
||||
/** pretty-print empty struct **/
|
||||
template <typename StructName, typename... Members>
|
||||
std::uint32_t pretty_struct(const ppindentinfo & ppii, StructName && structname, Members&&...);
|
||||
|
||||
/** auxiliary function supporting @ref pretty_stuct .
|
||||
* pretty-print a single member name on behalf of a struct/class.
|
||||
* @return true iff printed content fits on remainder of line before right margin
|
||||
**/
|
||||
template <typename Member, typename... Rest>
|
||||
std::uint32_t print_upto_struct_members(const ppindentinfo & ppii,
|
||||
Member && member,
|
||||
Rest&&... rest);
|
||||
|
||||
/** base-case overload **/
|
||||
std::uint32_t print_upto_struct_members(const ppindentinfo &) { return true; }
|
||||
|
||||
/** pretty-print newline-and-indent separated member values.
|
||||
* For struct members, use refrtag(name,value)
|
||||
**/
|
||||
template <typename Member, typename... Rest>
|
||||
void pretty_struct_members(const ppindentinfo & ppii,
|
||||
Member && member,
|
||||
Rest&&... rest);
|
||||
|
||||
/** base-case overload **/
|
||||
void pretty_struct_members(const ppindentinfo &) {}
|
||||
|
||||
template <typename T>
|
||||
bool print_upto(T && x);
|
||||
|
||||
template <typename Name, typename Value>
|
||||
bool print_upto_tag(Name && name, Value && value);
|
||||
|
||||
template <typename T>
|
||||
ppstate& pretty(T && x);
|
||||
|
||||
/** write (to internal scratch stream), in order:
|
||||
* newline, indent to @p ci, tag @p name, space, @p value
|
||||
**/
|
||||
template <typename Name, typename Value>
|
||||
ppstate& newline_pretty_tag(std::uint32_t ci, Name && name, Value && value);
|
||||
|
||||
/** like pretty(x), but follow with trailing \n **/
|
||||
template <typename T>
|
||||
ppstate& prettyn(T && x);
|
||||
|
|
@ -165,6 +210,7 @@ namespace xo {
|
|||
|
||||
void check_commit() {
|
||||
if (pps_) {
|
||||
/* nuke state to prevent duplicate commit */
|
||||
ppstate * pps = pps_;
|
||||
pps_ = nullptr;
|
||||
if (pps->decr_nesting_level() == 0)
|
||||
|
|
@ -175,42 +221,59 @@ namespace xo {
|
|||
ppstate * pps_ = nullptr;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
ppdetail_atomic<T>::print_upto(ppstate * pps, const T & x)
|
||||
template <typename StructName, typename... Members>
|
||||
std::uint32_t
|
||||
ppstate::pretty_struct(const ppindentinfo & ppii, StructName && structname, Members&&... members)
|
||||
{
|
||||
/* position before we write */
|
||||
if (!pps->has_margin())
|
||||
if (ppii.upto()) {
|
||||
return (this->print_upto("<")
|
||||
&& this->print_upto(structname)
|
||||
&& this->print_upto_struct_members(ppii, members...)
|
||||
&& this->print_upto(">"));
|
||||
} else {
|
||||
this->write("<");
|
||||
this->write(structname);
|
||||
this->pretty_struct_members(ppii, members...);
|
||||
this->write(">");
|
||||
return false;
|
||||
|
||||
std::uint32_t start = pps->pos();
|
||||
|
||||
/* if x is non-atomic may optimize by checking budget more often */
|
||||
pps->write(x);
|
||||
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
|
||||
/* scan characters [lo, hi) in line buffer.
|
||||
* Newline -> caller should use print_pretty()
|
||||
*/
|
||||
return (pps->scan_no_newline(start));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
ppdetail_atomic<T>::print_pretty(ppstate * pps, const T & x)
|
||||
template <typename Member, typename... Rest>
|
||||
std::uint32_t
|
||||
ppstate::print_upto_struct_members(const ppindentinfo & ppii,
|
||||
Member && member,
|
||||
Rest&&... rest)
|
||||
{
|
||||
/* In default implementation we don't know where to introduce newlines.
|
||||
* Still need to calculate lpos though
|
||||
*/
|
||||
pps->write(x);
|
||||
if (this->print_upto(" ") && this->print_upto(member))
|
||||
return this->print_upto_struct_members(ppii, rest...);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Member, typename... Rest>
|
||||
void
|
||||
ppstate::pretty_struct_members(const ppindentinfo & ppii,
|
||||
Member && member,
|
||||
Rest&&... rest)
|
||||
{
|
||||
newline_indent(ppii.ci1());
|
||||
this->pretty(member);
|
||||
this->pretty_struct_members(ppii, rest...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
ppstate::print_upto(T && value) {
|
||||
return ppdetail<std::decay_t<T>>::print_upto(this, value);
|
||||
std::uint32_t saved = pos();
|
||||
|
||||
if (!has_margin())
|
||||
return false;
|
||||
|
||||
if (!ppdetail<std::decay_t<T>>::print_pretty(this->indent_info(true /*upto*/), value))
|
||||
return false;
|
||||
|
||||
return scan_no_newline(saved);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -220,12 +283,13 @@ namespace xo {
|
|||
* Decision depends on ancestor context
|
||||
*/
|
||||
|
||||
std::uint32_t saved = pos();
|
||||
auto saved = scratch_sbuf_->checkpoint();
|
||||
|
||||
ppcommitter ppc(this);
|
||||
|
||||
/* print_upto() modifies @ref scratch_sbuf_ (and @ref scratch_ss_) */
|
||||
bool fits = ppdetail<std::decay_t<T>>::print_upto(this, static_cast<const T &>(value));
|
||||
/* print_pretty() modifies @ref scratch_sbuf_ (and @ref scratch_ss_) */
|
||||
bool fits = ppdetail<std::decay_t<T>>::print_pretty(this->indent_info(true /*upto*/),
|
||||
static_cast<const T &>(value));
|
||||
|
||||
if (fits) {
|
||||
/* fits on 1 line -> pretty-printing maybe not required */
|
||||
|
|
@ -235,7 +299,7 @@ namespace xo {
|
|||
/* here: didn't fit -> split over multiple lines */
|
||||
|
||||
this->scratch_sbuf_->rewind_to(saved);
|
||||
ppdetail<std::decay_t<T>>::print_pretty(this, value);
|
||||
ppdetail<std::decay_t<T>>::print_pretty(this->indent_info(false), value);
|
||||
ppc.check_commit();
|
||||
|
||||
return *this;
|
||||
|
|
@ -248,12 +312,12 @@ namespace xo {
|
|||
* Decision depends on ancestor context
|
||||
*/
|
||||
|
||||
std::uint32_t saved = pos();
|
||||
auto saved = scratch_sbuf_->checkpoint();
|
||||
|
||||
ppcommitter ppc(this);
|
||||
|
||||
/* print_upto() modifies @ref scratch_sbuf_ (and @ref scratch_ss_) */
|
||||
bool fits = ppdetail<std::decay_t<T>>::print_upto(this, value);
|
||||
/* print_pretty() modifies @ref scratch_sbuf_ (and @ref scratch_ss_) */
|
||||
bool fits = ppdetail<std::decay_t<T>>::print_pretty(this->indent_info(true), value);
|
||||
|
||||
if (fits) {
|
||||
this->newline_indent(0);
|
||||
|
|
@ -264,12 +328,121 @@ namespace xo {
|
|||
/* here: didn't fit -> split over multiple lines */
|
||||
|
||||
this->scratch_sbuf_->rewind_to(saved);
|
||||
ppdetail<std::remove_reference_t<T>>::print_pretty(this, value);
|
||||
ppdetail<std::remove_reference_t<T>>::print_pretty(this->indent_info(false), value);
|
||||
this->newline_indent(0);
|
||||
ppc.check_commit();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
ppdetail_atomic<T>::print_pretty(const ppindentinfo & ppii, const T & x)
|
||||
{
|
||||
if (ppii.upto()) {
|
||||
std::uint32_t start = ppii.pps()->pos();
|
||||
|
||||
/* if x is non-atomic may optimize by checking budget more often */
|
||||
ppii.pps()->write(x);
|
||||
|
||||
if (!ppii.pps()->has_margin())
|
||||
return false;
|
||||
|
||||
/* scan characters [lo, hi) in line buffer.
|
||||
* Newline -> caller should use print_pretty()
|
||||
*/
|
||||
return (ppii.pps()->scan_no_newline(start));
|
||||
} else {
|
||||
/* In default implementation we don't know where to introduce newlines.
|
||||
* Still need to calculate lpos though
|
||||
*/
|
||||
ppii.pps()->write(x);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename Tag>
|
||||
struct ppdetail_tag {
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const Tag & tag)
|
||||
{
|
||||
if (ppii.upto()) {
|
||||
if (tag.prefix_space())
|
||||
ppii.pps()->write(" ");
|
||||
|
||||
/* must color here, because we may keep the output if it fits! */
|
||||
if (!ppii.pps()->print_upto(with_color(color_spec_type::yellow(), // tag_config::tag_color,
|
||||
concat((char const *)":", tag.name()))))
|
||||
return false;
|
||||
|
||||
ppii.pps()->write(" ");
|
||||
|
||||
if (!ppii.pps()->print_upto(tag.value()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
/* pretty-print like
|
||||
* :somename
|
||||
* pretty(value)
|
||||
*/
|
||||
|
||||
if (tag.prefix_space())
|
||||
ppii.pps()->write(" ");
|
||||
ppii.pps()->write(with_color(color_spec_type::yellow(), //tag_config::tag_color,
|
||||
concat((char const *)":", tag.name())));
|
||||
|
||||
ppii.pps()->newline_indent(ppii.ci1());
|
||||
ppii.pps()->pretty(tag.value());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
struct ppdetail<tag_impl<PrefixSpace, TagStyle, Name, Value>> {
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const tag_impl<PrefixSpace, TagStyle, Name, Value> & tag)
|
||||
{
|
||||
using tag_type = tag_impl<PrefixSpace, TagStyle, Name, Value>;
|
||||
|
||||
return detail::ppdetail_tag<tag_type>::print_pretty(ppii, tag);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
struct ppdetail<ref_tag_impl<PrefixSpace, TagStyle, Name, Value>> {
|
||||
static bool print_pretty(const ppindentinfo & ppii,
|
||||
const ref_tag_impl<PrefixSpace, TagStyle, Name, Value> & tag)
|
||||
{
|
||||
using tag_type = ref_tag_impl<PrefixSpace, TagStyle, Name, Value>;
|
||||
|
||||
return detail::ppdetail_tag<tag_type>::print_pretty(ppii, tag);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Name, typename Value>
|
||||
bool
|
||||
ppstate::print_upto_tag(Name && name, Value && value)
|
||||
{
|
||||
return this->print_upto(xrtag(name, value));
|
||||
}
|
||||
|
||||
template <typename Name, typename Value>
|
||||
ppstate &
|
||||
ppstate::newline_pretty_tag(std::uint32_t ci, Name && name, Value && value)
|
||||
{
|
||||
newline_indent(ci);
|
||||
this->pretty(rtag(name, value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
/* @file pretty_concat.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "concat.hpp"
|
||||
#include "pretty.hpp"
|
||||
|
||||
namespace xo {
|
||||
}
|
||||
|
||||
/* end pretty_concat.hpp */
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/* file pretty_tag.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pretty.hpp"
|
||||
#include "tag.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
struct ppdetail<tag_impl<PrefixSpace, TagStyle, Name, Value>> {
|
||||
static bool print_upto(ppstate * pps, const tag_impl<PrefixSpace, TagStyle, Name, Value> & tag) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
|
||||
if (PrefixSpace)
|
||||
pps->write(" ");
|
||||
|
||||
/* skil colorizing here, since doesn't consume visible space */
|
||||
if (!pps->print_upto(concat((char const *)":", concat(tag.name(), (char const *)" "))))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto(quot_impl(TagStyle == tagstyle::autoescape, tag.value())))
|
||||
return false;
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const tag_impl<PrefixSpace, TagStyle, Name, Value> & tag) {
|
||||
/* pretty-print like
|
||||
* :somename
|
||||
* pretty(value)
|
||||
*/
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
|
||||
if (PrefixSpace)
|
||||
pps->write(" ");
|
||||
pps->write(with_color(tag_config::tag_color,
|
||||
concat((char const *)":", tag.name())));
|
||||
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(tag.value());
|
||||
|
||||
pps->newline_indent(ci0);
|
||||
}
|
||||
};
|
||||
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end pretty_tag.hpp */
|
||||
|
|
@ -11,56 +11,47 @@
|
|||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <typename T>
|
||||
struct ppdetail<std::vector<T>> {
|
||||
static bool print_upto(ppstate * pps, const std::vector<T> & x) {
|
||||
std::uint32_t saved = pps->pos();
|
||||
if (!pps->has_margin())
|
||||
template <typename Vector>
|
||||
struct ppdetail_vector {
|
||||
static bool print_pretty(const ppindentinfo & ppii, const Vector & x) {
|
||||
if (ppii.upto()) {
|
||||
ppii.pps()->write("[");
|
||||
for (size_t i = 0, z = x.size(); i < z; ++i) {
|
||||
if (i > 0)
|
||||
ppii.pps()->write(", ");
|
||||
|
||||
if (!ppii.pps()->print_upto(x[i]))
|
||||
return false;
|
||||
if (!ppii.pps()->has_margin())
|
||||
return false;
|
||||
}
|
||||
ppii.pps()->write("]");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
ppii.pps()->write('[');
|
||||
|
||||
for (size_t i = 0, z = x.size(); i < z; ++i) {
|
||||
if (i == 0)
|
||||
ppii.pps()->indent(std::max(ppii.pps()->indent_width(), 1u) - 1);
|
||||
else
|
||||
ppii.pps()->newline_indent(ppii.ci1());
|
||||
ppii.pps()->pretty(x[i]);
|
||||
|
||||
if (i+1 < z)
|
||||
ppii.pps()->write(',');
|
||||
}
|
||||
|
||||
ppii.pps()->write(" ]");
|
||||
return false;
|
||||
|
||||
pps->write("[");
|
||||
for (size_t i = 0, z = x.size(); i < z; ++i) {
|
||||
if (i > 0)
|
||||
pps->write(", ");
|
||||
|
||||
if (!pps->print_upto(x[i]))
|
||||
return false;
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
}
|
||||
pps->write("]");
|
||||
if (!pps->has_margin())
|
||||
return false;
|
||||
|
||||
return pps->scan_no_newline(saved);
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const std::vector<T> & x) {
|
||||
std::uint32_t ci0 = pps->lpos();
|
||||
|
||||
pps->write('[');
|
||||
|
||||
std::uint32_t ci1 = ci0 + pps->indent_width();
|
||||
for (size_t i = 0, z = x.size(); i < z; ++i) {
|
||||
pps->newline_indent(ci1);
|
||||
pps->pretty(x[i]);
|
||||
|
||||
if (i+1 < z)
|
||||
pps->write(',');
|
||||
}
|
||||
|
||||
pps->newline_indent(ci0);
|
||||
pps->write(']');
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ppdetail<const std::vector<T>> {
|
||||
static bool print_upto(ppstate * pps, const std::vector<T> & x) {
|
||||
return ppdetail<std::vector<T>>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const std::vector<T> & x) {
|
||||
ppdetail<std::vector<T>>::print_pretty(pps, x);
|
||||
struct ppdetail<std::vector<T>> {
|
||||
static bool print_pretty(const ppindentinfo & ppii, const std::vector<T> & x) {
|
||||
return ppdetail_vector<std::vector<T>>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,13 +103,13 @@ namespace xo {
|
|||
} /*print*/
|
||||
|
||||
private:
|
||||
/* .unq_flag: if true, omit surrounding " chars
|
||||
* whenever printed value satisfies both:
|
||||
* - no escaped chars
|
||||
* - no spaces
|
||||
*/
|
||||
/** .unq_flag: if true, omit surrounding " chars
|
||||
* whenever printed value satisfies both:
|
||||
* - no escaped chars
|
||||
* - no spaces
|
||||
**/
|
||||
bool unq_flag_ = false;
|
||||
/* .value: value to be printed */
|
||||
/** .value: value to be printed **/
|
||||
T value_;
|
||||
}; /*quot_impl*/
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ namespace xo {
|
|||
return os;
|
||||
} /*operator*/
|
||||
|
||||
/* writing out std::forward<T> behavior for completeness' sake:
|
||||
/** writing out std::forward<T> behavior for completeness' sake:
|
||||
*
|
||||
* 1. call quoted(x) with rvalue std::string x, then:
|
||||
* - T will be deduced to [std::string]
|
||||
|
|
@ -134,7 +134,7 @@ namespace xo {
|
|||
* 2b. call quoted(x) with std::string const & x, then:
|
||||
* - T deduced to [std::string const &]
|
||||
* - std::string const & passed to quot_impl ctor
|
||||
*/
|
||||
**/
|
||||
template<typename T>
|
||||
auto quot(T && x) {
|
||||
return quot_impl(false /*unq_flag*/, std::forward<T>(x));
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace xo {
|
|||
raw,
|
||||
};
|
||||
|
||||
/** K,V pair for printing.
|
||||
/** key-value pair for printing.
|
||||
*
|
||||
* @tparam PrefixSpace if true print one space before :K
|
||||
* @tparam TagStyle controls printing format
|
||||
|
|
@ -63,6 +63,8 @@ namespace xo {
|
|||
tag_impl(Name && n, Value && v)
|
||||
: name_{std::forward<Name>(n)}, value_{std::forward<Value>(v)} {}
|
||||
|
||||
constexpr bool prefix_space() const { return PrefixSpace; }
|
||||
|
||||
Name const & name() const { return name_; }
|
||||
Value const & value() const { return value_; }
|
||||
|
||||
|
|
@ -71,20 +73,52 @@ namespace xo {
|
|||
Value value_;
|
||||
};
|
||||
|
||||
/** key-value pair for printing.
|
||||
* Like tag_impl<..> but uses reference for value.
|
||||
* Use in context where value can't be a temporary rvalue.
|
||||
**/
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
struct ref_tag_impl {
|
||||
ref_tag_impl(Name const & n, Value const & v) : name_{n}, value_{v} {}
|
||||
ref_tag_impl(Name && n, Value && v) : name_{std::forward<Name>(n)}, value_{std::forward<Value>(v)} {}
|
||||
|
||||
constexpr bool prefix_space() const { return PrefixSpace; }
|
||||
|
||||
Name const & name() const { return name_; }
|
||||
Value const & value() const { return value_; }
|
||||
|
||||
private:
|
||||
Name name_;
|
||||
const Value& value_;
|
||||
};
|
||||
|
||||
// ----- xtag -----
|
||||
|
||||
/** Write name,value pair @p n, @p v with format like
|
||||
* :name value
|
||||
* Precede with initial space
|
||||
* Escape whitespace/special characters in @p v
|
||||
**/
|
||||
template<typename Name, typename Value>
|
||||
auto //tag_impl<true, tagstyle::autoescape, Name, std::decay_t<Value>>
|
||||
auto
|
||||
xtag(Name && n, Value && v)
|
||||
{
|
||||
return tag_impl<true, tagstyle::autoescape, Name, std::decay_t<Value>>(n, v);
|
||||
return tag_impl<true, tagstyle::autoescape, std::decay_t<Name>, std::decay_t<Value>>(n, v);
|
||||
} /*xtag*/
|
||||
|
||||
template<typename Value>
|
||||
auto //tag_impl<true, tagstyle::autoescape, char const *, std::decay_t<Value>>
|
||||
xtag(char const * n, Value && v) {
|
||||
return tag_impl<true, tagstyle::autoescape, char const *, std::decay_t<Value>>(n, v);
|
||||
} /*xtag*/
|
||||
// ----- xrtag ----
|
||||
|
||||
/** Write name,value pair @p n, @p v with format like
|
||||
* :name value
|
||||
* Precede with initial space.
|
||||
* Do not escape whitespace/special characters in @p v.
|
||||
**/
|
||||
template<typename Name, typename Value>
|
||||
auto
|
||||
xrtag(Name && n, Value && v)
|
||||
{
|
||||
return tag_impl<true, tagstyle::raw, std::decay_t<Name>, std::decay_t<Value>>(n, v);
|
||||
}
|
||||
|
||||
// ----- tag -----
|
||||
|
||||
|
|
@ -102,6 +136,28 @@ namespace xo {
|
|||
return tag_impl<false, tagstyle::autoescape, char const *, Value>(n, v);
|
||||
}
|
||||
|
||||
// ----- rtag -----
|
||||
|
||||
template<typename Name, typename Value>
|
||||
auto
|
||||
rtag(Name && n, Value && v)
|
||||
{
|
||||
return tag_impl<false, tagstyle::raw, std::decay_t<Name>, std::decay_t<Value>>(n, v);
|
||||
}
|
||||
|
||||
// ----- refrtag -----
|
||||
|
||||
/** 'reference raw tag'.
|
||||
* 1. @p v must survive until refrtag is used (i.e. until tag inserted into some stream)
|
||||
* 2. don't escape whitespace when printing value (pretty-printing with parseable structure)
|
||||
**/
|
||||
template <typename Name, typename Value>
|
||||
auto
|
||||
refrtag(Name && n, Value && v)
|
||||
{
|
||||
return ref_tag_impl<false, tagstyle::raw, std::decay_t<Name>, std::decay_t<Value>>(n, v);
|
||||
}
|
||||
|
||||
// ----- operator<< on tag_impl -----
|
||||
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
|
|
@ -124,6 +180,29 @@ namespace xo {
|
|||
|
||||
return s;
|
||||
} /*operator<<*/
|
||||
|
||||
// ----- operator<< on ref_tag_impl -----
|
||||
|
||||
template <bool PrefixSpace, tagstyle TagStyle, typename Name, typename Value>
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream &s,
|
||||
ref_tag_impl<PrefixSpace, TagStyle, Name, Value> const & tag)
|
||||
{
|
||||
using xo::print::unq;
|
||||
|
||||
if (PrefixSpace)
|
||||
s << " ";
|
||||
|
||||
s << with_color(tag_config::tag_color, concat((char const *)":", tag.name()))
|
||||
<< " ";
|
||||
|
||||
if (TagStyle == tagstyle::autoescape)
|
||||
s << unq(tag.value());
|
||||
else
|
||||
s << tag.value();
|
||||
|
||||
return s;
|
||||
} /*operator<<*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end tag.hpp */
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#include "print/filename.hpp"
|
||||
#include "print/ppstr.hpp"
|
||||
#include "print/tostr.hpp"
|
||||
#include "print/pretty_concat.hpp"
|
||||
#include "print/pretty_tag.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstdint>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,16 @@ namespace xo {
|
|||
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
PPDETAIL_ATOMIC(xo::jit::runtime_binding_path);
|
||||
PPDETAIL_ATOMIC(xo::jit::runtime_binding_detail);
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace jit {
|
||||
/**
|
||||
* 1. pattern for a stack frame associated with a user-defined function (some Lambda lm)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "MachPipeline.hpp"
|
||||
#include "activation_record.hpp"
|
||||
#include "type2llvm.hpp"
|
||||
#include "xo/expression/pretty_variable.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace xo {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ namespace xo {
|
|||
virtual void notify_source_primed(bp<ReactorSource> src) override;
|
||||
virtual std::uint64_t run_one() override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
||||
private:
|
||||
PollingReactor() = default;
|
||||
|
||||
|
|
@ -42,7 +44,17 @@ namespace xo {
|
|||
*/
|
||||
std::vector<ReactorSourcePtr> source_v_;
|
||||
}; /*PollingReactor*/
|
||||
|
||||
} /*namespace reactor*/
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
using PollingReactorPointer = xo::reactor::PollingReactor*;
|
||||
// placeholder, until we implement pretty-printing
|
||||
PPDETAIL_ATOMIC(xo::reactor::PollingReactor);
|
||||
PPDETAIL_ATOMIC(PollingReactorPointer);
|
||||
}
|
||||
#endif
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end PollingReactor.hpp */
|
||||
|
|
|
|||
|
|
@ -61,6 +61,10 @@ namespace xo {
|
|||
*/
|
||||
void run() { this->run_n(-1); }
|
||||
|
||||
/** print self human-readably on stream @p os
|
||||
**/
|
||||
virtual void display(std::ostream & os) const = 0;
|
||||
|
||||
protected:
|
||||
Reactor();
|
||||
|
||||
|
|
@ -68,6 +72,12 @@ namespace xo {
|
|||
/* control logging verbosity */
|
||||
log_level loglevel_;
|
||||
}; /*Reactor*/
|
||||
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream & os, const Reactor & x) {
|
||||
x.display(os);
|
||||
return os;
|
||||
}
|
||||
} /*namespace reactor*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -98,6 +98,15 @@ namespace xo {
|
|||
|
||||
return retval;
|
||||
} /*run_one*/
|
||||
|
||||
void
|
||||
PollingReactor::display(std::ostream & os) const {
|
||||
os << "<PollingReactor"
|
||||
<< xtag("next_ix", next_ix_)
|
||||
<< xtag("source_v.size", source_v_.size())
|
||||
<< ">";
|
||||
}
|
||||
|
||||
} /*namespace reactor*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ namespace xo {
|
|||
**/
|
||||
class envframestack {
|
||||
public:
|
||||
using LocalEnv = xo::ast::LocalEnv;
|
||||
using Variable = xo::ast::Variable;
|
||||
using LocalEnv = xo::ast::LocalEnv;
|
||||
using Variable = xo::ast::Variable;
|
||||
using ppstate = xo::print::ppstate;
|
||||
using ppindentinfo = xo::print::ppindentinfo;
|
||||
|
||||
public:
|
||||
envframestack() {}
|
||||
|
|
@ -58,6 +60,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
void print (std::ostream & os) const;
|
||||
bool pretty_print(const ppindentinfo & ppii) const;
|
||||
|
||||
private:
|
||||
std::vector<rp<LocalEnv>> stack_;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
class parserstatemachine; /* see parserstatemachine.hpp */
|
||||
class exprstatestack;
|
||||
class exprstatestack; /* see exprstatestack.hpp */
|
||||
|
||||
class formal_arg;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ namespace xo {
|
|||
* @brief A stack of exprstate objects
|
||||
**/
|
||||
class exprstatestack {
|
||||
public:
|
||||
using ppstate = xo::print::ppstate;
|
||||
using ppindentinfo = xo::print::ppindentinfo;
|
||||
|
||||
public:
|
||||
exprstatestack() {}
|
||||
|
||||
|
|
@ -45,6 +49,7 @@ namespace xo {
|
|||
}
|
||||
|
||||
void print (std::ostream & os) const;
|
||||
bool pretty_print(const ppindentinfo & ppii) const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<exprstate>> stack_;
|
||||
|
|
@ -65,21 +70,6 @@ namespace xo {
|
|||
return os;
|
||||
}
|
||||
} /*namespace scm*/
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
template <>
|
||||
struct ppdetail<xo::scm::exprstatestack *> {
|
||||
static bool print_upto(ppstate * pps, const xo::scm::exprstatestack * x) {
|
||||
return ppdetail_atomic<const xo::scm::exprstatestack *>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const xo::scm::exprstatestack * x) {
|
||||
ppdetail_atomic<const xo::scm::exprstatestack *>::print_pretty(pps, x);
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -87,13 +87,4 @@ namespace xo {
|
|||
return os;
|
||||
}
|
||||
} /*namespace scm*/
|
||||
|
||||
#ifndef ppdetail_atomic
|
||||
namespace print {
|
||||
PPDETAIL_ATOMIC(xo::scm::parserstatemachine);
|
||||
}
|
||||
#endif
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end parserstatemachine.hpp */
|
||||
|
|
|
|||
20
xo-reader/include/xo/reader/pretty_envframestack.hpp
Normal file
20
xo-reader/include/xo/reader/pretty_envframestack.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* file pretty_envframestack.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "envframestack.hpp"
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <>
|
||||
struct ppdetail<xo::scm::envframestack*> {
|
||||
static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::envframestack * p) {
|
||||
return p->pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
20
xo-reader/include/xo/reader/pretty_exprstatestack.hpp
Normal file
20
xo-reader/include/xo/reader/pretty_exprstatestack.hpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* file pretty_exprstatestack.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "exprstatestack.hpp"
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template <>
|
||||
struct ppdetail<xo::scm::exprstatestack*> {
|
||||
static inline bool print_pretty(const ppindentinfo & ppii, const xo::scm::exprstatestack * p) {
|
||||
return p->pretty_print(ppii);
|
||||
}
|
||||
};
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
18
xo-reader/include/xo/reader/pretty_parserstatemachine.hpp
Normal file
18
xo-reader/include/xo/reader/pretty_parserstatemachine.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/* file pretty_parserstatemachine.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "parserstatemachine.hpp"
|
||||
#include "xo/indentlog/print/pretty.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
template<>
|
||||
struct ppdetail<xo::scm::parserstatemachine> {
|
||||
static bool print_pretty(const ppindentinfo & ppii, const xo::scm::parserstatemachine & x);
|
||||
};
|
||||
}
|
||||
} /*namespace xo*/
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# parser/CMakeLists.txt
|
||||
# reader/CMakeLists.txt
|
||||
|
||||
set(SELF_LIB xo_reader)
|
||||
set(SELF_SRCS
|
||||
|
|
@ -19,7 +19,9 @@ set(SELF_SRCS
|
|||
expect_type_xs.cpp
|
||||
lambda_xs.cpp
|
||||
let1_xs.cpp
|
||||
envframestack.cpp)
|
||||
envframestack.cpp
|
||||
pretty_parserstatemachine.cpp
|
||||
)
|
||||
|
||||
xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS})
|
||||
xo_dependency(${SELF_LIB} xo_expression)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
*/
|
||||
|
||||
#include "envframestack.hpp"
|
||||
#include "pretty_envframestack.hpp"
|
||||
#include "pretty_localenv.hpp"
|
||||
|
||||
namespace xo {
|
||||
using xo::ast::LocalEnv;
|
||||
|
|
@ -92,6 +94,45 @@ namespace xo {
|
|||
|
||||
os << ">" << std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
envframestack::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (stack_.size() > 1)
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto("<envframestack"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("size", stack_.size()))
|
||||
return false;
|
||||
|
||||
if ((stack_.size() > 0)
|
||||
&& !pps->print_upto_tag("[0]", stack_[0]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<envframestack");
|
||||
|
||||
pps->newline_pretty_tag(ppii.ci1(), "size", stack_.size());
|
||||
|
||||
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
|
||||
std::string i_str = tostr("[", z-i-1, "]");
|
||||
pps->newline_pretty_tag(ppii.ci1(), i_str, stack_[i]);
|
||||
}
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "exprstate.hpp"
|
||||
#include "exprstatestack.hpp"
|
||||
#include "parserstatemachine.hpp"
|
||||
#include "pretty_parserstatemachine.hpp"
|
||||
#include "pretty_expression.hpp"
|
||||
//#include "formal_arg.hpp"
|
||||
#include "xo/expression/Variable.hpp"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
#include "exprstatestack.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace scm {
|
||||
|
|
@ -65,6 +66,48 @@ namespace xo {
|
|||
|
||||
os << ">" << std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
exprstatestack::pretty_print(const ppindentinfo & ppii) const
|
||||
{
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (stack_.size() > 1)
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto("<exprstatestack"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("size", stack_.size()))
|
||||
return false;
|
||||
|
||||
/** always multiple lines if more than one element in stack **/
|
||||
if ((stack_.size() > 0)
|
||||
&& !pps->print_upto_tag("[0]", *stack_[0].get()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
pps->write("<exprstatestack");
|
||||
|
||||
pps->newline_pretty_tag(ppii.ci1(), "size", stack_.size());
|
||||
|
||||
for (std::size_t i = 0, z = stack_.size(); i < z; ++i) {
|
||||
std::string i_str = tostr("[", z-i-1, "]");
|
||||
|
||||
pps->newline_pretty_tag(ppii.ci1(), i_str, *stack_[i].get());
|
||||
}
|
||||
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
#include "parserstatemachine.hpp"
|
||||
#include "exprstatestack.hpp"
|
||||
#include "pretty_parserstatemachine.hpp"
|
||||
#include "pretty_envframestack.hpp"
|
||||
#include "pretty_localenv.hpp"
|
||||
#include "xo/expression/pretty_expression.hpp"
|
||||
|
||||
namespace xo {
|
||||
|
|
|
|||
44
xo-reader/src/reader/pretty_parserstatemachine.cpp
Normal file
44
xo-reader/src/reader/pretty_parserstatemachine.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* file pretty_parserstatemachine.cpp
|
||||
*
|
||||
* author: Roland Conybeare, Jul 2025
|
||||
*/
|
||||
|
||||
#include "pretty_parserstatemachine.hpp"
|
||||
#include "pretty_exprstatestack.hpp"
|
||||
#include "pretty_envframestack.hpp"
|
||||
#include "exprstatestack.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
bool
|
||||
ppdetail<xo::scm::parserstatemachine>::print_pretty(const ppindentinfo & ppii, const xo::scm::parserstatemachine & x)
|
||||
{
|
||||
ppstate * pps = ppii.pps();
|
||||
|
||||
if (ppii.upto()) {
|
||||
if (!pps->print_upto("<psm"))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("stack", x.p_stack_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("env_stack", x.p_env_stack_))
|
||||
return false;
|
||||
|
||||
if (!pps->print_upto_tag("emit_expr", (void*)x.p_emit_expr_))
|
||||
return false;
|
||||
|
||||
return pps->print_upto(">");
|
||||
} else {
|
||||
pps->write("<psm");
|
||||
pps->newline_pretty_tag(ppii.ci1(), "stack", x.p_stack_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "env_stack", x.p_env_stack_);
|
||||
pps->newline_pretty_tag(ppii.ci1(), "emit_expr", (void*)x.p_emit_expr_);
|
||||
pps->write(">");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} /*namespace print*/
|
||||
} /*namespace xo*/
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "exprstatestack.hpp"
|
||||
#include "expect_expr_xs.hpp"
|
||||
#include "parserstatemachine.hpp"
|
||||
#include "pretty_exprstatestack.hpp"
|
||||
#include "xo/expression/AssignExpr.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include "xo/expression/pretty_expression.hpp"
|
||||
|
|
|
|||
|
|
@ -10,66 +10,67 @@
|
|||
|
||||
namespace xo {
|
||||
namespace print {
|
||||
#ifndef ppdetail_atomic
|
||||
template <>
|
||||
struct ppdetail<xo::ref::Refcount *> {
|
||||
static bool print_upto(ppstate * pps, const xo::ref::Refcount * x) {
|
||||
return ppdetail_atomic<const xo::ref::Refcount *>::print_upto(pps, x);
|
||||
}
|
||||
static void print_pretty(ppstate * pps, const xo::ref::Refcount * x) {
|
||||
ppdetail_atomic<const xo::ref::Refcount *>::print_pretty(pps, x);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const xo::ref::Refcount * x) {
|
||||
return ppdetail_atomic<const xo::ref::Refcount *>::print_pretty(ppii, x);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct ppdetail<rp<T>> {
|
||||
static bool print_upto(ppstate * pps, const rp<T> & x) {
|
||||
if (auto p = x.get()) {
|
||||
return ppdetail<T>::print_upto(pps, *p);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const rp<T> & x) {
|
||||
if (ppii.upto()) {
|
||||
if (auto p = x.get()) {
|
||||
return ppdetail<T>::print_pretty(ppii, *p);
|
||||
} else {
|
||||
/* note: degenerate case here, since never write newline for nullptr */
|
||||
|
||||
ppii.pps()->write("<nullptr ");
|
||||
ppii.pps()->write(reflect::type_name<T>());
|
||||
ppii.pps()->write(">");
|
||||
|
||||
return ppii.pps()->has_margin();
|
||||
}
|
||||
} else {
|
||||
/* note: degenerate case here, since never write newline for nullptr */
|
||||
|
||||
pps->write("<nullptr ");
|
||||
pps->write(reflect::type_name<T>());
|
||||
pps->write(">");
|
||||
|
||||
return pps->has_margin();
|
||||
}
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const rp<T> & x) {
|
||||
if (auto p = x.get()) {
|
||||
ppdetail<T>::print_pretty(pps, *p);
|
||||
} else {
|
||||
pps->write("<nullptr ");
|
||||
pps->write(reflect::type_name<T>());
|
||||
pps->write(">");
|
||||
if (auto p = x.get()) {
|
||||
ppdetail<T>::print_pretty(ppii, *p);
|
||||
} else {
|
||||
ppii.pps()->write("<nullptr ");
|
||||
ppii.pps()->write(reflect::type_name<T>());
|
||||
ppii.pps()->write(">");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ppdetail<bp<T>> {
|
||||
static bool print_upto(ppstate * pps, const bp<T> & x) {
|
||||
if (auto p = x.get()) {
|
||||
return ppdetail<T>::print_upto(pps, *p);
|
||||
static bool print_pretty(const ppindentinfo & ppii, const bp<T> & x) {
|
||||
if (ppii.upto()) {
|
||||
if (auto p = x.get()) {
|
||||
return ppdetail<T>::print_pretty(ppii, *p);
|
||||
} else {
|
||||
/* note: degenerate case here, since never write newline for nullptr */
|
||||
|
||||
ppii.pps()->write("<nullptr ");
|
||||
ppii.pps()->write(reflect::type_name<T>());
|
||||
ppii.pps()->write(">");
|
||||
|
||||
return ppii.pps()->has_margin();
|
||||
}
|
||||
} else {
|
||||
/* note: degenerate case here, since never write newline for nullptr */
|
||||
|
||||
pps->write("<nullptr ");
|
||||
pps->write(reflect::type_name<T>());
|
||||
pps->write(">");
|
||||
|
||||
return pps->has_margin();
|
||||
}
|
||||
}
|
||||
|
||||
static void print_pretty(ppstate * pps, const bp<T> & x) {
|
||||
if (auto p = x.get()) {
|
||||
ppdetail<T>::print_pretty(pps, *p);
|
||||
} else {
|
||||
pps->write("<nullptr ");
|
||||
pps->write(reflect::type_name<T>());
|
||||
pps->write(">");
|
||||
if (auto p = x.get()) {
|
||||
ppdetail<T>::print_pretty(ppii, *p);
|
||||
} else {
|
||||
ppii.pps()->write("<nullptr ");
|
||||
ppii.pps()->write(reflect::type_name<T>());
|
||||
ppii.pps()->write(">");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -218,6 +218,8 @@ namespace xo {
|
|||
/* synonym for .advance_one_event() */
|
||||
virtual std::uint64_t run_one() override;
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
||||
private:
|
||||
explicit Simulator(utc_nanos t0);
|
||||
|
||||
|
|
|
|||
|
|
@ -543,6 +543,16 @@ namespace xo {
|
|||
return n;
|
||||
} /*run_throttled_until*/
|
||||
|
||||
void
|
||||
Simulator::display(std::ostream & os) const
|
||||
{
|
||||
os << "<Simulator"
|
||||
<< xtag("sim_heap.size", sim_heap_.size())
|
||||
<< xtag("n_event", n_event_)
|
||||
<< xtag("src_v.size", src_v_.size())
|
||||
<< ">";
|
||||
} /*display*/
|
||||
|
||||
} /*namespace sim*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "xo/unit/basis_unit.hpp"
|
||||
#include "xo/unit/bu_store.hpp"
|
||||
#include "xo/indentlog/scope.hpp"
|
||||
#include "xo/flatstring/flatstring_pretty.hpp"
|
||||
//#include "xo/indentlog/print/tag.hpp"
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue