lambda stuff [wip]
This commit is contained in:
parent
d4fd55b8ed
commit
5038045bdc
10 changed files with 309 additions and 41 deletions
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "exprtype.hpp"
|
||||
#include "GeneralizedExpression.hpp"
|
||||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
|
|
@ -33,7 +31,7 @@ namespace xo {
|
|||
*
|
||||
* Every expression evaluates to a value with a particular type
|
||||
**/
|
||||
class Expression : public ref::Refcount {
|
||||
class Expression : public GeneralizedExpression {
|
||||
public:
|
||||
using VisitFn = std::function
|
||||
<void (ref::brw<Expression>)>;
|
||||
|
|
@ -43,10 +41,7 @@ namespace xo {
|
|||
|
||||
public:
|
||||
explicit Expression(exprtype extype, TypeDescr valuetype)
|
||||
: extype_{extype}, valuetype_{valuetype}{}
|
||||
|
||||
exprtype extype() const { return extype_; }
|
||||
TypeDescr valuetype() const { return valuetype_; }
|
||||
: GeneralizedExpression(extype, valuetype) {}
|
||||
|
||||
/** find free named variables in this expression.
|
||||
* comprises the set of names that don't match formal parameters in
|
||||
|
|
@ -87,29 +82,8 @@ namespace xo {
|
|||
**/
|
||||
//virtual std::int32_t find_free_vars(std::vector<ref::brw<Lambda>> env) = 0;
|
||||
|
||||
/** write human-readable representation to stream **/
|
||||
virtual void display(std::ostream & os) const = 0;
|
||||
/** human-readable string representation **/
|
||||
virtual std::string display_string() const;
|
||||
|
||||
protected:
|
||||
/** useful when scaffolding expressions in a parser **/
|
||||
void assign_valuetype(TypeDescr x) { valuetype_ = x; }
|
||||
|
||||
private:
|
||||
/** expression type (constant | apply | ..) for this expression **/
|
||||
exprtype extype_ = exprtype::invalid;
|
||||
/** type information (when available) for values produced by this
|
||||
* expression.
|
||||
**/
|
||||
TypeDescr valuetype_ = nullptr;
|
||||
}; /*Expression*/
|
||||
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream & os, const Expression & x) {
|
||||
x.display(os);
|
||||
return os;
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
60
include/xo/expression/GeneralizedExpression.hpp
Normal file
60
include/xo/expression/GeneralizedExpression.hpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/** @file GeneralizedExpression.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "xo/reflect/TypeDescr.hpp"
|
||||
#include "exprtype.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
/** @class GeneralizedExpression
|
||||
* @brief abstract syntax tree (non-executable) for schematica
|
||||
*
|
||||
* 'Generalized' because it includes both kernel and macro expressions.
|
||||
* Every macro expression automatically translates to an equivalent kernel expression.
|
||||
* Kernel expressions are directly executable.
|
||||
**/
|
||||
class GeneralizedExpression : public ref::Refcount {
|
||||
public:
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
|
||||
public:
|
||||
GeneralizedExpression(exprtype extype, TypeDescr valuetype)
|
||||
: extype_{extype}, valuetype_{valuetype}{}
|
||||
|
||||
exprtype extype() const { return extype_; }
|
||||
TypeDescr valuetype() const { return valuetype_; }
|
||||
|
||||
/** write human-readable representation to stream **/
|
||||
virtual void display(std::ostream & os) const = 0;
|
||||
/** human-readable string representation **/
|
||||
virtual std::string display_string() const;
|
||||
|
||||
protected:
|
||||
/** useful when scaffolding expressions in a parser **/
|
||||
void assign_valuetype(TypeDescr x) { valuetype_ = x; }
|
||||
|
||||
private:
|
||||
/** expression type (constant | apply | ..) for this expression **/
|
||||
exprtype extype_ = exprtype::invalid;
|
||||
/** type information (when available) for values produced by this
|
||||
* expression.
|
||||
**/
|
||||
TypeDescr valuetype_ = nullptr;
|
||||
};
|
||||
|
||||
inline std::ostream &
|
||||
operator<<(std::ostream & os, const GeneralizedExpression & x) {
|
||||
x.display(os);
|
||||
return os;
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end GeneralizedExpression.hpp **/
|
||||
|
|
@ -86,6 +86,18 @@ namespace xo {
|
|||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
||||
protected:
|
||||
/** create type description for lambda with arguments @p argv
|
||||
* and body expression @p body
|
||||
**/
|
||||
static TypeDescr assemble_lambda_td(const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body);
|
||||
|
||||
/** create string description for function signature,
|
||||
* consistent with c++ expectation
|
||||
**/
|
||||
static std::string assemble_type_str(TypeDescr lambda_td);
|
||||
|
||||
private:
|
||||
/** @param lambda_type. function type for this lambda.
|
||||
* We arbitrarily choose the form "Retval(*)(Args...)"
|
||||
|
|
@ -157,6 +169,25 @@ namespace xo {
|
|||
{
|
||||
return Lambda::make(name, argv, body);
|
||||
}
|
||||
|
||||
class LambdaAccess : public Lambda {
|
||||
public:
|
||||
static rp<LambdaAccess> make(const std::string & name,
|
||||
const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body);
|
||||
static rp<LambdaAccess> make_empty();
|
||||
|
||||
private:
|
||||
/** lambda_type, body can be null here,
|
||||
* in which case fill in with assign methods
|
||||
**/
|
||||
LambdaAccess(const std::string & name,
|
||||
TypeDescr lambda_type,
|
||||
const rp<LocalEnv> & local_env,
|
||||
const rp<Expression> & body);
|
||||
|
||||
|
||||
};
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
52
include/xo/expression/Sequence.hpp
Normal file
52
include/xo/expression/Sequence.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/** @file Sequence.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Expression.hpp"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
class Sequence : public Expression {
|
||||
public:
|
||||
Sequence(const std::vector<rp<Expression>> & xv)
|
||||
: Expression(exprtype::sequence,
|
||||
xv[xv.size() - 1]->valuetype()),
|
||||
expr_v_(xv) {}
|
||||
|
||||
static rp<Sequence> make(const std::vector<rp<Expression>> & xv) { return new Sequence(xv); }
|
||||
|
||||
std::size_t size() const { return expr_v_.size(); }
|
||||
const rp<Expression> & operator[](std::size_t i) const { return expr_v_[i]; }
|
||||
|
||||
// ----- from Expression -----
|
||||
|
||||
/** note: broken if .expr_v_ contains any def-exprs
|
||||
* (will treat references to so-defined vars as free).
|
||||
* must rewrite these first
|
||||
**/
|
||||
virtual std::set<std::string> get_free_variables() const override;
|
||||
virtual std::size_t visit_preorder(VisitFn visitor_fn) override;
|
||||
/** note: borken if .expr_v_ contains any def-exprs **/
|
||||
virtual std::size_t visit_layer(VisitFn visitor_fn) override;
|
||||
virtual rp<Expression> xform_layer(TransformFn visitor_fn) override;
|
||||
virtual void attach_envs(ref::brw<Environment> parent) override;
|
||||
|
||||
// ----- from GeneralizedExpression ----
|
||||
|
||||
virtual void display(std::ostream & os) const override;
|
||||
|
||||
private:
|
||||
/** sequence of expressions; evaluate in left-to-right order.
|
||||
**/
|
||||
std::vector<rp<Expression>> expr_v_;
|
||||
};
|
||||
} /*namespace ast*/
|
||||
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end Sequence.hpp **/
|
||||
|
|
@ -32,6 +32,8 @@ namespace xo {
|
|||
variable,
|
||||
/** if-then-else **/
|
||||
ifexpr,
|
||||
/** sequence **/
|
||||
sequence,
|
||||
/** type conversion **/
|
||||
convert,
|
||||
|
||||
|
|
@ -51,6 +53,7 @@ namespace xo {
|
|||
case exprtype::lambda: return "lambda";
|
||||
case exprtype::variable: return "variable";
|
||||
case exprtype::ifexpr: return "if_expr";
|
||||
case exprtype::sequence: return "sequence";
|
||||
case exprtype::convert: return "convert";
|
||||
default: break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@
|
|||
|
||||
set(SELF_LIB xo_expression)
|
||||
set(SELF_SRCS
|
||||
GeneralizedExpression.cpp
|
||||
Expression.cpp
|
||||
DefineExpr.cpp
|
||||
Apply.cpp
|
||||
Lambda.cpp
|
||||
Variable.cpp
|
||||
IfExpr.cpp
|
||||
Sequence.cpp
|
||||
LocalEnv.cpp
|
||||
ConvertExpr.cpp
|
||||
Primitive.cpp
|
||||
|
|
|
|||
|
|
@ -4,10 +4,6 @@
|
|||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
std::string
|
||||
Expression::display_string() const {
|
||||
return tostr(*this);
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
14
src/expression/GeneralizedExpression.cpp
Normal file
14
src/expression/GeneralizedExpression.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* @file GeneralizedExpression.cpp */
|
||||
|
||||
#include "GeneralizedExpression.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
std::string
|
||||
GeneralizedExpression::display_string() const {
|
||||
return tostr(*this);
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end GeneralizedExpression.cpp */
|
||||
|
|
@ -5,19 +5,21 @@
|
|||
#include "xo/reflect/function/FunctionTdx.hpp"
|
||||
#include "xo/indentlog/print/vector.hpp"
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
namespace xo {
|
||||
using xo::reflect::TypeDescr;
|
||||
using xo::reflect::TypeDescrBase;
|
||||
using xo::reflect::FunctionTdxInfo;
|
||||
using std::stringstream;
|
||||
|
||||
namespace ast {
|
||||
rp<Lambda>
|
||||
Lambda::make(const std::string & name,
|
||||
const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body)
|
||||
TypeDescr
|
||||
Lambda::assemble_lambda_td(const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body)
|
||||
{
|
||||
using xo::reflect::FunctionTdx;
|
||||
if (!body)
|
||||
return nullptr;
|
||||
|
||||
/** assemble function type.
|
||||
*
|
||||
|
|
@ -41,8 +43,39 @@ namespace xo {
|
|||
TypeDescr lambda_td
|
||||
= TypeDescrBase::require_by_fn_info(function_info);
|
||||
|
||||
return lambda_td;
|
||||
}
|
||||
|
||||
std::string
|
||||
Lambda::assemble_type_str(TypeDescr lambda_td) {
|
||||
assert(lambda_td);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << lambda_td->fn_retval()->short_name()
|
||||
<< "(";
|
||||
|
||||
for (std::size_t i = 0, n = lambda_td->n_fn_arg(); i < n; ++i) {
|
||||
if (i > 0)
|
||||
ss << ",";
|
||||
ss << lambda_td->fn_arg(i)->short_name();
|
||||
}
|
||||
ss << ")";
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
rp<Lambda>
|
||||
Lambda::make(const std::string & name,
|
||||
const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body)
|
||||
{
|
||||
using xo::reflect::FunctionTdx;
|
||||
|
||||
rp<LocalEnv> env = LocalEnv::make(argv);
|
||||
|
||||
TypeDescr lambda_td = assemble_lambda_td(argv, body);
|
||||
|
||||
rp<Lambda> retval
|
||||
= new Lambda(name,
|
||||
lambda_td,
|
||||
|
|
@ -122,14 +155,15 @@ namespace xo {
|
|||
} /*regularize_layer_vars*/
|
||||
|
||||
Lambda::Lambda(const std::string & name,
|
||||
TypeDescr lambda_type,
|
||||
TypeDescr lambda_td,
|
||||
const rp<LocalEnv> & local_env,
|
||||
const rp<Expression> & body)
|
||||
: FunctionInterface(exprtype::lambda, lambda_type),
|
||||
: FunctionInterface(exprtype::lambda, lambda_td),
|
||||
name_{name},
|
||||
body_{body},
|
||||
local_env_{local_env}
|
||||
{
|
||||
#ifdef OBSOLETE
|
||||
stringstream ss;
|
||||
ss << "double";
|
||||
ss << "(";
|
||||
|
|
@ -139,8 +173,10 @@ namespace xo {
|
|||
ss << "double";
|
||||
}
|
||||
ss << ")";
|
||||
#endif
|
||||
|
||||
this->type_str_ = ss.str();
|
||||
if (lambda_td)
|
||||
this->type_str_ = assemble_type_str(lambda_td);
|
||||
|
||||
/* ensure variables are unique within layer for this lambda */
|
||||
this->layer_var_map_ = this->regularize_layer_vars();
|
||||
|
|
@ -209,6 +245,28 @@ namespace xo {
|
|||
<< xtag("body", body_)
|
||||
<< ">";
|
||||
} /*display*/
|
||||
|
||||
// ----- Lambda Access -----
|
||||
|
||||
rp<LambdaAccess>
|
||||
LambdaAccess::make(const std::string & name,
|
||||
const std::vector<rp<Variable>> & argv,
|
||||
const rp<Expression> & body)
|
||||
{
|
||||
TypeDescr lambda_td =
|
||||
|
||||
TypeDescr body_valuetype = nullptr;
|
||||
|
||||
}
|
||||
|
||||
rp<LambdaAccess>
|
||||
LambdaAccess::make_empty()
|
||||
{
|
||||
return new LambdaAccess("" /*name*/,
|
||||
nullptr /*lambda_td*/,
|
||||
nullptr /*local_env*/,
|
||||
nullptr /*body*/);
|
||||
}
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
|
|
|||
78
src/expression/Sequence.cpp
Normal file
78
src/expression/Sequence.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/* @file Sequence.cpp */
|
||||
|
||||
#include "Sequence.hpp"
|
||||
#include <cstddef>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
std::set<std::string>
|
||||
Sequence::get_free_variables() const {
|
||||
std::set<std::string> retval;
|
||||
|
||||
for (const auto & x : expr_v_) {
|
||||
std::set<std::string> free_vars;
|
||||
free_vars = x->get_free_variables();
|
||||
|
||||
for (const auto & y : free_vars)
|
||||
retval.insert(y);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Sequence::visit_preorder(VisitFn visitor_fn) {
|
||||
std::size_t n = 1;
|
||||
|
||||
visitor_fn(this);
|
||||
|
||||
for (const auto & x : expr_v_)
|
||||
n += x->visit_preorder(visitor_fn);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Sequence::visit_layer(VisitFn visitor_fn) {
|
||||
std::size_t n = 1;
|
||||
|
||||
visitor_fn(this);
|
||||
|
||||
for (const auto & x : expr_v_)
|
||||
n += x->visit_layer(visitor_fn);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
rp<Expression>
|
||||
Sequence::xform_layer(TransformFn xform_fn) {
|
||||
for (std::size_t i = 0, n = expr_v_.size(); i < n; ++i) {
|
||||
expr_v_[i] = expr_v_[i]->xform_layer(xform_fn);
|
||||
}
|
||||
|
||||
return xform_fn(this);
|
||||
}
|
||||
|
||||
void
|
||||
Sequence::attach_envs(ref::brw<Environment> p) {
|
||||
for (const auto & x : expr_v_)
|
||||
x->attach_envs(p);
|
||||
}
|
||||
|
||||
void
|
||||
Sequence::display(std::ostream & os) const {
|
||||
os << "<Sequence";
|
||||
std::size_t i = 0;
|
||||
for (const auto & x : expr_v_) {
|
||||
std::string i_str = tostr("[", i, "]");
|
||||
|
||||
os << xtag(i_str.c_str(), x);
|
||||
}
|
||||
|
||||
os << ">";
|
||||
}
|
||||
} /*namespace scm*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end Sequence.cpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue