/*++ Copyright (c) 2006 Microsoft Corporation Module Name: format.cpp Abstract: Author: Leonardo de Moura (leonardo) 2008-01-20. Revision History: --*/ #include"format.h" #include"recurse_expr_def.h" namespace format_ns { class format_decl_plugin : public decl_plugin { protected: sort * m_format_sort; symbol m_nil; symbol m_string; symbol m_indent; symbol m_compose; symbol m_choice; symbol m_line_break; symbol m_line_break_ext; virtual void set_manager(ast_manager * m, family_id id) { SASSERT(m->is_format_manager()); decl_plugin::set_manager(m, id); m_format_sort = m->mk_sort(symbol("format"), sort_info(id, FORMAT_SORT)); m->inc_ref(m_format_sort); } public: format_decl_plugin(): m_format_sort(0), m_nil("nil"), m_string("string"), m_indent("indent"), m_compose("compose"), m_choice("choice"), m_line_break("cr"), m_line_break_ext("cr++") { } virtual ~format_decl_plugin() {} virtual void finalize() { if (m_format_sort) m_manager->dec_ref(m_format_sort); } virtual decl_plugin * mk_fresh() { return alloc(format_decl_plugin); } virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const* parameters) { SASSERT(k == FORMAT_SORT); return m_format_sort; } virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned arity, sort * const * domain, sort * range) { switch (k) { case OP_NIL: return m_manager->mk_func_decl(m_nil, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_NIL)); case OP_STRING: return m_manager->mk_func_decl(m_string, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_STRING, num_parameters, parameters)); case OP_INDENT: return m_manager->mk_func_decl(m_indent, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_INDENT, num_parameters, parameters)); case OP_COMPOSE: return m_manager->mk_func_decl(m_compose, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_COMPOSE)); case OP_CHOICE: return m_manager->mk_func_decl(m_choice, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_CHOICE)); case OP_LINE_BREAK: return m_manager->mk_func_decl(m_line_break, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_LINE_BREAK)); case OP_LINE_BREAK_EXT: return m_manager->mk_func_decl(m_line_break_ext, arity, domain, m_format_sort, func_decl_info(m_family_id, OP_LINE_BREAK_EXT, num_parameters, parameters)); default: return 0; } } }; family_id get_format_family_id(ast_manager & m) { symbol f("format"); if (!fm(m).has_plugin(f)) fm(m).register_plugin(f, alloc(format_decl_plugin)); return fm(m).get_family_id(f); } static family_id fid(ast_manager & m) { return get_format_family_id(m); } sort * fsort(ast_manager & m) { return fm(m).mk_sort(fid(m), FORMAT_SORT); } struct flat_visitor { ast_manager & m_manager; family_id m_fid; flat_visitor(ast_manager & m): m_manager(fm(m)), m_fid(fid(m)) { SASSERT(m_manager.is_format_manager()); } format * visit(var *) { UNREACHABLE(); return 0; } format * visit(quantifier * q, format *, format * const *, format * const *) { UNREACHABLE(); return 0; } format * visit(format * n, format * const * children) { if (is_app_of(n, m_fid, OP_LINE_BREAK)) return mk_string(m_manager, " "); else if (is_app_of(n, m_fid, OP_LINE_BREAK_EXT)) return mk_string(m_manager, n->get_decl()->get_parameter(0).get_symbol().bare_str()); else if (is_app_of(n, m_fid, OP_CHOICE)) return to_app(n->get_arg(0)); else return m_manager.mk_app(n->get_decl(), n->get_num_args(), (expr *const*) children); } }; format * flat(ast_manager & m, format * f) { flat_visitor v(m); recurse_expr r(v); return r(f); } format * mk_string(ast_manager & m, char const * str) { symbol s(str); parameter p(s); return fm(m).mk_app(fid(m), OP_STRING, 1, &p, 0, 0); } format * mk_int(ast_manager & m, int i) { static char buffer[128]; #ifdef _WINDOWS sprintf_s(buffer, ARRAYSIZE(buffer), "%d", i); #else sprintf(buffer, "%d", i); #endif return mk_string(m, buffer); } format * mk_unsigned(ast_manager & m, unsigned u) { static char buffer[128]; #ifdef _WINDOWS sprintf_s(buffer, ARRAYSIZE(buffer), "%u", u); #else sprintf(buffer, "%u", u); #endif return mk_string(m, buffer); } format * mk_indent(ast_manager & m, unsigned i, format * f) { parameter p(i); expr * e = static_cast(f); return fm(m).mk_app(fid(m), OP_INDENT, 1, &p, 1, &e); } format * mk_line_break(ast_manager & m) { return fm(m).mk_app(fid(m), OP_LINE_BREAK); } format * mk_choice(ast_manager & m, format * f1, format * f2) { return fm(m).mk_app(fid(m), OP_CHOICE, f1, f2); } format * mk_group(ast_manager & m, format * f) { return mk_choice(m, flat(m, f), f); } format * mk_compose(ast_manager & m, unsigned num_children, format * const * children) { return fm(m).mk_app(fid(m), OP_COMPOSE, num_children, (expr * const *) children); } format * mk_compose(ast_manager & m, format * f1, format * f2) { return fm(m).mk_app(fid(m), OP_COMPOSE, f1, f2); } format * mk_compose(ast_manager & m, format * f1, format * f2, format * f3) { return fm(m).mk_app(fid(m), OP_COMPOSE, f1, f2, f3); } format * mk_compose(ast_manager & m, format * f1, format * f2, format * f3, format * f4) { expr * f[4] = { f1, f2, f3, f4 }; return fm(m).mk_app(fid(m), OP_COMPOSE, 4, f); } format * mk_nil(ast_manager & m) { return fm(m).mk_app(fid(m), OP_NIL); } };