Advertisement
Guest User

Untitled

a guest
Apr 4th, 2020
437
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 35.60 KB | None | 0 0
  1. #include <iostream>
  2. //#define BOOST_SPIRIT_DEBUG
  3. //static inline std::ostream dbg_out {std::clog.rdbuf()};
  4. static inline std::ostream dbg_out{ nullptr };
  5.  
  6. // header ast.h
  7. #include <boost/multiprecision/cpp_dec_float.hpp>
  8. #include <boost/variant.hpp>
  9. #include <iomanip>
  10. #include <iostream>
  11. #include <string>
  12. #include <cassert>
  13.  
  14. namespace Ast {
  15.     using Identifier = std::string;
  16.     struct String : std::string {
  17.         String(std::string const& s) : std::string(s) {}
  18.         using std::string::string;
  19.         using std::string::operator=;
  20.  
  21.     private:
  22.         std::string const& str() const { return *this; }
  23.         std::string      & str() { return *this; }
  24.  
  25.         friend std::ostream& operator<<(std::ostream& os, String const& s) {
  26.             return os << std::quoted(s.str());
  27.         }
  28.     };
  29.  
  30.     enum class Boolean { False, True };
  31.     using Number = boost::multiprecision::cpp_dec_float_100;
  32.  
  33.     enum class Operator {
  34.         Plus, Minus, Mult, Div, Mod,
  35.         Less, LessEq, Greater, GreaterEq, Equal, NotEq,
  36.         NOT, AND, OR, XOR,
  37.     };
  38.     struct Member;
  39.     struct Unary;
  40.     struct Binary;
  41.     struct Ternary;
  42.     struct Call;
  43.     struct Subscript;
  44.  
  45.     using Expression = boost::make_recursive_variant<
  46.         Boolean,
  47.         Number,
  48.         String,
  49.         Identifier,
  50.         boost::recursive_wrapper<Member>,
  51.         boost::recursive_wrapper<Unary>,
  52.         boost::recursive_wrapper<Binary>,
  53.         boost::recursive_wrapper<Ternary>,
  54.         boost::recursive_wrapper<Call>,
  55.         boost::recursive_wrapper<Subscript>,
  56.         boost::recursive_variant_
  57.     >::type;
  58.  
  59.     using Expressions = std::vector<Expression>;
  60.  
  61.     struct Member { Expression obj, member; };
  62.     struct Unary { Operator op; Expression rhs; };
  63.     struct Binary { Expression lhs, rhs; Operator op; };
  64.     struct Ternary { Expression true_, cond, false_; };
  65.     struct Call { Expression fun; Expressions params; };
  66.     struct Subscript { Expression obj; Expressions indices; };
  67.  
  68.     struct Assignment { Expression lhs, value; };
  69. }
  70.  
  71. namespace Ast {
  72.     std::ostream& operator<<(std::ostream& os, Boolean const&b) {
  73.         switch (b) {
  74.         case Boolean::False: return os << "False";
  75.         case Boolean::True:  return os << "True";
  76.         }
  77.         return os << "?bool?";
  78.     }
  79.  
  80.     std::ostream& operator<<(std::ostream& os, Operator const&op) {
  81.         switch (op) {
  82.         case Operator::Plus:      return os << "+";
  83.         case Operator::Minus:     return os << "-";
  84.         case Operator::Mult:      return os << "*";
  85.         case Operator::Div:       return os << "/";
  86.         case Operator::Mod:       return os << "%";
  87.             //   logical
  88.         case Operator::AND:       return os << "and";
  89.         case Operator::NOT:       return os << "not";
  90.         case Operator::OR:        return os << "or";
  91.         case Operator::XOR:       return os << "xor";
  92.             //   relational
  93.         case Operator::Equal:     return os << "=";
  94.         case Operator::NotEq:     return os << "!=";
  95.         case Operator::Less:      return os << "<";
  96.         case Operator::LessEq:    return os << "<=";
  97.         case Operator::Greater:   return os << ">";
  98.         case Operator::GreaterEq: return os << ">=";
  99.         }
  100.         return os << "?op?";
  101.     }
  102.  
  103.     std::ostream& operator<<(std::ostream& os, Expressions const&ee) {
  104.         auto first = true;
  105.         for (auto& e : ee) {
  106.             if (!std::exchange(first, false))
  107.                 os << ", ";
  108.             os << e;
  109.         }
  110.         return os;
  111.     }
  112.  
  113.     std::ostream& operator<<(std::ostream&os, Member const&o) {
  114.         return os << o.obj << "." << o.member;
  115.     }
  116.     std::ostream& operator<<(std::ostream&os, Unary const&o) {
  117.         return os << o.op << " " << o.rhs;
  118.     }
  119.     std::ostream& operator<<(std::ostream&os, Binary const&o) {
  120.         return os << o.lhs << " " << o.op << " " << o.rhs;
  121.     }
  122.     std::ostream& operator<<(std::ostream&os, Ternary const&o) {
  123.         return os << o.true_ << " if " << o.cond << " else " << o.false_;
  124.     }
  125.     std::ostream& operator<<(std::ostream&os, Call const&o) {
  126.         return os << o.fun << "(" << o.params << ")";
  127.     }
  128.     std::ostream& operator<<(std::ostream&os, Subscript const&o) {
  129.         return os << o.obj << "[" << o.indices << "]";
  130.     }
  131.     std::ostream& operator<<(std::ostream&os, Assignment const&o) {
  132.         return os << o.lhs << ":=" << o.value;
  133.     }
  134. }
  135. // header parser.h
  136. //#define BOOST_SPIRIT_DEBUG
  137. //#include "ast.h"
  138. #include <boost/spirit/include/qi.hpp>
  139. #include <boost/core/ignore_unused.hpp>
  140. #include <boost/fusion/adapted.hpp>
  141. #include <boost/spirit/include/phoenix.hpp>
  142.  
  143. namespace qi = boost::spirit::qi;
  144. namespace px = boost::phoenix;
  145.  
  146. BOOST_FUSION_ADAPT_STRUCT(Ast::Assignment, lhs, value)
  147.  
  148. namespace Parser {
  149.     template <typename It>
  150.     struct Expression : qi::grammar<It, Ast::Expression()> {
  151.         Expression() : Expression::base_type(start) {
  152.             identifier_ = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z0-9_");
  153.             quoted_string = '"' >> *(R"("")" >> qi::attr('"') | ~qi::char_('"')) >> '"';
  154.  
  155.             using namespace boost::spirit::labels;
  156.  
  157.             term_ =
  158.                 factor_[_val = _1] >>
  159.                 *(
  160.                     (mult_div_mod_binary_op_ >> factor_)[_val = make_binary(_val, _2, _1)]
  161.                 )
  162.                 ;
  163.  
  164.             factor_
  165.                 = '(' >> expression_ >> ')'
  166.                 | quoted_string
  167.                 | unary_
  168.                 | qi::no_case[bool_]
  169.                 | identifier_
  170.                 | number_
  171.                 ;
  172.  
  173.             expression_
  174.                 = term_[_val = _1] >>
  175.                 *(
  176.                     (minus_plus_binary_op_ >> expression_)[_val = make_binary(_val, _2, _1)]
  177.                     | ('.' >> expression_)[_val = make_member(_val, _1)]
  178.                     | (qi::no_case[binary_op_] >> expression_)[_val = make_binary(_val, _2, _1)]
  179.                     | ("if" >> expression_ >> "else" >> expression_)[_val = make_ternary(_val, _1, _2)]
  180.                     | ('(' >> list_ >> ')')[_val = make_call(_val, _1)]
  181.                     | ('[' >> list_ >> ']')[_val = make_subscript(_val, _1)]
  182.                     );
  183.  
  184.             list_ = -(expression_ % ',');
  185.  
  186.             start = qi::skip(qi::blank)[expression_];
  187.  
  188.             unary_ = (qi::no_case[unary_op_] >> expression_)[_val = make_unary(_1, _2)];
  189.  
  190.             BOOST_SPIRIT_DEBUG_NODES(
  191.                 (start)(expression_)(factor_)
  192.                 (quoted_string)(identifier_)(unary_)
  193.             )
  194.         }
  195.  
  196.     private:
  197.         template <typename T> struct make_ {
  198.             struct arg_print {
  199.                 template <typename V>
  200.                 int operator()(V const& v) const { dbg_out << " (" << v << ")"; return 42; }
  201.             };
  202.  
  203.             template <typename... Args>
  204.             auto operator()(Args const&... args) const {
  205.                 dbg_out << "Make " << boost::core::demangle(typeid(T).name());
  206.                 int ignored[]{ arg_print{}(args)... };
  207.                 boost::ignore_unused(ignored);
  208.                 dbg_out << std::endl;
  209.                 return T{ args... };
  210.             }
  211.         };
  212.  
  213.         px::function<make_<Ast::Binary>    > make_binary{};
  214.         px::function<make_<Ast::Unary>     > make_unary{};
  215.         px::function<make_<Ast::Ternary>   > make_ternary{};
  216.         px::function<make_<Ast::Member>    > make_member{};
  217.         px::function<make_<Ast::Call>      > make_call{};
  218.         px::function<make_<Ast::Subscript> > make_subscript{};
  219.  
  220.         struct binary_op_sym : qi::symbols<char, Ast::Operator> {
  221.             binary_op_sym() {
  222.                 this->add
  223.                 //("-", Ast::Operator::Minus)
  224.                 //    ("+", Ast::Operator::Plus)
  225.                 //    ("*", Ast::Operator::Mult)
  226.                 //    ("/", Ast::Operator::Div)
  227.                 //    ("%", Ast::Operator::Mod)
  228.  
  229.                     //      logical
  230.                     ("and", Ast::Operator::AND)
  231.                     ("or", Ast::Operator::OR)
  232.                     ("xor", Ast::Operator::XOR) // aka '<>' or '!='
  233.  
  234.                     //      relational
  235.                     ("=", Ast::Operator::Equal)
  236.                     ("<>", Ast::Operator::NotEq)
  237.  
  238.                     ("<", Ast::Operator::Less)
  239.                     ("<=", Ast::Operator::LessEq)
  240.                     (">", Ast::Operator::Greater)
  241.                     (">=", Ast::Operator::GreaterEq)
  242.                     ;
  243.             }
  244.         } binary_op_;
  245.  
  246.         struct minus_plus_binary_op_sym : qi::symbols<char, Ast::Operator> {
  247.             minus_plus_binary_op_sym() {
  248.                 this->add
  249.                 ("-", Ast::Operator::Minus)
  250.                     ("+", Ast::Operator::Plus)
  251.                     ;
  252.             }
  253.         } minus_plus_binary_op_;
  254.  
  255.         struct mult_div_mod_binary_op_sym : qi::symbols<char, Ast::Operator> {
  256.             mult_div_mod_binary_op_sym() {
  257.                 this->add
  258.                     ("*", Ast::Operator::Mult)
  259.                     ("/", Ast::Operator::Div)
  260.                     ("%", Ast::Operator::Mod)
  261.                     ;
  262.             }
  263.         } mult_div_mod_binary_op_;
  264.  
  265.         struct bool_sym : qi::symbols<char, Ast::Boolean> {
  266.             bool_sym() {
  267.                 this->add
  268.                 ("false", Ast::Boolean::False)
  269.                     ("true", Ast::Boolean::True)
  270.                     ;
  271.             }
  272.         } bool_;
  273.         struct unary_op_sym : qi::symbols<char, Ast::Operator> {
  274.             unary_op_sym() {
  275.                 this->add
  276.                 ("-", Ast::Operator::Minus)
  277.                     ("+", Ast::Operator::Plus)
  278.                     ("not", Ast::Operator::NOT)
  279.                     ;
  280.             }
  281.         } unary_op_;
  282.  
  283.         qi::rule<It, Ast::Expression()> start;
  284.         qi::rule<It, Ast::Expression(), qi::blank_type> factor_, expression_;
  285.         qi::rule<It, Ast::Expression(), qi::blank_type> term_;
  286.         qi::rule<It, Ast::Expressions(), qi::blank_type> list_;
  287.         qi::rule<It, Ast::Unary(), qi::blank_type> unary_;
  288.  
  289.         // implicit lexemes
  290.         qi::real_parser<Ast::Number> number_;
  291.         qi::rule<It, Ast::Identifier()> identifier_;
  292.         qi::rule<It, Ast::String()> quoted_string;
  293.     };
  294.  
  295.     template <typename It>
  296.     struct Assignment : qi::grammar<It, Ast::Assignment()> {
  297.         Assignment() : Assignment::base_type(start) {
  298.             start = qi::skip(qi::blank)[expression_ >> ":=" >> expression_];
  299.             BOOST_SPIRIT_DEBUG_NODES((start))
  300.         }
  301.  
  302.     private:
  303.         Expression<It> expression_;
  304.         qi::rule<It, Ast::Assignment()> start;
  305.     };
  306. }
  307. // header null.h
  308. #include <iosfwd>
  309.  
  310. namespace Eval {
  311.     // We define an inert type Null
  312.     struct Null {
  313.         friend std::ostream& operator<<(std::ostream& os, Null) { return os << "null"; }
  314.     };
  315.  
  316.     template <typename T> Null operator+ (Null, T const&) { return {}; }
  317.     template <typename T> Null operator- (Null, T const&) { return {}; }
  318.     template <typename T> Null operator* (Null, T const&) { return {}; }
  319.     template <typename T> Null operator/ (Null, T const&) { return {}; }
  320.     template <typename T> Null operator% (Null, T const&) { return {}; }
  321.     template <typename T> Null operator&&(Null, T const&) { return {}; }
  322.     template <typename T> Null operator||(Null, T const&) { return {}; }
  323.     template <typename T> Null operator^ (Null, T const&) { return {}; }
  324.  
  325.     template <typename T> Null operator+ (T const&, Null) { return {}; }
  326.     template <typename T> Null operator- (T const&, Null) { return {}; }
  327.     template <typename T> Null operator* (T const&, Null) { return {}; }
  328.     template <typename T> Null operator/ (T const&, Null) { return {}; }
  329.     template <typename T> Null operator% (T const&, Null) { return {}; }
  330.     template <typename T> Null operator&&(T const&, Null) { return {}; }
  331.     template <typename T> Null operator||(T const&, Null) { return {}; }
  332.     template <typename T> Null operator^ (T const&, Null) { return {}; }
  333.  
  334.     template <typename T> Null operator< (Null, T const&) { return {}; }
  335.     template <typename T> Null operator<=(Null, T const&) { return {}; }
  336.     template <typename T> Null operator> (Null, T const&) { return {}; }
  337.     template <typename T> Null operator>=(Null, T const&) { return {}; }
  338.     template <typename T> Null operator==(Null, T const&) { return {}; }
  339.     template <typename T> Null operator!=(Null, T const&) { return {}; }
  340.  
  341.     template <typename T> Null operator< (T const&, Null) { return {}; }
  342.     template <typename T> Null operator<=(T const&, Null) { return {}; }
  343.     template <typename T> Null operator> (T const&, Null) { return {}; }
  344.     template <typename T> Null operator>=(T const&, Null) { return {}; }
  345.     template <typename T> Null operator==(T const&, Null) { return {}; }
  346.     template <typename T> Null operator!=(T const&, Null) { return {}; }
  347.     Null operator- (Null) { return {}; }
  348.     Null operator! (Null) { return {}; }
  349. }
  350. // header eval.h
  351. //#include "ast.h"
  352. //#include "null.h"
  353. #include <boost/variant.hpp>
  354. #include <vector>
  355. #include <map>
  356.  
  357. namespace Eval {
  358.     using boost::core::demangle;
  359.  
  360.     struct Value;
  361.     using Values = std::vector<Value>;
  362.     using Function = std::function<Value(Values const&)>;
  363.     using ValueV = boost::variant<
  364.         Null,
  365.         Ast::Number,
  366.         std::string,
  367.         Ast::Boolean,
  368.         Function
  369.     >;
  370.  
  371.     struct Value : ValueV {
  372.         using ValueV::ValueV;
  373.         using ValueV::operator=;
  374.     };
  375.  
  376.     static inline std::ostream& operator<<(std::ostream& os, Function const&) {
  377.         return os << "function(...){}";
  378.     }
  379.  
  380.     // Reflects a dynamic object instance in the Evaluation engine. Losely
  381.     // based on the idea of ExpandoObject in System.Dynamic from the CLR
  382.     struct Expando {
  383.         using Sub = boost::recursive_wrapper<Expando>;
  384.         using Key = std::string;
  385.  
  386.         using Array = std::vector<Sub>;
  387.         using Object = std::map<Key, Sub>;
  388.  
  389.         Expando() = default;
  390.         Expando(Value  v) : _value(std::move(v)) {}
  391.         Expando(Object v) : _object(std::move(v)) {}
  392.         Expando(Array  v) : _array(std::move(v)) {}
  393.  
  394.         Value  _value;
  395.         Object _object;
  396.         Array  _array;
  397.  
  398.         Expando& operator[](Values indices) {
  399.             if (indices.empty())
  400.                 return *this;
  401.  
  402.             auto f = indices.front();
  403.  
  404.             if (auto index = boost::get<Ast::Number>(&f)) {
  405.                 auto i = index->convert_to<std::size_t>();
  406.  
  407.                 if (i >= _array.size()) {
  408.                     _array.insert(_array.end(), 1 + i - _array.size(), Expando{});
  409.                 }
  410.                 indices.erase(indices.begin());
  411.                 return _array.at(i).get()[indices];
  412.             }
  413.             if (auto key = boost::get<std::string>(&f)) {
  414.                 auto it = _object.find(*key);
  415.  
  416.                 if (it == _object.end()) {
  417.                     auto insertion = _object.emplace(*key, Expando{});
  418.                     it = insertion.first;
  419.                 }
  420.                 indices.erase(indices.begin());
  421.                 return it->second.get()[indices];
  422.             }
  423.  
  424.             throw std::runtime_error("Type Mismatch: " + type_name(f));
  425.         }
  426.  
  427.         Expando& operator[](Value const& key) { return operator[](Values{ key }); }
  428.  
  429.     private:
  430.  
  431.         static std::string type_name(Value const& v) {
  432.             return demangle(v.type().name());
  433.         }
  434.         void dump(std::ostream& os, std::string indent = "\n") const {
  435.             os << _value << " ";
  436.  
  437.             if (!_object.empty()) {
  438.                 os << "{";
  439.                 for (auto&[k, v] : _object) {
  440.                     os << indent << std::quoted(k) << ": ";
  441.                     v.get().dump(os, indent + "  ");
  442.                 }
  443.                 if (_object.empty())
  444.                     os << " }";
  445.                 else
  446.                     os << indent << "}";
  447.             }
  448.  
  449.             if (!_array.empty()) {
  450.                 os << "[";
  451.                 size_t i = 0;
  452.                 for (auto& v : _array) {
  453.                     v.get().dump(os << indent << "#" << i++ << ": ", indent + " ");
  454.                 }
  455.                 if (i)
  456.                     os << indent << "]";
  457.                 else
  458.                     os << " ]";
  459.             }
  460.         }
  461.  
  462.         friend std::ostream& operator<<(std::ostream& os, Expando const& obj) {
  463.             obj.dump(os);
  464.             return os;
  465.         }
  466.     };
  467.  
  468.     // In our "typesystem" we will have Dynamic variables, where each variable
  469.     // can be either an LValue or RValue
  470.     struct WrapValue { Value _value; }; // to unconfuse boost::variant convert_construct
  471.     using RValue = Value;
  472.     using LValue = Expando & ;
  473.  
  474.     struct Dynamic : boost::variant<WrapValue, Expando*> {
  475.         using Variant = boost::variant<WrapValue, Expando*>;
  476.         Dynamic() = default;
  477.         Dynamic(Value const& v) : Variant(WrapValue{ v }) {}
  478.         Dynamic(LValue r) : Variant(&r) {}
  479.         using Variant::operator=;
  480.  
  481.         LValue lvalue() const {
  482.             if (auto* p = boost::strict_get<Expando*>(&base()))
  483.                 return **p;
  484.             throw std::runtime_error("LValue required (" + boost::lexical_cast<std::string>(*this) + ")");
  485.         }
  486.         Value value() const {
  487.             return which() == 0
  488.                 ? boost::strict_get<WrapValue>(base())._value
  489.                 : boost::strict_get<Expando*>(base())->_value;
  490.         }
  491.  
  492.         operator LValue() const { return lvalue(); }
  493.         operator Value() const { return value(); }
  494.  
  495.         friend inline bool is_rvalue(Dynamic const& v) { return 0 == v.which(); }
  496.         friend inline bool is_lvalue(Dynamic const& v) { return 1 == v.which(); }
  497.  
  498.     private:
  499.         Variant&       base() { return *this; }
  500.         Variant const& base() const { return *this; }
  501.  
  502.         friend std::ostream& operator<<(std::ostream& os, Dynamic const& obj) {
  503.             return is_lvalue(obj)
  504.                 ? os << obj.lvalue()
  505.                 : os << obj.value();
  506.         }
  507.     };
  508.  
  509.     namespace detail {
  510.         struct Truthyness {
  511.             template <typename... T>
  512.             bool operator()(boost::variant<T...> const& v) const { return boost::apply_visitor(*this, v); }
  513.             bool operator()(Dynamic const& o) const { return operator()(o.value()); }
  514.             bool operator()(Value const& o) const { return boost::apply_visitor(*this, o); }
  515.             bool operator()(Null) const { return false; }
  516.             bool operator()(Ast::Boolean const& o) const { return o == Ast::Boolean::True; }
  517.             bool operator()(Ast::Number const& o) const { return o != 0; }
  518.             bool operator()(Ast::String const& o) const { return !o.empty(); }
  519.             template <typename T>
  520.             bool operator()(T const& v) const {
  521.                 std::ostringstream oss;
  522.                 oss << "No conversion of " << v << " (" << demangle(typeid(T).name()) << " to boolean";
  523.                 throw std::runtime_error(oss.str());
  524.             }
  525.         };
  526.  
  527.         static inline const Truthyness truthy = {};
  528.  
  529.         struct OperationBase {
  530.             static Null boolcast(Null) {
  531.                 return {};
  532.             }
  533.             static Ast::Boolean boolcast(bool b) {
  534.                 return b ? Ast::Boolean::True : Ast::Boolean::False;
  535.             }
  536.         };
  537.  
  538.         template <typename Op>
  539.         struct Arithmetic : OperationBase {
  540.             using result_type = RValue;
  541.  
  542.             Ast::Number operator()(Ast::Number const& a) const { return Op{}(a); }
  543.  
  544.             template <typename T, typename U>
  545.             RValue operator()(T const& a, U const& b, decltype(Op{}(T{}, U{}))* = nullptr) const {
  546.                 return Op{}(a, b);
  547.             }
  548.  
  549.             template <typename... T>
  550.             RValue operator()(T const&...) const {
  551.                 //dbg_out << "L" << __LINE__ << ": " << __PRETTY_FUNCTION__ << "\n";
  552.                 throw std::runtime_error("Incompatible operands to " + demangle(typeid(Op).name()));
  553.             }
  554.         };
  555.  
  556.         template <typename Op>
  557.         struct Logical : OperationBase {
  558.             using result_type = RValue;
  559.  
  560.             template <typename T>
  561.             RValue operator()(T const& a) const { return boolcast(Op{}(truthy(a))); }
  562.             template <typename T, typename U>
  563.             RValue operator()(T const& a, U const& b) const { return boolcast(Op{}(truthy(a), truthy(b))); }
  564.         };
  565.  
  566.         template <typename Op>
  567.         struct Relational : OperationBase {
  568.             using result_type = RValue;
  569.  
  570.             template <typename T, typename U>
  571.             RValue operator()(T const& a, U const& b, decltype(Op{}(T{}, U{}))* = nullptr) const
  572.             {
  573.                 return boolcast(Op{}(a, b));
  574.             }
  575.  
  576.             template <typename... T>
  577.             RValue operator()(T const&...) const {
  578.                 //dbg_out << "L" << __LINE__ << ": " << __PRETTY_FUNCTION__ << "\n";
  579.                 throw std::runtime_error("Incompatible operands to " + demangle(typeid(Op).name()));
  580.             }
  581.         };
  582.  
  583.         struct Modulus : std::modulus<> {
  584.             auto operator()(Ast::Number const& a, Ast::Number const& b) const {
  585.                 return fmod(a, b);
  586.             }
  587.             using std::modulus<>::operator();
  588.         };
  589.     }
  590.  
  591.     struct Evaluator {
  592.         using result_type = Dynamic;
  593.  
  594.         LValue _root_context;
  595.  
  596.         Evaluator(LValue root) : _root_context(root) {}
  597.         Evaluator(Evaluator const&) = default;
  598.  
  599.         template <typename... T> Dynamic operator()(T&&...args) {
  600.             return call(_root_context, std::forward<T>(args)...);
  601.         }
  602.  
  603.     private:
  604.         template <typename... T> Dynamic call(LValue ctx, boost::variant<T...> const& v) {
  605.             Evaluator nest(ctx);
  606.             return boost::apply_visitor(nest, v);
  607.         }
  608.  
  609.         Dynamic call(LValue ctx, Ast::Assignment const& o) {
  610.             LValue dest = call(ctx, o.lhs);
  611.  
  612.             // protect against aliasing source/destination
  613.             RValue tmp = call(ctx, o.value);
  614.             dest = tmp;
  615.  
  616.             return dest;
  617.         }
  618.  
  619.         // Expression
  620.         RValue call(LValue, Ast::Boolean const& o) { return o; }
  621.         RValue call(LValue, Ast::Number const& o) { return o; }
  622.         RValue call(LValue, Ast::String const& o) { return o; }
  623.         LValue call(LValue ctx, Ast::Identifier const& o) { return ctx[o]; }
  624.  
  625.         Dynamic call(LValue ctx, Ast::Member const& o) {
  626.             LValue obj = call(ctx, o.obj);
  627.             return call(obj, o.member);
  628.         }
  629.  
  630.         RValue call(LValue ctx, Ast::Unary const& o) {
  631.             RValue const rhs = call(ctx, o.rhs);
  632.  
  633.             switch (o.op) {
  634.             case Ast::Operator::Plus:
  635.                 return rhs;
  636.             case Ast::Operator::Minus:
  637.                 return boost::apply_visitor(detail::Arithmetic<std::negate<>>{}, rhs);
  638.             case Ast::Operator::NOT:
  639.                 return boost::apply_visitor(detail::Logical<std::logical_not<>>{}, rhs);
  640.             default:
  641.                 throw std::runtime_error("Not implemented");
  642.             }
  643.         }
  644.  
  645.         RValue call(LValue ctx, Ast::Binary const& o) {
  646.             ValueV lhs = call(ctx, o.lhs);
  647.             ValueV rhs = call(ctx, o.rhs);
  648.  
  649.             auto arith = [&](auto op) {
  650.                 return boost::apply_visitor(detail::Arithmetic<decltype(op)>{}, lhs, rhs);
  651.             };
  652.             auto logical = [&](auto op) {
  653.                 return boost::apply_visitor(detail::Logical<decltype(op)>{}, lhs, rhs);
  654.             };
  655.             auto relational = [&](auto op) {
  656.                 return boost::apply_visitor(detail::Relational<decltype(op)>{}, lhs, rhs);
  657.             };
  658.  
  659.             switch (o.op) {
  660.             case Ast::Operator::Minus:     return arith(std::minus<>{});
  661.             case Ast::Operator::Plus:      return arith(std::plus<>{});
  662.             case Ast::Operator::Mult:      return arith(std::multiplies<>{});
  663.             case Ast::Operator::Div:       return arith(std::divides<>{});
  664.             case Ast::Operator::Mod:       return arith(detail::Modulus{});
  665.                 //   logical
  666.             case Ast::Operator::AND:       return logical(std::logical_and<>{});
  667.             case Ast::Operator::OR:        return logical(std::logical_or<>{});
  668.             case Ast::Operator::XOR:       return logical(std::not_equal_to<>{});
  669.                 //   relational
  670.             case Ast::Operator::Equal:     return relational(std::equal_to<>{});
  671.             case Ast::Operator::NotEq:     return relational(std::not_equal_to<>{});
  672.             case Ast::Operator::Less:      return relational(std::less<>{});
  673.             case Ast::Operator::LessEq:    return relational(std::less_equal<>{});
  674.             case Ast::Operator::Greater:   return relational(std::greater<>{});
  675.             case Ast::Operator::GreaterEq: return relational(std::greater_equal<>{});
  676.             default: throw std::runtime_error("Invalid operator");
  677.             }
  678.         }
  679.  
  680.         Dynamic call(LValue ctx, Ast::Ternary const& o) {
  681.             return detail::truthy(call(ctx, o.cond))
  682.                 ? call(ctx, o.true_)
  683.                 : call(ctx, o.false_);
  684.         }
  685.  
  686.         RValue call(LValue ctx, Ast::Call const& o) {
  687.             Values params;
  688.             for (auto& p : o.params) {
  689.                 params.push_back(call(ctx, p));
  690.             }
  691.             RValue fun = call(ctx, o.fun);
  692.             if (auto* f = boost::get<Function>(&fun)) {
  693.                 return (*f)(params);
  694.             }
  695.             throw std::runtime_error("Invalid callable");
  696.         }
  697.  
  698.         LValue call(LValue ctx, Ast::Subscript const& o) {
  699.             Values indices;
  700.             for (auto& p : o.indices) {
  701.                 indices.push_back(call(ctx, p));
  702.             }
  703.             LValue obj = call(ctx, o.obj);
  704.             return obj[indices];
  705.         }
  706.     };
  707. }
  708.  
  709. //#include "ast.h"
  710. //#include "parser.h"
  711. //#include "eval.h"
  712.  
  713. template <typename T, typename G>
  714. bool require_result(Eval::Expando context, G const& g, std::string const& str, const Eval::Value& compare_value_) {
  715.     auto iter = str.begin(), end = str.end();
  716.  
  717.     std::cout << std::quoted(str) << " ";
  718.     T parsed;
  719.     if (qi::parse(iter, end, g, parsed)) {
  720.         std::cout << "OK: " << parsed << "\n";
  721.  
  722.         try {
  723.             Eval::Value outcome = Eval::Evaluator{ context }(parsed);
  724.             std::cout << " -- outcome: " << outcome << "\n"; // , context: " << context << std::endl;
  725.             return true; // TODO: how to compare outcome and compare_value_?
  726.         }
  727.         catch (std::exception const& e) {
  728.             std::cout << " -- evaluation failed: " << e.what() << "\n";
  729.             return false;
  730.         }
  731.     }
  732.     else {
  733.         std::cout << "Failed\n";
  734.     }
  735.     if (iter != end) {
  736.         std::cout << "Remaining unparsed: " << std::quoted(std::string(iter, end)) << "\n";
  737.     }
  738.     return false;
  739. }
  740.  
  741. template <typename T, typename G>
  742. void run_tests(Eval::Expando context, G const& g, std::vector<std::string> const& inputs) {
  743.     for (std::string const str : inputs) {
  744.         auto iter = str.begin(), end = str.end();
  745.  
  746.         std::cout << std::quoted(str) << " ";
  747.         T parsed;
  748.         if (qi::parse(iter, end, g, parsed)) {
  749.             std::cout << "OK: " << parsed << "\n";
  750.  
  751.             try {
  752.                 Eval::Value outcome = Eval::Evaluator{ context }(parsed);
  753.                 std::cout << " -- outcome: " << outcome << "\n"; // , context: " << context << std::endl;
  754.             }
  755.             catch (std::exception const& e) {
  756.                 std::cout << " -- evaluation failed: " << e.what() << "\n";
  757.             }
  758.         }
  759.         else {
  760.             std::cout << "Failed\n";
  761.         }
  762.         if (iter != end) {
  763.             std::cout << "Remaining unparsed: " << std::quoted(std::string(iter, end)) << "\n";
  764.         }
  765.     }
  766. }
  767.  
  768. static inline Eval::Value demofunction(Eval::Values const& params) {
  769. #if 0  
  770.     std::ostringstream oss;
  771.     oss << "demofunction returned: c(";
  772.     bool first = true;
  773.     for (auto& param : params)
  774.         oss << (std::exchange(first, false) ? "" : ", ") << param;
  775.     oss << ")";
  776.     return oss.str();
  777. #else
  778.     return Ast::Number(23.45);
  779. #endif
  780. }
  781.  
  782. static inline auto make_context() {
  783.     using namespace Eval;
  784.     Expando ctx;
  785.     Value f = demofunction;
  786.     Value identity = [](Values v) { return v.front(); };
  787.     ctx["a"] = Value(43);
  788.     ctx["b"] = Value(1);
  789.     ctx["c"] = Value(7);
  790.     ctx["a"]["d"][2]["c"] = f;
  791.     ctx["a"]["d"][3]["c"] = f;
  792.     ctx["a"]["b"]["c"] = identity;
  793.  
  794.     return ctx;
  795. }
  796.  
  797. int main() {
  798.     std::cout << std::unitbuf
  799.         << "========== Context: " << make_context() << "\n"
  800.         << "==========\n";
  801.  
  802.     auto expressions = [](std::vector<std::string> const& cases) {
  803.         Parser::Expression<std::string::const_iterator> g;
  804.         run_tests<Ast::Expression>(make_context(), g, cases);
  805.     };
  806.  
  807.     auto assignments = [](std::vector<std::string> const& cases) {
  808.         Parser::Assignment<std::string::const_iterator> g;
  809.         run_tests<Ast::Assignment>(make_context(), g, cases);
  810.     };
  811.  
  812.     //expressions({
  813.     //    R"(a > 20)",
  814.     //    R"(a+10 > 30)",
  815.     //    R"(a = True)",
  816.     //    R"(a = b.a.c)",
  817.     //    R"(not a)",
  818.     //    R"(a and (b and c))",
  819.     //    R"(a*34+a.b.c(23))",
  820.     //    R"(10 if a > b else 30)", // python style unary
  821.     //    });
  822.  
  823.     //expressions({
  824.     //    R"("hello")",
  825.     //    R"(10)",
  826.     //    R"(a)",
  827.     //    R"(a.b)",
  828.     //    R"(a.b[2])",
  829.     //    R"(a.d)",
  830.     //    R"(a.d[2].c(a.e*3,20,"hello"))",
  831.     //    R"(a.d[3])",
  832.     //    R"(a.d[3].c(34))",
  833.     //    R"(a.d[3].c)",
  834.     //    R"(a.e)",
  835.     //    R"(b.c.d*20)",
  836.     //    R"(-20)"
  837.     //    });
  838.  
  839.     //// Mutability makes the universe wonky:
  840.     //assignments({
  841.     //    R"(a.b.c := 10)",
  842.     //    // Invoking a function doesn't yield an LValue
  843.     //    R"(a.d[3].c(34) := a.b[2])",
  844.     //    R"(a.d[2].c(a.e*3,20,"hello") := b.c.d*20)",
  845.     //    // NOTE: replaces a.d entirely!
  846.     //    R"(a := 10)",
  847.     //    // Now, this will not invoke a.d[2].c anymore:
  848.     //    R"(a.d[2].c(a.e*3,20,"hello") := b.c.d*20)",
  849.     //    R"(a.d := a.b)",
  850.     //    R"(a.d[3] := 10)",
  851.     //    R"(a.d[3] := a.b[2])",
  852.     //    R"(a.e := "hello")",
  853.     //    });
  854.  
  855.     //expressions({
  856.     //    R"(-a)",
  857.     //    R"(b)",
  858.     //    R"(a>-b)",
  859.     //    R"(a<-b)",
  860.     //    R"(a<a)",
  861.     //    R"(a<=a)",
  862.     //    R"(True = (a=a))",
  863.     //    R"(True = not (False))",
  864.     //    R"(True xor (a=a))",
  865.     //    R"(True or (a=a))",
  866.     //    R"(True and (a=a))",
  867.     //    R"(False xor (a=a))",
  868.     //    R"(False or (a=a))",
  869.     //    R"(False and (a=a))",
  870.     //    R"(2*8 + 7)",
  871.     //    R"(2*8 + False)",
  872.     //    R"(a.d[3].c(34))",
  873.     //    });
  874.  
  875.     //expressions({
  876.     //    R"(-a)",
  877.     //    R"(b)",
  878.     //    R"(a-b)",
  879.     //    R"(b-a)",
  880.     //    R"(b/a)",
  881.     //    R"(b*a)",
  882.     //    R"(b%3)",
  883.     //    R"(b/0)",
  884.     //    });
  885.  
  886.     ////bool x = true || true && false; // true ==> and then or, false ==> or then and
  887.     ////// in C/C++ true
  888.  
  889.     ////bool y1 = false == (1 > 20);
  890.     ////bool y2 = (false == 1) > 20;
  891.  
  892.     //#define RequiresTrue(EXPRESSION) assert( EXPRESSION );
  893.     //#define RequiresFalse(EXPRESSION) assert( !(EXPRESSION) );
  894.  
  895.     //RequiresFalse(false == 1 < 20); // '<' bindet staerker als '=='
  896.     //RequiresFalse(false == (1 < 20)); // beweis
  897.     //RequiresTrue((false == 1) < 20); // passt nicht
  898.  
  899.     //RequiresFalse(false && true == false); // '==' bindet staerker als '&&'
  900.     //RequiresFalse(false && (true == false)); // beweis
  901.     //RequiresTrue((false && true) == false); // passt nicht
  902.  
  903.     //assert( (0 == 1 && 0) == 0); // 0: '==' bindet staerker als '&&'
  904.     //assert( ((0 == 1) && 0) == 0);
  905.     //assert( (0 == (1 && 0)) == 1);
  906.  
  907.     //expressions({
  908.     //    R"(2*8 + 7)",
  909.     //    R"((1*2+3*4+5)*6)",
  910.     //    R"((1+2*3+4*5)+6)",
  911.     //    R"(1+2+3+4)",
  912.     //    R"(-20)",
  913.     //    R"(1+3*4)",
  914.     //    R"(1+4/2)",
  915.     //    R"(1+4%3)",
  916.     //    R"((1+3)*4)",
  917.     //    R"((1+4)/2)",
  918.     //    R"((1+4)%3)",
  919.     //    R"(True or True and False)",
  920.     //    R"(False = (1 < 20))", // should be False - OK
  921.     //    R"(False = 1 < 20)", // should be also False - OK
  922.     //    R"(False = (1 > 20))", // should be True - OK
  923.     //    R"(False = 1 > 20)", // should be also True - OK
  924.     //    R"(10 < 20 = 10 > 20)", // should be False - OK
  925.     //    R"((false and true) = (false and true))", // should be True - OK
  926.     //    R"(false and (true = false) and true)", // should be False - OK
  927.     //    R"(false and true = false and true)", // should be False - OK
  928.     //    R"(a.b.c(123))",
  929.     //    R"(a.d[3].c(321))",
  930.  
  931.     //    R"((8*2+7)=((8*2)+7))", // True: * stringer binding then +
  932.     //    R"((8*2-7)=((8*2)-7))", // True: * stringer binding then -
  933.     //    R"((8/2+7)=((8/2)+7))", // True: / stringer binding then +
  934.     //    R"((8/2-7)=((8/2)-7))", // True: / stringer binding then -
  935.     //    R"((8/2*7)=(8/2*7)", // True: * / equal binding
  936.     //    R"((8/2*7)=(7*8/2)", // True: * / equal binding
  937.     //    R"((8-2+7)=(8-2+7)", // True: * / equal binding
  938.     //    R"((8-2+7)=(7+8-2)", // True: * / equal binding
  939.     //    R"((False = 1 < 20)=(False = (1 < 20)))", // True: '<' stronger binding then '=='
  940.     //    R"((False = 1 > 20)=(False = (1 > 20)))", // True: '>' stronger binding then '=='
  941.     //    R"((False = 1 <= 20)=(False = (1 <= 20)))", // True: '<' stronger binding then '=='
  942.     //    R"((False = 1 => 20)=(False = (1 => 20)))", // True: '>' stronger binding then '=='
  943.     //    R"((False and True = False)=(False and (True = False)))", // True: '==' stronger binding then '&&'
  944.     //    R"((True or False and False)=(True or (False and False)))", // True: '&&' stronger binding then '||'
  945.     //    });
  946.  
  947.     //expressions({
  948.     //    R"((8*2+7)=((8*2)+7))", // True: * stronger binding then +
  949.     //    R"((8*2-7)=((8*2)-7))", // True: * stronger binding then -
  950.     //    R"((8/2+7)=((8/2)+7))", // True: / stronger binding then +
  951.     //    R"((8/2-7)=((8/2)-7))", // True: / stronger binding then -
  952.  
  953.     //    R"((8/2*7)=(8/2*7))", // True: * / equal binding, etc. test
  954.     //    R"((8/2*7)=(7*8/2))", // True: * / equal binding, etc. test
  955.  
  956.     //    R"((8-2+7)=(8-2+7))", // True: + - equal binding, etc. test
  957.     //    R"((8-2+7)=(7+8-2))", // True: + - equal binding, etc. test // FAILS
  958.  
  959.     //    R"(8-2+7)", // 13 // OK
  960.     //    R"(7+8-2)", // -1 // ??
  961.  
  962.     //    R"((False = 1 < 20)=(False = (1 < 20)))", // True: '<' stronger binding then '=='
  963.     //    R"((False = 1 > 20)=(False = (1 > 20)))", // True: '>' stronger binding then '=='
  964.  
  965.     //    R"((False = 1 <= 20)=(False = (1 <= 20)))", // True: '<' stronger binding then '=='
  966.     //    R"((False = 1 => 20)=(False = (1 => 20)))", // True: '>' stronger binding then '=='
  967.  
  968.     //    R"((False and True = False)=(False and (True = False)))", // True: '==' stronger binding then '&&'
  969.  
  970.     //    R"((True or False and False)=(True or (False and False)))", // True: '&&' stronger binding then '||'
  971.     //    });
  972.  
  973.     expressions({
  974.          R"(8-2*7)",
  975.          R"(7*8-2)",
  976.  
  977.          R"(7+8-2)",
  978.          R"(8-2+7)",
  979.         });
  980.  
  981.     Parser::Expression<std::string::const_iterator> g;
  982.     auto c = make_context();
  983.     assert(require_result<Ast::Expression>(c, g, "8-2*7", -6));
  984.     assert(require_result<Ast::Expression>(c, g, "8-2*7", 54));
  985.     assert(require_result<Ast::Expression>(c, g, "7+8-2", 13));
  986.     assert(require_result<Ast::Expression>(c, g, "8-2+7", 13)); // Fails -1
  987.  
  988. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement