From d780414989ef7e101cdaf269d4b01003d0721e6a Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 11 Sep 2011 11:06:34 +0200 Subject: Generalize pragma code to support arbitrary types for context values --- odb/context.hxx | 28 +++++++ odb/parser.cxx | 44 +++-------- odb/pragma.cxx | 152 +++++++++++++++++++++++++------------- odb/pragma.hxx | 39 +++++----- odb/relational/schema.cxx | 63 ++++++---------- odb/relational/type-processor.cxx | 37 ++++------ odb/validator.cxx | 10 +-- 7 files changed, 201 insertions(+), 172 deletions(-) diff --git a/odb/context.hxx b/odb/context.hxx index cb8e2ef..ea351de 100644 --- a/odb/context.hxx +++ b/odb/context.hxx @@ -6,6 +6,8 @@ #ifndef ODB_CONTEXT_HXX #define ODB_CONTEXT_HXX +#include + #include #include #include @@ -67,6 +69,32 @@ enum class_kind class_other }; +// Semantic graph context types. +// +struct view_object +{ + tree node; + std::string name; + semantics::class_* object; +}; + +struct default_value +{ + enum kind_type + { + reset, // Default value reset. + null, + boolean, + number, // Integer of floating-point number. Value contains sign. + string, + enumerator // Value is the name, node is the tree node. + }; + + kind_type kind; + std::string value; + tree node; +}; + class context { public: diff --git a/odb/parser.cxx b/odb/parser.cxx index b615a2f..b8ea160 100644 --- a/odb/parser.cxx +++ b/odb/parser.cxx @@ -1902,49 +1902,23 @@ void parser::impl:: add_pragma (node& n, pragma const& p) { if (trace) - ts << "\t\t pragma " << p.pragma_name << " (" << p.value << ")" << endl; + ts << "\t\t pragma " << p.pragma_name << endl; // Convert '_' to '-' in the pragma name so we get foo-bar instead // of foo_bar (that's the convention used). // - string kv (p.context_name); - for (size_t i (0); i < kv.size (); ++i) - if (kv[i] == '_') - kv[i] = '-'; + string k (p.context_name); + for (size_t i (0); i < k.size (); ++i) + if (k[i] == '_') + k[i] = '-'; - string kl (kv + "-loc"); - string kn (kv + "-node"); - - if (p.mode == pragma::override) + if (p.add == 0) { - n.set (kv, p.value); - n.set (kn, p.node); - n.set (kl, p.loc); + n.set (k, p.value); + n.set (k + "-location", p.loc); } else - { - // Having three parallel vectors is not the most efficient - // way to store this, but it is quite simple. - // - typedef vector values; - typedef vector nodes; - typedef vector locations; - - if (!n.count (kv)) - { - n.set (kv, values ()); - n.set (kn, nodes ()); - n.set (kl, locations ()); - } - - values& vs (n.get (kv)); - nodes& ns (n.get (kn)); - locations& ls (n.get (kl)); - - vs.push_back (p.value); - ns.push_back (p.node); - ls.push_back (p.loc); - } + p.add (n, k, p.value, p.loc); } void parser::impl:: diff --git a/odb/pragma.cxx b/odb/pragma.cxx index a6ec579..ea2a696 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -5,11 +5,35 @@ #include +#include + #include #include #include +#include using namespace std; +using namespace cutl; + +using container::any; + +template +void +accumulate (compiler::context& ctx, string const& k, any const& v, location_t) +{ + // Empty values are used to indicate that this pragma must be ignored. + // + if (v.empty ()) + return; + + typedef vector container; + + container& c (ctx.count (k) + ? ctx.get (k) + : ctx.set (k, container ())); + + c.push_back (v.value ()); +} // Lists of pragmas. // @@ -311,10 +335,9 @@ handle_pragma (cpp_reader* reader, cpp_ttype tt; string name (p); // Pragma name. - string val; // Pragma string value. - tree node (0); // Pragma tree node value. + any val; // Pragma value. + pragma::add_func adder (0); // Custom context adder. location_t loc (input_location); // Pragma location. - pragma::mode_type mode (pragma::override); // Pragma mode. if (p == "table") { @@ -340,7 +363,7 @@ handle_pragma (cpp_reader* reader, return; } - val = TREE_STRING_POINTER (t); + val = string (TREE_STRING_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -366,6 +389,7 @@ handle_pragma (cpp_reader* reader, return; } + string v; size_t pb (0); bool punc (false); @@ -374,7 +398,7 @@ handle_pragma (cpp_reader* reader, tt = pragma_lex (&t)) { if (punc && tt > CPP_LAST_PUNCTUATOR) - val += ' '; + v += ' '; punc = false; @@ -389,29 +413,29 @@ handle_pragma (cpp_reader* reader, { case CPP_LESS: { - val += "< "; + v += "< "; break; } case CPP_GREATER: { - val += " >"; + v += " >"; break; } case CPP_COMMA: { - val += ", "; + v += ", "; break; } case CPP_NAME: { - val += IDENTIFIER_POINTER (t); + v += IDENTIFIER_POINTER (t); punc = true; break; } default: { if (tt <= CPP_LAST_PUNCTUATOR) - val += cxx_lexer::token_spelling[tt]; + v += cxx_lexer::token_spelling[tt]; else { error () << "unexpected token '" << cxx_lexer::token_spelling[tt] @@ -429,12 +453,14 @@ handle_pragma (cpp_reader* reader, return; } - if (val.empty ()) + if (v.empty ()) { error () << "expected pointer name in db pragma " << p << endl; return; } + val = v; + tt = pragma_lex (&t); } else if (p == "abstract") @@ -473,7 +499,7 @@ handle_pragma (cpp_reader* reader, return; } - val = IDENTIFIER_POINTER (t); + val = string (IDENTIFIER_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -507,7 +533,7 @@ handle_pragma (cpp_reader* reader, return; } - val = TREE_STRING_POINTER (t); + val = string (TREE_STRING_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -541,11 +567,10 @@ handle_pragma (cpp_reader* reader, return; } - name = "objects"; // Change the context entry name. - mode = pragma::accumulate; - node = parse_scoped_name (t, tt, val, true, p); + view_object vo; + vo.node = parse_scoped_name (t, tt, vo.name, true, p); - if (node == 0) + if (vo.node == 0) return; // Diagnostics has already been issued. if (tt != CPP_CLOSE_PAREN) @@ -554,6 +579,10 @@ handle_pragma (cpp_reader* reader, return; } + val = vo; + name = "objects"; // Change the context entry name. + adder = &accumulate; + tt = pragma_lex (&t); } else if (p == "id") @@ -612,7 +641,7 @@ handle_pragma (cpp_reader* reader, return; } - val = TREE_STRING_POINTER (t); + val = string (TREE_STRING_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -648,16 +677,26 @@ handle_pragma (cpp_reader* reader, tt = pragma_lex (&t); - // An empty options specifier signals options reset. - // if (tt == CPP_STRING) { - val = TREE_STRING_POINTER (t); + string o (TREE_STRING_POINTER (t)); + + // Ignore empty options strings. Internally, we use them to + // indicate options reset (see below). + // + if (!o.empty ()) + val = string (TREE_STRING_POINTER (t)); + tt = pragma_lex (&t); } - // Empty options specifier signals options reset. - // - else if (tt != CPP_CLOSE_PAREN) + else if (tt == CPP_CLOSE_PAREN) + { + // Empty options specifier signals options reset. Encode it as an + // empty string. + // + val = string (); + } + else { error () << "options string expected in db pragma " << p << endl; return; @@ -669,7 +708,7 @@ handle_pragma (cpp_reader* reader, return; } - mode = pragma::accumulate; + adder = &accumulate; tt = pragma_lex (&t); } else if (p == "type" || @@ -704,7 +743,7 @@ handle_pragma (cpp_reader* reader, return; } - val = TREE_STRING_POINTER (t); + val = string (TREE_STRING_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -756,34 +795,41 @@ handle_pragma (cpp_reader* reader, tt = pragma_lex (&t); - // Encode the kind of value we have in the first letter of - // the string. - // + default_value dv; + switch (tt) { case CPP_CLOSE_PAREN: { - // Default value override. + // Default value reset. // + dv.kind = default_value::reset; break; } case CPP_STRING: { - val = "s"; - val += TREE_STRING_POINTER (t); + dv.kind = default_value::string; + dv.value = TREE_STRING_POINTER (t); tt = pragma_lex (&t); break; } case CPP_NAME: { - // This can be the null, true, or false keyword or a enumerator + // This can be the null, true, or false keyword or an enumerator // name. // string n (IDENTIFIER_POINTER (t)); - if (n == "null" || n == "true" || n == "false") + if (n == "null") { - val = n[0]; + dv.kind = default_value::null; + tt = pragma_lex (&t); + break; + } + else if (n == "true" || n == "false") + { + dv.kind = default_value::boolean; + dv.value = n; tt = pragma_lex (&t); break; } @@ -793,26 +839,27 @@ handle_pragma (cpp_reader* reader, { // We have a potentially scopped enumerator name. // - string n; - tree decl (parse_scoped_name (t, tt, n, false, p)); + dv.node = parse_scoped_name (t, tt, dv.value, false, p); - if (decl == 0) + if (dv.node == 0) return; // Diagnostics has already been issued. - node = decl; - val = "e" + n; + dv.kind = default_value::enumerator; break; } case CPP_MINUS: case CPP_PLUS: { - val = (tt == CPP_MINUS ? "-" : "+"); + if (tt == CPP_MINUS) + dv.value = "-"; + tt = pragma_lex (&t); if (tt != CPP_NUMBER) { - error () << "expected numeric constant after '" << val - << "' in db pragma " << p << endl; + error () << "expected numeric constant after '" + << (tt == CPP_MINUS ? "-" : "+") << "' in db pragma " + << p << endl; return; } @@ -828,10 +875,8 @@ handle_pragma (cpp_reader* reader, return; } - if (val.empty ()) - val = "+"; - - node = t; + dv.node = t; + dv.kind = default_value::number; tt = pragma_lex (&t); break; } @@ -848,6 +893,7 @@ handle_pragma (cpp_reader* reader, return; } + val = dv; tt = pragma_lex (&t); } else if (p == "inverse") @@ -874,7 +920,7 @@ handle_pragma (cpp_reader* reader, return; } - val = IDENTIFIER_POINTER (t); + val = string (IDENTIFIER_POINTER (t)); if (pragma_lex (&t) != CPP_CLOSE_PAREN) { @@ -914,9 +960,15 @@ handle_pragma (cpp_reader* reader, return; } + // If the value is not specified and we don't use a custom adder, + // then make it bool (flag). + // + if (adder == 0 && val.empty ()) + val = true; + // Record this pragma. // - pragma prag (mode, p, name, val, node, loc, &check_spec_decl_type); + pragma prag (p, name, val, loc, &check_spec_decl_type, adder); if (decl) decl_pragmas_[decl].insert (prag); @@ -1073,7 +1125,7 @@ handle_pragma_qualifier (cpp_reader* reader, string const& p) // Record this pragma. // - pragma prag (pragma::override, p, p, "", 0, loc, &check_qual_decl_type); + pragma prag (p, p, any (true), loc, &check_qual_decl_type, 0); if (decl) decl_pragmas_[decl].insert (prag); diff --git a/odb/pragma.hxx b/odb/pragma.hxx index 5ff6165..ba4aab8 100644 --- a/odb/pragma.hxx +++ b/odb/pragma.hxx @@ -13,10 +13,11 @@ #include #include +#include +#include + struct pragma { - enum mode_type {override, accumulate}; - // Check that the pragma is applicable to the declaration. Return true // on success, complain and return false otherwise. // @@ -25,46 +26,50 @@ struct pragma std::string const& prag_name, location_t); - pragma (mode_type m, - std::string const& pn, + // Add the pragma value to the context. + // + typedef void (*add_func) (cutl::compiler::context&, + std::string const& key, + cutl::container::any const& value, + location_t); + + pragma (std::string const& pn, std::string const& cn, - std::string const& v, - tree n, + cutl::container::any const& v, location_t l, - check_func c) - : mode (m), - pragma_name (pn), + check_func c, + add_func a) + : pragma_name (pn), context_name (cn), value (v), - node (n), loc (l), - check (c) + check (c), + add (a) { } bool operator< (pragma const& y) const { - if (mode == override) + if (add == 0) return pragma_name < y.pragma_name; else return pragma_name < y.pragma_name || (pragma_name == y.pragma_name && loc < y.loc); } - mode_type mode; std::string pragma_name; // Actual pragma name for diagnostics. std::string context_name; // Context entry name. - std::string value; - tree node; + cutl::container::any value; location_t loc; check_func check; + add_func add; }; typedef std::vector pragma_list; -// A set of pragmas. Insertion of a pragma with the same name and override -// mode overrides the old value. +// A set of pragmas. Insertion of a pragma with the same name and no +// custom add function overrides the old value. // struct pragma_set: std::set { diff --git a/odb/relational/schema.cxx b/odb/relational/schema.cxx index c55837e..df871e7 100644 --- a/odb/relational/schema.cxx +++ b/odb/relational/schema.cxx @@ -25,56 +25,38 @@ namespace relational void object_columns:: default_ (semantics::data_member& m) { - string s; - tree n (0); + default_value* dv (0); semantics::type& t (m.type ()); if (m.count ("default")) - { - s = m.get ("default"); - - // Empty string is a default value override which means - // there is no default value. - // - if (s.empty ()) - return; - - if (m.count ("default-node")) - n = m.get ("default-node"); - } + dv = &m.get ("default"); else if (t.count ("default")) - { - s = t.get ("default"); - - if (s.empty ()) - return; - - if (t.count ("default-node")) - n = t.get ("default-node"); - } + dv = &t.get ("default"); else return; // No default value for this column. - // The first letter in the default value string identifies - // the type of the value. See pragma.cxx for details. - // - switch (s[0]) + switch (dv->kind) { - case 'n': + case default_value::reset: + { + // No default value. + break; + } + case default_value::null: { default_null (m); break; } - case 't': - case 'f': + case default_value::boolean: { - default_bool (m, s[0] == 't'); + default_bool (m, dv->value == "true"); break; } - case '+': - case '-': + case default_value::number: { + tree n (dv->node); + switch (TREE_CODE (n)) { case INTEGER_CST: @@ -88,7 +70,7 @@ namespace relational unsigned long long v ((h << width) + l); - default_integer (m, v, s[0] == '-'); + default_integer (m, v, dv->value == "-"); break; } case REAL_CST: @@ -109,7 +91,7 @@ namespace relational is >> v; } - if (s[0] == '-') + if (dv->value == "-") v = -v; default_float (m, v); @@ -120,19 +102,16 @@ namespace relational } break; } - - case 's': + case default_value::string: { - default_string (m, string (s, 1, string::npos)); + default_string (m, dv->value); break; } - case 'e': + case default_value::enumerator: { - default_enum (m, n, string (s, 1, string::npos)); + default_enum (m, dv->node, dv->value); break; } - default: - assert (false); } } diff --git a/odb/relational/type-processor.cxx b/odb/relational/type-processor.cxx index 14b546e..a74af9b 100644 --- a/odb/relational/type-processor.cxx +++ b/odb/relational/type-processor.cxx @@ -411,7 +411,7 @@ namespace relational // Mark id column as not null. // - t.set ("id-not-null", string ()); + t.set ("id-not-null", true); // Get the value type. // @@ -465,7 +465,7 @@ namespace relational throw generation_failed (); } else - t.set ("value-not-null", string ()); + t.set ("value-not-null", true); } // Issue a warning if we are relaxing null-ness in the @@ -517,7 +517,7 @@ namespace relational t.set ("index-tree-type", it); t.set ("index-tree-hint", ih); - t.set ("index-not-null", string ()); + t.set ("index-not-null", true); } // Get the key type for maps. @@ -559,7 +559,7 @@ namespace relational t.set ("key-tree-type", kt); t.set ("key-tree-hint", kh); - t.set ("key-not-null", string ()); + t.set ("key-not-null", true); } } @@ -581,7 +581,7 @@ namespace relational // no concept of order in this construct. // if (ck == ck_ordered && m.count ("value-inverse")) - m.set ("unordered", string ()); // Keep compatible with pragma. + m.set ("unordered", true); // Issue an error if we have a null column in a set container. // This can only happen if the value is declared as null in @@ -1110,33 +1110,24 @@ namespace relational virtual void traverse_view (type& c) { - // Convert referenced objects from tree nodes to semantic graph + // Resolve referenced objects from tree nodes to semantic graph // nodes. // if (c.count ("objects")) { using semantics::class_; + typedef vector objects; - typedef vector tree_nodes; - typedef vector class_nodes; + objects& objs (c.get ("objects")); - strings names (c.get ("objects")); - tree_nodes tnodes (c.get ("objects-node")); - - c.remove ("objects"); - c.remove ("objects-node"); - - c.set ("objects", class_nodes ()); - class_nodes& nodes (c.get ("objects")); - - for (size_t i (0); i < names.size (); ++i) + for (objects::iterator i (objs.begin ()); i < objs.end (); ++i) { - tree n (TYPE_MAIN_VARIANT (tnodes[i])); + tree n (TYPE_MAIN_VARIANT (i->node)); if (TREE_CODE (n) != RECORD_TYPE) { os << c.file () << ":" << c.line () << ":" << c.column () << ":" - << " error: name '" << names[i] << "' in db pragma object " + << " error: name '" << i->name << "' in db pragma object " << " does not name a class" << endl; throw generation_failed (); @@ -1147,17 +1138,17 @@ namespace relational if (!object (o)) { os << c.file () << ":" << c.line () << ":" << c.column () << ":" - << " error: name '" << names[i] << "' in db pragma object " + << " error: name '" << i->name << "' in db pragma object " << "does not name a persistent class" << endl; os << o.file () << ":" << o.line () << ":" << o.column () << ":" - << " info: class '" << names[i] << "' is defined here" + << " info: class '" << i->name << "' is defined here" << endl; throw generation_failed (); } - nodes.push_back (&o); + i->object = &o; } } } diff --git a/odb/validator.cxx b/odb/validator.cxx index 0494741..bf7784e 100644 --- a/odb/validator.cxx +++ b/odb/validator.cxx @@ -24,16 +24,16 @@ namespace if (n.count (p + "null") && n.count (p + "not-null")) { - if (n.get (p + "null-loc") < - n.get (p + "not-null-loc")) + if (n.get (p + "null-location") < + n.get (p + "not-null-location")) { n.remove (p + "null"); - n.remove (p + "null-loc"); + n.remove (p + "null-location"); } else { n.remove (p + "not-null"); - n.remove (p + "not-null-loc"); + n.remove (p + "not-null-location"); } } } @@ -334,7 +334,7 @@ namespace valid_ = false; } else - id->set ("not-null", string ()); + id->set ("not-null", true); } // Check members. -- cgit v1.1