diff --git a/include/xo/expression/ConvertExpr.hpp b/include/xo/expression/ConvertExpr.hpp new file mode 100644 index 00000000..8c5f9b70 --- /dev/null +++ b/include/xo/expression/ConvertExpr.hpp @@ -0,0 +1,109 @@ +/* file ConvertExpr.hpp + * + * author: Roland Conybeare, Aug 2024 + */ + +#pragma once + +#include "Expression.hpp" + +namespace xo { + namespace ast { + /** @class Convertexpr + * @brief Convenience for automatic type conversion + * + * This is equivalent to calling a built-in primitive + * that performs the conversion. + * + * We rely on this for convenience, for example to parse + * code like + * + * def foo : i16 = 0 + **/ + class ConvertExpr : public Expression { + public: + static rp make(TypeDescr dest_type, + rp arg); + + static ref::brw from(ref::brw x) { + return ref::brw::from(x); + } + + const rp & arg() const { return arg_; } + + // ----- Expression ----- + + virtual std::set get_free_variables() const override; + + virtual std::size_t visit_preorder(VisitFn visitor_fn) override { + std::size_t n = 1; + + visitor_fn(this); + + n += arg_->visit_preorder(visitor_fn); + + return n; + } + + virtual std::size_t visit_layer(VisitFn visitor_fn) override { + std::size_t n = 1; + + visitor_fn(this); + + n += this->arg_->visit_layer(visitor_fn); + + return n; + } + + virtual rp xform_layer(TransformFn xform_fn) override { + this->arg_ = this->arg_->xform_layer(xform_fn); + + return xform_fn(this); + } + + virtual void attach_envs(ref::brw p) override { + arg_->attach_envs(p); + } + + virtual void display(std::ostream & os) const override; + + protected: + ConvertExpr(TypeDescr dest_type, + rp arg) + : Expression(exprtype::convert, dest_type), + arg_{std::move(arg)} + {} + + protected: + /** source expression. Convert + * @c arg_->valuetype() to @c dest_type_ + **/ + rp arg_; + }; + + /** @class ConvertExprAccess + * @brief ConvertExpr with writeable members. + * + * Convenient when scaffolding a parser, + * e.g. see xo-parser + **/ + class ConvertExprAccess : public ConvertExpr { + public: + static rp make(TypeDescr dest_type, + rp arg); + static rp make_empty(); + + void assign_arg(rp arg) { this->arg_ = std::move(arg); } + + private: + ConvertExprAccess(TypeDescr dest_type, + rp arg) + : ConvertExpr(dest_type, + std::move(arg)) + {} + }; + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end ConvertExpr.hpp */ diff --git a/src/expression/CMakeLists.txt b/src/expression/CMakeLists.txt index 32520c85..eb0f6d64 100644 --- a/src/expression/CMakeLists.txt +++ b/src/expression/CMakeLists.txt @@ -9,6 +9,7 @@ set(SELF_SRCS Variable.cpp IfExpr.cpp LocalEnv.cpp + ConvertExpr.cpp ) xo_add_shared_library4(${SELF_LIB} ${PROJECT_NAME}Targets ${PROJECT_VERSION} 1 ${SELF_SRCS}) diff --git a/src/expression/ConvertExpr.cpp b/src/expression/ConvertExpr.cpp new file mode 100644 index 00000000..2e741f1b --- /dev/null +++ b/src/expression/ConvertExpr.cpp @@ -0,0 +1,53 @@ +/* file ConvertExpr.cpp + * + * author: Roland Conybeare + */ + +#include "ConvertExpr.hpp" + +namespace xo { + namespace ast { + rp + ConvertExpr::make(TypeDescr dest_type, + rp arg) + { + return new ConvertExpr(dest_type, + std::move(arg)); + } + + std::set + ConvertExpr::get_free_variables() const { + if (this->arg_) + return this->arg_->get_free_variables(); + else + return std::set(); + } + + void + ConvertExpr::display(std::ostream & os) const { + os << "valuetype()->short_name()) + << xtag("arg", arg_) + << ">"; + } + + // ----- ConvertExprAccess ----- + + rp + ConvertExprAccess::make(TypeDescr dest_type, + rp arg) + { + return new ConvertExprAccess(dest_type, + std::move(arg)); + } + + rp + ConvertExprAccess::make_empty() { + return new ConvertExprAccess(nullptr /*dest_type*/, + nullptr /*arg*/); + } + } /*namespace ast*/ +} /*namespace xo*/ + + +/* end ConvertExpr.cpp */