Symbol: switch to using the symbol-table as backing implementation (#158)

...which means, from now on identical input strings
will produce the same Symbol object (embedded pointer).

TODO: does not handle null pointers passed in as c-String properly
This commit is contained in:
Fischlurch 2017-04-07 06:34:41 +02:00
parent f9c3b8b61c
commit 29b8b2b8bc
5 changed files with 116 additions and 63 deletions

View file

@ -48,6 +48,7 @@ extern "C" {
using std::size_t;
using std::string;
using std::forward;
using boost::hash_combine;
@ -92,17 +93,16 @@ namespace lib {
namespace { // quick-n-dirty symbol table implementation
/** @warning grows eternally, never shrinks */
std::unordered_set<string> symbolTable; ////////////////////////////////TICKET #158 replace by symbol table
std::unordered_set<string> symbolTable; ////////////////////////////////TICKET #158 replace by symbol table class
}
/** @internal quick-n-dirty hack, used as workaround for creating command-IDs on the fly */
Symbol
internedString (string&& symbolString)
{
auto res = symbolTable.insert (std::forward<string> (symbolString));
return Symbol (res.first->c_str());
}
/////////////////////////////////////(End)symbol-table hack
/** create Symbol by symbol table lookup.
* @note identical strings will be mapped to
* the same Literal (embedded pointer)
*/
Symbol::Symbol (string&& definition)
: Literal{symbolTable.insert(forward<string> (definition)).first->c_str()}
{ }

View file

@ -88,45 +88,36 @@ namespace lib {
/** Token or Atom with distinct identity
* @todo define a real Symbol class, i.e. same literal string==same pointer,
* @note same literal string==same pointer representation
*/
class Symbol
: public Literal
{
public:
Symbol (const char* lit =0)
: Literal(lit)
explicit
Symbol (std::string&& definition);
Symbol()
: Symbol{""}
{ }
Symbol (Symbol const& o)
: Literal(o)
Symbol (const char* lit)
: Symbol{std::string(lit)}
{ }
Symbol (Literal const& base, std::string ext)
: Literal(NULL)
{
UNIMPLEMENTED ("symbol table");
}
: Symbol{std::string(base)+"."+ext}
{ }
Symbol (Literal const& base, Literal ext)
: Literal(NULL)
{
UNIMPLEMENTED ("symbol table");
}
Symbol (Literal const& base, const char* ext)
: Symbol{base, std::string(ext)}
{ }
explicit
Symbol (std::string definition)
: Literal(NULL)
{
UNIMPLEMENTED ("symbol table");
}
Symbol (Symbol const&) = default;
Symbol (Symbol &&) = default;
Symbol&
operator= (Literal const& otherSym)
{
Literal::operator= (otherSym);
return *this;
}
Symbol& operator= (Symbol const&) = default;
Symbol& operator= (Symbol &&) = default;
};
@ -145,32 +136,98 @@ namespace lib {
inline bool
operator!= (Literal sy1, Literal sy2)
{
return ! (sy1 == sy2);
return not (sy1 == sy2);
}
/** @note two symbols are equal iff
* they use the same symbol table entry
*/
inline bool
operator== (Symbol sy1, Symbol sy2)
{
return sy1.c() == sy2.c();
}
inline bool
operator!= (Symbol sy1, Symbol sy2)
{
return not (sy1 == sy2);
}
/// mixed comparison based on string equality
inline bool
operator== (Symbol sy1, Literal sy2)
{
return Literal(sy1) == sy2;
}
inline bool
operator== (Literal sy1, Symbol sy2)
{
return sy1 == Literal(sy2);
}
inline bool
operator!= (Symbol sy1, Literal sy2)
{
return not (sy1 == sy2);
}
inline bool
operator!= (Literal sy1, Symbol sy2)
{
return not (sy1 == sy2);
}
/// comparison with c-strings //////TICKET #417
inline bool
operator== (Literal sy1, const char* const sy2)
operator== (Literal sy1, const char* sy2)
{
return (sy1 == Literal(sy2));
return (sy1 == Literal(sy2));
}
inline bool
operator== (const char* const sy1, Literal sy2)
operator== (const char* sy1, Literal sy2)
{
return (Literal(sy1) == sy2);
return (Literal(sy1) == sy2);
}
inline bool
operator!= (Literal sy1, const char* const sy2)
operator!= (Literal sy1, const char* sy2)
{
return ! (sy1 == Literal(sy2));
return ! (sy1 == Literal(sy2));
}
inline bool
operator!= (const char* const sy1, Literal sy2)
operator!= (const char* sy1, Literal sy2)
{
return ! (Literal(sy1) == sy2);
return ! (Literal(sy1) == sy2);
}
inline bool
operator== (Symbol sy1, const char* sy2)
{
return (Literal(sy1) == Literal(sy2));
}
inline bool
operator== (const char* sy1, Symbol sy2)
{
return (Literal(sy1) == Literal(sy2));
}
inline bool
operator!= (Symbol sy1, const char* sy2)
{
return ! (Literal(sy1) == Literal(sy2));
}
inline bool
operator!= (const char* sy1, Symbol sy2)
{
return ! (Literal(sy1) == Literal(sy2));
}
/// string concatenation
@ -188,18 +245,7 @@ namespace lib {
return symP + str;
}
/* ===== temporary symbol table workaround ===== */
/** place the string persistently in memory.
* @todo temporary workaround, shall be replaced by lib::Symbol implementation ///////////////TICKET #157 maintain symbol table for interned strings
* @return a C-String marked as lib::Symbol, pointing
* to the permanent location in heap memory.
* @warning eternally growing, please look away...
* @see symbol-impl.cpp implementation
*/
Symbol internedString (std::string&& idString);
} // namespace lib
#endif
#endif /*LIB_SYMBOL_H*/

View file

@ -165,7 +165,7 @@ namespace control {
Symbol
CommandInstanceManager::newInstance (Symbol prototypeID, string invocationID)
{
Symbol instanceID{lib::internedString (string{prototypeID}+"."+invocationID)};
Symbol instanceID{prototypeID, invocationID};
Command& instance = table_[instanceID];
if (instance)
throw new error::Logic (_Fmt{"Attempt to create a new Command instance '%s', "

View file

@ -121,7 +121,7 @@ namespace test{
fabricateNewInstance (lib::test::EventLog const& invocationLog)
{
log_ = invocationLog;
return proc::control::CommandDef(lib::internedString (uniqueTypeInstance()))
return proc::control::CommandDef{Symbol{uniqueTypeInstance()}}
.operation(PlaceholderCommand::operate)
.captureUndo(PlaceholderCommand::capture)
.undoOperation(PlaceholderCommand::undo);

View file

@ -111,18 +111,25 @@ namespace test{
Symbol sy2(l1);
CHECK (sy1 == sy2);
CHECK (!isSameObject (l1,sy1));
CHECK (!isSameObject (sy1,sy2));
CHECK (not isSameObject (l1,sy1));
CHECK (not isSameObject (sy1,sy2));
CHECK (l1.c() == sy1.c());
CHECK (sy1.c() == sy2.c());
Symbol sy3;
CHECK (isnil(sy3));
CHECK (sy1 != sy3);
sy3 = l1;
sy3 = Symbol{l1};
CHECK (!isnil(sy3));
CHECK (sy1 == sy3);
TODO ("real functionality of Symbol data type");
Symbol sy4{sy3, "11"};
CHECK (sy4 == "1.11");
CHECK (not isSameObject(sy4.c(), "1.11"));
CHECK (sy4.c() == Symbol{"1.11"}.c());
CHECK (sy4.c() == (const char*)sy4);
CHECK (hash_value(sy4) == hash_value(Symbol{"1.11"}));
}
};