Browse Source

Other operators.

cl-refactor
Gav Wood 11 years ago
parent
commit
3744b2dab3
  1. 70
      libethereum/Instruction.cpp

70
libethereum/Instruction.cpp

@ -1165,7 +1165,7 @@ class CodeFragment
friend class CodeLocation; friend class CodeLocation;
public: 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; } bytes const& code() const { return m_code; }
@ -1193,7 +1193,7 @@ protected:
private: private:
template <class T> void error() { throw T(); } template <class T> 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<InvalidDeposit>(); } void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) error<InvalidDeposit>(); }
@ -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()) 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()) if (_t.empty())
error<EmptyList>(); error<EmptyList>();
@ -1388,10 +1388,11 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _
std::map<std::string, Instruction> const c_unary = { { "!", Instruction::NOT } }; std::map<std::string, Instruction> const c_unary = { { "!", Instruction::NOT } };
vector<CodeFragment> code; vector<CodeFragment> code;
CompileState ns;
int c = 0; int c = 0;
for (auto const& i: _t) for (auto const& i: _t)
if (c++) 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<IncorrectParameterCount>(); }; auto requireSize = [&](unsigned s) { if (code.size() != s) error<IncorrectParameterCount>(); };
auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(); }; auto requireMinSize = [&](unsigned s) { if (code.size() < s) error<IncorrectParameterCount>(); };
auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(); }; auto requireMaxSize = [&](unsigned s) { if (code.size() > s) error<IncorrectParameterCount>(); };
@ -1406,10 +1407,42 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _
else else
requireMinSize(-ea); requireMinSize(-ea);
for (int i = code.size(); i; --i) for (unsigned i = code.size(); i; --i)
appendFragment(code[i - 1], 1); appendFragment(code[i - 1], 1);
appendInstruction(it->second); 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") else if (s == "IF")
{ {
requireSize(3); requireSize(3);
@ -1536,13 +1569,33 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompileState const& _
for (auto& i: ends) for (auto& i: ends)
i.anchor(); 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") else if (s == "SEQ")
{ {
for (auto const& i: code) for (auto const& i: code)
appendFragment(i, 0); appendFragment(i, 0);
} }
else else
error<InvalidOpCode>(); {
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<InvalidOpCode>();
} }
} }
@ -1555,7 +1608,8 @@ bytes eth::compileLLL(string const& _s, vector<string>* _errors)
if (!o.empty()) if (!o.empty())
try try
{ {
ret = CodeFragment(o).code(); CompileState cs;
ret = CodeFragment(o, cs).code();
} }
catch (CompilerException const& _e) catch (CompilerException const& _e)
{ {

Loading…
Cancel
Save