diff --git a/include/hobbes/lang/expr.H b/include/hobbes/lang/expr.H index 8303f19c..bb96c989 100644 --- a/include/hobbes/lang/expr.H +++ b/include/hobbes/lang/expr.H @@ -19,6 +19,7 @@ public: virtual ~Expr(); virtual void show(std::ostream&) const = 0; + [[nodiscard]] std::string toString() const; virtual void showAnnotated(std::ostream&) const = 0; virtual Expr* clone() const = 0; virtual bool operator==(const Expr&) const = 0; diff --git a/include/hobbes/lang/module.H b/include/hobbes/lang/module.H index 637f98be..6f984237 100644 --- a/include/hobbes/lang/module.H +++ b/include/hobbes/lang/module.H @@ -17,6 +17,7 @@ namespace hobbes { struct ModuleDef : public LexicallyAnnotated { virtual ~ModuleDef(); virtual void show(std::ostream&) const = 0; + [[nodiscard]] std::string toString() const; // improves performance of case-analysis over instances (to avoid 'dynamic_cast') public: @@ -243,6 +244,7 @@ public: const ModuleDefs& definitions() const; void show(std::ostream& out) const; + [[nodiscard]] std::string toString() const; // allow language options set within modules void setOption(const std::string&, const LexicalAnnotation&); diff --git a/include/hobbes/lang/preds/class.H b/include/hobbes/lang/preds/class.H index 04ac66f0..8c51c3c1 100644 --- a/include/hobbes/lang/preds/class.H +++ b/include/hobbes/lang/preds/class.H @@ -68,6 +68,7 @@ public: // show this class definition void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; public: const TCInstances& instances() const; bool hasGroundInstanceAt(const MonoTypes&) const; @@ -122,6 +123,7 @@ public: // show this instance definition void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; private: std::string tcname; MonoTypes itys; @@ -152,6 +154,7 @@ public: // show this instance-generator definition void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; // produce a sequence of type variables and constraints unique to this invocation using IFnDef = std::pair; diff --git a/include/hobbes/lang/type.H b/include/hobbes/lang/type.H index 0db74564..42e571c9 100644 --- a/include/hobbes/lang/type.H +++ b/include/hobbes/lang/type.H @@ -41,6 +41,7 @@ public: using ptr = std::shared_ptr; virtual void show(std::ostream&) const = 0; + [[nodiscard]] std::string toString() const; bool operator==(const MonoType& rhs) const; // improves performance of case-analysis over instances (to avoid 'dynamic_cast') @@ -109,6 +110,8 @@ public: // get access to the parent and root type environment from here const TEnvPtr& parentTypeEnv() const; TEnv* root(); + + [[nodiscard]] std::string toString() const; public: // get access to the internal type environment map (should only be used for debugging) using PolyTypeEnv = std::map; @@ -179,6 +182,7 @@ public: QualTypePtr instantiate() const; void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; bool operator==(const PolyType& rhs) const; // this should only be used if you don't mind capturing bound type variables @@ -206,6 +210,7 @@ public: void monoType(const MonoTypePtr&); void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; bool operator==(const QualType& rhs) const; private: Constraints cs; @@ -238,6 +243,7 @@ public: // compare/show void show(std::ostream&) const; + [[nodiscard]] std::string toString() const; bool operator==(const Constraint& rhs) const; // are there free variables referenced in this constraint? diff --git a/lib/hobbes/lang/expr.C b/lib/hobbes/lang/expr.C index db3081eb..60156446 100644 --- a/lib/hobbes/lang/expr.C +++ b/lib/hobbes/lang/expr.C @@ -40,6 +40,11 @@ Expr::~Expr() = default; const QualTypePtr& Expr::type() const { return this->annotatedType; } void Expr::type(const QualTypePtr& ty) { this->annotatedType = ty; } int Expr::case_id() const { return this->cid; } +std::string Expr::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} Primitive::Primitive(int cid, const LexicalAnnotation& la) : Expr(cid, la) { } bool PrimPtrLT::operator()(const PrimitivePtr& p0, const PrimitivePtr& p1) const { return *p0 < *p1; } diff --git a/lib/hobbes/lang/module.C b/lib/hobbes/lang/module.C index 8dd9f3a3..1d86cc2a 100644 --- a/lib/hobbes/lang/module.C +++ b/lib/hobbes/lang/module.C @@ -19,6 +19,11 @@ void Module::show(std::ostream& out) const { out << std::endl; } } +std::string Module::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} bool isValidOption(const std::string& o) { return o == "Safe" || o == "SafeArrays" || o == "IgnoreUnreachableMatches"; @@ -39,6 +44,11 @@ const std::vector& Module::options() const { /* module defs */ ModuleDef::ModuleDef(int cid, const LexicalAnnotation& la) : LexicallyAnnotated(la), cid(cid) { } int ModuleDef::case_id() const { return this->cid; } +std::string ModuleDef::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} ModuleDef::~ModuleDef() = default; // module imports diff --git a/lib/hobbes/lang/preds/class.C b/lib/hobbes/lang/preds/class.C index 30432782..ee761bd0 100644 --- a/lib/hobbes/lang/preds/class.C +++ b/lib/hobbes/lang/preds/class.C @@ -430,6 +430,11 @@ void TClass::show(std::ostream& out) const { out << " " << tcmember.first << " :: " << hobbes::show(tcmember.second) << "\n"; } } +std::string TClass::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} const TCInstances& TClass::instances() const { return this->tcinstances; @@ -519,6 +524,11 @@ void TCInstance::show(std::ostream& out) const { out << " " << mm.first << " = " << hobbes::show(mm.second) << "\n"; } } +std::string TCInstance::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} //////// // generate class instances from class instance functions @@ -757,6 +767,11 @@ void TCInstanceFn::show(std::ostream& out) const { out << " " << mm.first << " = " << hobbes::show(substitute(simpl, mm.second)) << "\n"; } } +std::string TCInstanceFn::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} // generate a fresh type class and instance generator to control poly/qualtype instantiation in an expression void definePrivateClass(const TEnvPtr& tenv, const std::string& memberName, const ExprPtr& expr) { diff --git a/lib/hobbes/lang/type.C b/lib/hobbes/lang/type.C index 6d1c75da..3a0d0ef2 100644 --- a/lib/hobbes/lang/type.C +++ b/lib/hobbes/lang/type.C @@ -103,6 +103,14 @@ bool TEnv::hasImmediateBinding(const std::string& vname) const { return (this->ptenv.find(vname) != this->ptenv.end()) || (this->unquals && this->unquals->lookup(vname) != PolyTypePtr()); } +std::string TEnv::toString() const { + std::ostringstream out; + for (const auto& pe: ptenv) { + out << " " << pe.first << ": " << pe.second->toString() << '\n'; + } + return std::move(out).str(); +} + void TEnv::bind(const std::string& vname, const PolyTypePtr& pt) { if (hasImmediateBinding(vname)) { throw std::runtime_error("Variable already defined: " + vname); @@ -365,6 +373,12 @@ void PolyType::show(std::ostream& out) const { simplifyVarNames(instantiate())->show(out); } +std::string PolyType::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} + bool PolyType::operator==(const PolyType& rhs) const { return this->vs == rhs.vs && *this->qt == *rhs.qt; } @@ -406,7 +420,14 @@ void QualType::show(std::ostream& out) const { } } +std::string QualType::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} + bool QualType::operator==(const QualType& rhs) const { + return this->cs == rhs.cs && *this->mt == *rhs.mt; } @@ -474,6 +495,12 @@ void Constraint::show(std::ostream& out) const { } } +std::string Constraint::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} + bool Constraint::operator==(const Constraint& rhs) const { if (this->cat != rhs.cat || this->mts.size() != rhs.mts.size()) { return false; @@ -492,6 +519,11 @@ bool Constraint::operator==(const Constraint& rhs) const { //////// MonoType::MonoType(int cid) : cid(cid), tgenCount(0), memorySize(-1) { } int MonoType::case_id() const { return this->cid; } +std::string MonoType::toString() const { + std::ostringstream out; + this->show(out); + return std::move(out).str(); +} MonoType::~MonoType() = default; bool MonoType::operator==(const MonoType& rhs) const {