Add 'xo-expression/' from commit '5ac3c03a0c'
git-subtree-dir: xo-expression git-subtree-mainline:d0f5ccc1cegit-subtree-split:5ac3c03a0c
This commit is contained in:
commit
aecabbb144
46 changed files with 3241 additions and 0 deletions
163
xo-expression/include/xo/expression/Apply.hpp
Normal file
163
xo-expression/include/xo/expression/Apply.hpp
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/** @file Apply.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Expression.hpp"
|
||||
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
|
||||
/** @class Apply
|
||||
* @brief syntax for a function call.
|
||||
*
|
||||
* In general we don't know function to be invoked
|
||||
* until runtime, depending on the nature of Expression.
|
||||
**/
|
||||
class Apply : public Expression {
|
||||
public:
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
|
||||
public:
|
||||
/** create new apply-expression instance
|
||||
**/
|
||||
static rp<Apply> make(const rp<Expression> & fn,
|
||||
const std::vector<rp<Expression>> & argv);
|
||||
|
||||
/** create apply-expression to add two 64-bit floating-point numbers **/
|
||||
static rp<Apply> make_add2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs);
|
||||
/** create apply-expression to subtract two 64-bit floating-point numbers **/
|
||||
static rp<Apply> make_sub2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs);
|
||||
/** create apply-expression to multiply two 64-bit floating-point numbers **/
|
||||
static rp<Apply> make_mul2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs);
|
||||
/** create apply-expression to divide two 64-bit floating-point numbers **/
|
||||
static rp<Apply> make_div2_f64(const rp<Expression> & lhs,
|
||||
const rp<Expression> & rhs);
|
||||
|
||||
/** downcast from Expression **/
|
||||
static ref::brw<Apply> from(ref::brw<Expression> x) {
|
||||
return ref::brw<Apply>::from(x);
|
||||
}
|
||||
|
||||
const rp<Expression> & fn() const { return fn_; }
|
||||
const std::vector<rp<Expression>> & argv() const { return argv_; }
|
||||
|
||||
virtual std::set<std::string> get_free_variables() const override {
|
||||
std::set<std::string> retval = fn_->get_free_variables();
|
||||
|
||||
for (const auto & arg : argv_) {
|
||||
std::set<std::string> arg_free_set
|
||||
= arg->get_free_variables();
|
||||
|
||||
for (const auto & name : arg_free_set)
|
||||
retval.insert(name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual std::size_t visit_preorder(VisitFn visitor_fn) override {
|
||||
std::size_t n = 1;
|
||||
|
||||
visitor_fn(this);
|
||||
|
||||
n += fn_->visit_preorder(visitor_fn);
|
||||
|
||||
for (const auto & arg : argv_)
|
||||
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 += fn_->visit_layer(visitor_fn);
|
||||
|
||||
for (const auto & arg : argv_)
|
||||
n += arg->visit_layer(visitor_fn);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
virtual rp<Expression> xform_layer(TransformFn xform_fn) override {
|
||||
this->fn_ = fn_->xform_layer(xform_fn);
|
||||
|
||||
for (auto & arg : argv_)
|
||||
arg = arg->xform_layer(xform_fn);
|
||||
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
virtual void attach_envs(ref::brw<Environment> p) override {
|
||||
fn_->attach_envs(p);
|
||||
|
||||
for (const auto & arg : argv_)
|
||||
arg->attach_envs(p);
|
||||
}
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
||||
private:
|
||||
Apply(TypeDescr apply_valuetype,
|
||||
const rp<Expression> & fn,
|
||||
const std::vector<rp<Expression>> & argv)
|
||||
: Expression(exprtype::apply, apply_valuetype),
|
||||
fn_{fn}, argv_(argv)
|
||||
{}
|
||||
|
||||
private:
|
||||
/** function to invoke **/
|
||||
rp<Expression> fn_;
|
||||
/** argument expressions, in l-to-r order **/
|
||||
std::vector<rp<Expression>> argv_;
|
||||
}; /*Apply*/
|
||||
|
||||
#ifdef NOT_USING
|
||||
namespace detail {
|
||||
/** Use:
|
||||
** std::vector<ref::rp<Expression>>
|
||||
**/
|
||||
|
||||
template <typename... Args>
|
||||
struct apply_push_args;
|
||||
|
||||
template <>
|
||||
struct apply_push_args<> {
|
||||
static void push_all(std::vector<ref::rp<Expression>> * /*p_argv*/) {}
|
||||
};
|
||||
|
||||
template <typename Arg1, typename... Rest>
|
||||
struct apply_push_args<Arg1, Rest...> {
|
||||
static void push_all(std::vector<ref::rp<Expression>> * p_argv,
|
||||
const ref::rp<Expression> & x, Rest... rest)
|
||||
{
|
||||
p_argv->push_back(x);
|
||||
apply_push_args<Rest...>::push_all(p_argv, rest...);
|
||||
};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reminder: initializer-lists are compile-time only */
|
||||
inline rp<Apply>
|
||||
make_apply(const rp<Expression> & fn,
|
||||
const std::initializer_list<rp<Expression>> args) {
|
||||
std::vector<rp<Expression>> argv(args);
|
||||
return Apply::make(fn, argv);
|
||||
} /*make_apply*/
|
||||
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end Apply.hpp **/
|
||||
Loading…
Add table
Add a link
Reference in a new issue