diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index df0a13683..401c977d9 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -215,57 +215,6 @@ const std::map eth::c_instructionInfo = { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } }; -void killBigints(sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; - case sp::utree_type::any_type: delete _this.get(); break; - default:; - } -} - -void debugOut(ostream& _out, sp::utree const& _this) -{ - switch (_this.which()) - { - case sp::utree_type::list_type: _out << "( "; for (auto const& i: _this) { debugOut(_out, i); _out << " "; } _out << ")"; break; - case sp::utree_type::int_type: _out << _this.get(); break; - case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; - case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; - case sp::utree_type::any_type: _out << *_this.get(); break; - default: _out << "nil"; - } -} - -void parseLLL(string const& _s, sp::utree& o_out) -{ - using qi::ascii::space; - typedef sp::basic_string symbol_type; - typedef string::const_iterator it; - - qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; - qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;())") + '\0'))]; - qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" ();\"\x01-\x1f\x7f") + '\0'))]; - qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; - qi::rule integer = intstr; - qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; - qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; - qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; - qi::rule list; - qi::rule element = atom | list; - list = '(' > *element > ')'; - - try - { - qi::phrase_parse(_s.begin(), _s.end(), element, space, o_out); - } - catch (std::exception& _e) - { - cnote << _e.what(); - } -} - static string readQuoted(char const*& o_d, char const* _e) { string ret; @@ -1132,6 +1081,50 @@ bytes eth::compileLisp(std::string const& _code, bool _quiet, bytes& _init) return body; } +void killBigints(sp::utree const& _this) +{ + switch (_this.which()) + { + case sp::utree_type::list_type: for (auto const& i: _this) killBigints(i); break; + case sp::utree_type::any_type: delete _this.get(); break; + default:; + } +} + +void parseLLL(string const& _s, sp::utree& o_out) +{ + using qi::ascii::space; + typedef sp::basic_string symbol_type; + typedef string::const_iterator it; + + qi::rule element; + qi::rule str = '"' > qi::lexeme[+(~qi::char_(std::string("\"") + '\0'))] > '"'; + qi::rule strsh = '\'' > qi::lexeme[+(~qi::char_(std::string(" ;())") + '\0'))]; + qi::rule symbol = qi::lexeme[+(~qi::char_(std::string(" @[]{}:();\"\x01-\x1f\x7f") + '\0'))]; + qi::rule intstr = qi::lexeme[ qi::no_case["0x"][qi::_val = "0x"] >> *qi::char_("0-9a-fA-F")[qi::_val += qi::_1]] | qi::lexeme[+qi::char_("0-9")[qi::_val += qi::_1]]; + qi::rule integer = intstr; + qi::rule multiplier = qi::lit("wei")[qi::_val = 1] | qi::lit("szabo")[qi::_val = szabo] | qi::lit("finney")[qi::_val = finney] | qi::lit("ether")[qi::_val = ether]; + qi::rule quantity = integer[qi::_val = qi::_1] >> -multiplier[qi::_val *= qi::_1]; + qi::rule atom = quantity[qi::_val = px::construct(px::new_(qi::_1))] | (str | strsh)[qi::_val = qi::_1] | symbol[qi::_val = qi::_1]; + qi::rule seq = '{' > *element > '}'; + qi::rule mload = '@' > element; + qi::rule sload = qi::lit("@@") > element; + qi::rule mstore = '[' > element > ']' > -qi::lit(":") > element; + qi::rule sstore = qi::lit("[[") > element > qi::lit("]]") > -qi::lit(":") > element; + qi::rule extra = sload[qi::_val = qi::_1, bind(&sp::utree::tag, qi::_val, 2)] | mload[qi::_val = qi::_1, bind(&sp::utree::tag, qi::_val, 1)] | sstore[qi::_val = qi::_1, bind(&sp::utree::tag, qi::_val, 4)] | mstore[qi::_val = qi::_1, bind(&sp::utree::tag, qi::_val, 3)] | seq[qi::_val = qi::_1, bind(&sp::utree::tag, qi::_val, 5)]; + qi::rule list = '(' > *element > ')'; + element = atom | list | extra; + + try + { + qi::phrase_parse(_s.begin(), _s.end(), element, space, o_out); + } + catch (std::exception& _e) + { + cnote << _e.what(); + } +} + struct CompileState { map vars; @@ -1303,7 +1296,19 @@ void debugOutAST(ostream& _out, sp::utree const& _this) { switch (_this.which()) { - case sp::utree_type::list_type: _out << "( "; for (auto const& i: _this) { debugOut(_out, i); _out << " "; } _out << ")"; break; + case sp::utree_type::list_type: + switch (_this.tag()) + { + case 0: _out << "( "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << ")"; break; + case 1: _out << "@ "; debugOutAST(_out, _this.front()); break; + case 2: _out << "@@ "; debugOutAST(_out, _this.front()); break; + case 3: _out << "[ "; debugOutAST(_out, _this.front()); _out << " ] "; debugOutAST(_out, _this.back()); break; + case 4: _out << "[[ "; debugOutAST(_out, _this.front()); _out << " ]] "; debugOutAST(_out, _this.back()); break; + case 5: _out << "{ "; for (auto const& i: _this) { debugOutAST(_out, i); _out << " "; } _out << "}"; break; + default:; + } + + break; case sp::utree_type::int_type: _out << _this.get(); break; case sp::utree_type::string_type: _out << "\"" << _this.get, sp::utree_type::string_type>>() << "\""; break; case sp::utree_type::symbol_type: _out << _this.get, sp::utree_type::symbol_type>>(); break; @@ -1367,13 +1372,37 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState& _s) { if (_t.empty()) error(); - else if (_t.front().which() != sp::utree_type::symbol_type) + else if (_t.tag() == 0 && _t.front().which() != sp::utree_type::symbol_type) error(); else { - auto sr = _t.front().get, sp::utree_type::symbol_type>>(); - string s(sr.begin(), sr.end()); - boost::algorithm::to_upper(s); + string s; + switch (_t.tag()) + { + case 0: + { + auto sr = _t.front().get, sp::utree_type::symbol_type>>(); + s = string(sr.begin(), sr.end()); + boost::algorithm::to_upper(s); + break; + } + case 1: + s = "MLOAD"; + break; + case 2: + s = "SLOAD"; + break; + case 3: + s = "MSTORE"; + break; + case 4: + s = "SSTORE"; + break; + case 5: + s = "SEQ"; + break; + default:; + } if (s == "ASM") { @@ -1390,7 +1419,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState& _s) vector code; CompileState ns = _s; ns.vars.clear(); - int c = 0; + int c = _t.tag() ? 1 : 0; for (auto const& i: _t) if (c++) code.push_back(CodeFragment(i, (s == "LLL" && c == 1) ? ns : _s)); @@ -1579,8 +1608,12 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState& _s) } else if (s == "SEQ") { + unsigned ii = 0; for (auto const& i: code) - appendFragment(i, 0); + if (++ii < code.size()) + appendFragment(i, 0); + else + appendFragment(i); } else {