diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index fe19c818e..c76ed77ba 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -1165,7 +1165,7 @@ class CodeFragment friend class CodeLocation; public: - CodeFragment(sp::utree const& _t, CompileState const& _s = CompileState(), bool _allowASM = false); + CodeFragment(sp::utree const& _t, CompileState& _s, bool _allowASM = false); bytes const& code() const { return m_code; } @@ -1193,7 +1193,7 @@ protected: private: template void error() { throw T(); } - void constructOperation(sp::utree const& _t, CompileState const& _s); + void constructOperation(sp::utree const& _t, CompileState& _s); void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) error(); } @@ -1312,7 +1312,7 @@ void debugOutAST(ostream& _out, sp::utree const& _this) } } -CodeFragment::CodeFragment(sp::utree const& _t, CompileState const& _s, bool _allowASM) +CodeFragment::CodeFragment(sp::utree const& _t, CompileState& _s, bool _allowASM) { switch (_t.which()) { @@ -1363,7 +1363,7 @@ CodeFragment::CodeFragment(sp::utree const& _t, CompileState const& _s, bool _al } } -void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _s) +void CodeFragment::constructOperation(sp::utree const& _t, CompileState& _s) { if (_t.empty()) error(); @@ -1388,10 +1388,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _ std::map const c_unary = { { "!", Instruction::NOT } }; vector code; + CompileState ns; int c = 0; for (auto const& i: _t) if (c++) - code.push_back(CodeFragment(i, (s == "LLL" && c == 1) ? CompileState() : _s)); + code.push_back(CodeFragment(i, (s == "LLL" && c == 1) ? ns : _s)); auto requireSize = [&](unsigned s) { if (code.size() != s) error(); }; auto requireMinSize = [&](unsigned s) { if (code.size() < s) error(); }; auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error(); }; @@ -1406,10 +1407,42 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _ else requireMinSize(-ea); - for (int i = code.size(); i; --i) + for (unsigned i = code.size(); i; --i) appendFragment(code[i - 1], 1); appendInstruction(it->second); } + else if (c_arith.count(s)) + { + auto it = c_arith.find(s); + requireMinSize(1); + for (unsigned i = 0; i < code.size(); ++i) + { + requireDeposit(i, 1); + appendFragment(code[i], 1); + } + for (unsigned i = 1; i < code.size(); ++i) + appendInstruction(it->second); + } + else if (c_binary.count(s)) + { + auto it = c_binary.find(s); + requireSize(2); + requireDeposit(0, 1); + requireDeposit(1, 1); + appendFragment(code[1], 1); + appendFragment(code[0], 1); + appendInstruction(it->second.first); + if (it->second.second) + appendInstruction(Instruction::NOT); + } + else if (c_unary.count(s)) + { + auto it = c_unary.find(s); + requireSize(1); + requireDeposit(0, 1); + appendFragment(code[0], 1); + appendInstruction(it->second); + } else if (s == "IF") { requireSize(3); @@ -1536,13 +1569,33 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _ for (auto& i: ends) i.anchor(); } + else if (s == "~") + { + requireSize(1); + requireDeposit(0, 1); + appendFragment(code[0], 1); + appendPush(1); + appendPush(0); + appendInstruction(Instruction::SUB); + appendInstruction(Instruction::SUB); + } else if (s == "SEQ") { for (auto const& i: code) appendFragment(i, 0); } else - error(); + { + auto it = _s.vars.find(s); + if (it == _s.vars.end()) + { + bool ok; + tie(it, ok) = _s.vars.insert(make_pair(s, _s.vars.size() * 32)); + } + appendPush(it->second); + } +// else +// error(); } } @@ -1555,7 +1608,8 @@ bytes eth::compileLLL(string const& _s, vector* _errors) if (!o.empty()) try { - ret = CodeFragment(o).code(); + CompileState cs; + ret = CodeFragment(o, cs).code(); } catch (CompilerException const& _e) {