137 lines
4.2 KiB
C++
137 lines
4.2 KiB
C++
/** @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 ref::rp<Apply> make(const ref::rp<Expression> & fn,
|
|
const std::vector<ref::rp<Expression>> & argv);
|
|
|
|
/** downcast from Expression **/
|
|
static ref::brw<Apply> from(ref::brw<Expression> x) {
|
|
return ref::brw<Apply>::from(x);
|
|
}
|
|
|
|
const ref::rp<Expression> & fn() const { return fn_; }
|
|
const std::vector<ref::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 ref::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 ref::rp<Expression> & fn,
|
|
const std::vector<ref::rp<Expression>> & argv)
|
|
: Expression(exprtype::apply, apply_valuetype),
|
|
fn_{fn}, argv_(argv)
|
|
{}
|
|
|
|
private:
|
|
/** function to invoke **/
|
|
ref::rp<Expression> fn_;
|
|
/** argument expressions, in l-to-r order **/
|
|
std::vector<ref::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 ref::rp<Apply>
|
|
make_apply(const ref::rp<Expression> & fn,
|
|
const std::initializer_list<ref::rp<Expression>> args) {
|
|
std::vector<ref::rp<Expression>> argv(args);
|
|
return Apply::make(fn, argv);
|
|
} /*make_apply*/
|
|
|
|
} /*namespace ast*/
|
|
} /*namespace xo*/
|
|
|
|
|
|
/** end Apply.hpp **/
|