diff --git a/include/xo/expression/Expression.hpp b/include/xo/expression/Expression.hpp index 3e9137c4..1b71ffcd 100644 --- a/include/xo/expression/Expression.hpp +++ b/include/xo/expression/Expression.hpp @@ -5,9 +5,7 @@ #pragma once -#include "xo/reflect/TypeDescr.hpp" -#include "xo/refcnt/Refcounted.hpp" -#include "exprtype.hpp" +#include "GeneralizedExpression.hpp" #include #include @@ -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 )>; @@ -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> 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*/ diff --git a/include/xo/expression/GeneralizedExpression.hpp b/include/xo/expression/GeneralizedExpression.hpp new file mode 100644 index 00000000..7866284e --- /dev/null +++ b/include/xo/expression/GeneralizedExpression.hpp @@ -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 + +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 **/ diff --git a/include/xo/expression/Lambda.hpp b/include/xo/expression/Lambda.hpp index e5d4a84e..be4d833d 100644 --- a/include/xo/expression/Lambda.hpp +++ b/include/xo/expression/Lambda.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> & argv, + const rp & 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 make(const std::string & name, + const std::vector> & argv, + const rp & body); + static rp 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 & local_env, + const rp & body); + + + }; } /*namespace ast*/ } /*namespace xo*/ diff --git a/include/xo/expression/Sequence.hpp b/include/xo/expression/Sequence.hpp new file mode 100644 index 00000000..af2fb0e3 --- /dev/null +++ b/include/xo/expression/Sequence.hpp @@ -0,0 +1,52 @@ +/** @file Sequence.hpp + * + * Author: Roland Conybeare + **/ + +#pragma once + +#include "Expression.hpp" +//#include + +namespace xo { + namespace ast { + class Sequence : public Expression { + public: + Sequence(const std::vector> & xv) + : Expression(exprtype::sequence, + xv[xv.size() - 1]->valuetype()), + expr_v_(xv) {} + + static rp make(const std::vector> & xv) { return new Sequence(xv); } + + std::size_t size() const { return expr_v_.size(); } + const rp & 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 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 xform_layer(TransformFn visitor_fn) override; + virtual void attach_envs(ref::brw parent) override; + + // ----- from GeneralizedExpression ---- + + virtual void display(std::ostream & os) const override; + + private: + /** sequence of expressions; evaluate in left-to-right order. + **/ + std::vector> expr_v_; + }; + } /*namespace ast*/ + +} /*namespace xo*/ + + +/** end Sequence.hpp **/ diff --git a/include/xo/expression/exprtype.hpp b/include/xo/expression/exprtype.hpp index 49745d52..ae764021 100644 --- a/include/xo/expression/exprtype.hpp +++ b/include/xo/expression/exprtype.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; } diff --git a/src/expression/CMakeLists.txt b/src/expression/CMakeLists.txt index 08c4302f..99a818db 100644 --- a/src/expression/CMakeLists.txt +++ b/src/expression/CMakeLists.txt @@ -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 diff --git a/src/expression/Expression.cpp b/src/expression/Expression.cpp index ecebe8b4..e9f02932 100644 --- a/src/expression/Expression.cpp +++ b/src/expression/Expression.cpp @@ -4,10 +4,6 @@ namespace xo { namespace ast { - std::string - Expression::display_string() const { - return tostr(*this); - } } /*namespace ast*/ } /*namespace xo*/ diff --git a/src/expression/GeneralizedExpression.cpp b/src/expression/GeneralizedExpression.cpp new file mode 100644 index 00000000..6239f700 --- /dev/null +++ b/src/expression/GeneralizedExpression.cpp @@ -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 */ diff --git a/src/expression/Lambda.cpp b/src/expression/Lambda.cpp index 039e1e1e..98f69e3a 100644 --- a/src/expression/Lambda.cpp +++ b/src/expression/Lambda.cpp @@ -5,19 +5,21 @@ #include "xo/reflect/function/FunctionTdx.hpp" #include "xo/indentlog/print/vector.hpp" #include +#include namespace xo { + using xo::reflect::TypeDescr; using xo::reflect::TypeDescrBase; using xo::reflect::FunctionTdxInfo; using std::stringstream; namespace ast { - rp - Lambda::make(const std::string & name, - const std::vector> & argv, - const rp & body) + TypeDescr + Lambda::assemble_lambda_td(const std::vector> & argv, + const rp & 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::make(const std::string & name, + const std::vector> & argv, + const rp & body) + { + using xo::reflect::FunctionTdx; + rp env = LocalEnv::make(argv); + TypeDescr lambda_td = assemble_lambda_td(argv, body); + rp 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 & local_env, const rp & 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::make(const std::string & name, + const std::vector> & argv, + const rp & body) + { + TypeDescr lambda_td = + + TypeDescr body_valuetype = nullptr; + + } + + rp + LambdaAccess::make_empty() + { + return new LambdaAccess("" /*name*/, + nullptr /*lambda_td*/, + nullptr /*local_env*/, + nullptr /*body*/); + } } /*namespace ast*/ } /*namespace xo*/ diff --git a/src/expression/Sequence.cpp b/src/expression/Sequence.cpp new file mode 100644 index 00000000..98269e2c --- /dev/null +++ b/src/expression/Sequence.cpp @@ -0,0 +1,78 @@ +/* @file Sequence.cpp */ + +#include "Sequence.hpp" +#include + +namespace xo { + namespace ast { + std::set + Sequence::get_free_variables() const { + std::set retval; + + for (const auto & x : expr_v_) { + std::set 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 + 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 p) { + for (const auto & x : expr_v_) + x->attach_envs(p); + } + + void + Sequence::display(std::ostream & os) const { + os << ""; + } + } /*namespace scm*/ +} /*namespace xo*/ + + +/* end Sequence.cpp */