From b486033cbf0074d59fe143dd3fc809b1a588798c Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Fri, 4 Apr 2014 21:34:02 -0400 Subject: [PATCH] New language facilities. --- alethzero/MainWin.cpp | 2 +- libethereum/Instruction.cpp | 120 ++++++++++++++++++++++++++++-------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index e358fc5d5..1dcd9c95d 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -537,7 +537,7 @@ void Main::on_data_textChanged() string code = ui->data->toPlainText().toStdString(); m_init.clear(); m_data = compileLisp(code, true, m_init); - ui->code->setHtml((m_init.size() ? ("

Init

" + QString::fromStdString(disassemble(m_init)) + "
") : "") + "

Body

" + QString::fromStdString(disassemble(m_data)) + "
"); + ui->code->setHtml((m_init.size() ? "

Init

" + QString::fromStdString(disassemble(m_init)).toHtmlEscaped() : "") + "

Body

" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped()); ui->gas->setMinimum((qint64)state().createGas(m_data.size() + m_init.size(), 0)); if (!ui->gas->isEnabled()) ui->gas->setValue(m_backupGas); diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index 994c0c2b7..109ed7ccf 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -339,7 +339,7 @@ static void appendCode(bytes& o_code, vector& o_locs, bytes _code, vec o_code.push_back(i); } -static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes& o_code, vector& o_locs) +static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes& o_code, vector& o_locs, map& _vars) { std::map const c_arith = { { "+", Instruction::ADD }, { "-", Instruction::SUB }, { "*", Instruction::MUL }, { "/", Instruction::DIV }, { "%", Instruction::MOD } }; std::map> const c_binary = { { "<", { Instruction::LT, false } }, { "<=", { Instruction::GT, true } }, { ">", { Instruction::GT, false } }, { ">=", { Instruction::LT, true } }, { "=", { Instruction::EQ, false } }, { "!=", { Instruction::EQ, true } } }; @@ -352,7 +352,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes while (d != e) { // skip to next token - for (; d != e && !isalnum(*d) && *d != '(' && *d != ')' && *d != '_' && *d != '"' && !c_allowed.count(*d) && *d != ';'; ++d) {} + for (; d != e && !isalnum(*d) && *d != '(' && *d != ')' && *d != '_' && *d != '"' && *d != '@' && *d != '[' && !c_allowed.count(*d) && *d != ';'; ++d) {} if (d == e) break; @@ -374,6 +374,59 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes else // unexpected - return false as we don't know what to do with it. return -1; + case '@': + { + if (exec) + return -1; + bool store = false; + ++d; + if (*d == '@') + { + ++d; + store = true; + } + bytes codes; + vector locs; + if (compileLispFragment(d, e, _quiet, codes, locs, _vars) != 1) + return -1; + while (d != e && isspace(*d)) + ++d; + appendCode(o_code, o_locs, codes, locs); + o_code.push_back((byte)(store ? Instruction::SLOAD : Instruction::MLOAD)); + return 1; + } + case '[': + { + if (exec) + return -1; + bool store = false; + ++d; + if (*d == '[') + { + ++d; + store = true; + } + bytes codes; + vector locs; + if (compileLispFragment(d, e, _quiet, codes, locs, _vars) != 1) + return -1; + while (d != e && isspace(*d)) + ++d; + + if (*d != ']') + return -1; + ++d; + if (store && *d != ']') + return -1; + ++d; + + if (compileLispFragment(d, e, _quiet, o_code, o_locs, _vars) != 1) + return -1; + + appendCode(o_code, o_locs, codes, locs); + o_code.push_back((byte)(store ? Instruction::SSTORE: Instruction::MSTORE)); + return 1; + } default: { bool haveLiteral = false; @@ -414,10 +467,10 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes { bytes codes; vector locs; - if (compileLispFragment(d, e, _quiet, codes, locs) != -1) + if (compileLispFragment(d, e, _quiet, codes, locs, _vars) != -1) { appendCode(o_code, o_locs, codes, locs); - while (compileLispFragment(d, e, _quiet, codes, locs) != -1) + while (compileLispFragment(d, e, _quiet, codes, locs, _vars) != -1) if (!_quiet) cwarn << "Additional items in bare store. Ignoring."; bareLoad = false; @@ -437,13 +490,13 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes vector locs[4]; for (int i = 0; i < 3; ++i) { - int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]); + int o = compileLispFragment(d, e, _quiet, codes[i], locs[i], _vars); if (i == 1) outs = o; if ((i == 0 && o != 1) || o == -1 || (i == 2 && o != outs)) return -1; } - if (compileLispFragment(d, e, _quiet, codes[3], locs[3]) != -1) + if (compileLispFragment(d, e, _quiet, codes[3], locs[3], _vars) != -1) return false; // First fragment - predicate @@ -481,14 +534,14 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes vector locs[3]; for (int i = 0; i < 2; ++i) { - int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]); + int o = compileLispFragment(d, e, _quiet, codes[i], locs[i], _vars); if (o == -1 || (i == 0 && o != 1)) return false; if (i == 1) for (int j = 0; j < o; ++j) codes[i].push_back((byte)Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on). } - if (compileLispFragment(d, e, _quiet, codes[2], locs[2]) != -1) + if (compileLispFragment(d, e, _quiet, codes[2], locs[2], _vars) != -1) return false; // First fragment - predicate @@ -518,14 +571,14 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes vector locs[3]; for (int i = 0; i < 2; ++i) { - int o = compileLispFragment(d, e, _quiet, codes[i], locs[i]); + int o = compileLispFragment(d, e, _quiet, codes[i], locs[i], _vars); if (o == -1 || (i == 0 && o != 1)) return false; if (i == 1) for (int j = 0; j < o; ++j) codes[i].push_back((byte)Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on). } - if (compileLispFragment(d, e, _quiet, codes[2], locs[2]) != -1) + if (compileLispFragment(d, e, _quiet, codes[2], locs[2], _vars) != -1) return false; unsigned startLocation = (unsigned)o_code.size(); @@ -561,7 +614,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes vector locs; outs = 0; int o; - if ((o = compileLispFragment(d, e, _quiet, codes, locs)) > -1) + if ((o = compileLispFragment(d, e, _quiet, codes, locs, _vars)) > -1) { for (int i = 0; i < outs; ++i) o_code.push_back((byte)Instruction::POP); // pop additional items off stack for the previous item (final item's returns get left on). @@ -580,7 +633,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes int totalArgs = 0; while (d != e) { - int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second); + int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second, _vars); if (o < 1) break; codes.push_back(pair>()); @@ -612,7 +665,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes vector locs; outs = 0; int o; - if ((o = compileLispFragment(d, e, _quiet, codes, locs)) > -1) + if ((o = compileLispFragment(d, e, _quiet, codes, locs, _vars)) > -1) { outs += o; appendCode(o_code, o_locs, codes, locs); @@ -630,11 +683,11 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes codes.resize(codes.size() + 1); locs.resize(locs.size() + 1); { - int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back()); + int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back(), _vars); if (o != 1) return false; } - if (compileLispFragment(d, e, _quiet, codes.back(), locs.back()) != -1) + if (compileLispFragment(d, e, _quiet, codes.back(), locs.back(), _vars) != -1) break; } @@ -684,7 +737,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes codes.resize(codes.size() + 1); locs.resize(locs.size() + 1); { - int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back()); + int o = compileLispFragment(d, e, _quiet, codes.back(), locs.back(), _vars); if (o != 1) return false; } @@ -737,7 +790,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes int totalArgs = 0; while (d != e) { - int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second); + int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second, _vars); if (o < 1) break; codes.push_back(pair>()); @@ -770,7 +823,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes int totalArgs = 0; while (d != e) { - int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second); + int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second, _vars); if (o < 1) break; codes.push_back(pair>()); @@ -795,7 +848,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes int totalArgs = 0; while (d != e) { - int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second); + int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second, _vars); if (o < 1) break; codes.push_back(pair>()); @@ -823,7 +876,7 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes int totalArgs = 0; while (d != e) { - int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second); + int o = compileLispFragment(d, e, _quiet, codes.back().first, codes.back().second, _vars); if (o == -1) break; totalArgs += o; @@ -840,8 +893,16 @@ static int compileLispFragment(char const*& d, char const* e, bool _quiet, bytes appendCode(o_code, o_locs, it->first, it->second); o_code.push_back((byte)it->second); } - else if (!_quiet) - cwarn << "Unknown assembler token" << t; + else + { + auto it = _vars.find(t); + if (it == _vars.end()) + { + bool ok; + tie(it, ok) = _vars.insert(make_pair(t, _vars.size() * 32)); + } + pushLiteral(o_code, it->second); + } } } } @@ -860,12 +921,19 @@ bytes eth::compileLisp(std::string const& _code, bool _quiet, bytes& _init) { char const* d = _code.data(); char const* e = _code.data() + _code.size(); - bytes ret; + bytes first; + bytes second; vector locs; - compileLispFragment(d, e, _quiet, ret, locs); + map vars; + compileLispFragment(d, e, _quiet, first, locs, vars); locs.clear(); - compileLispFragment(d, e, _quiet, _init, locs); - return ret; + vars.clear(); + if (compileLispFragment(d, e, _quiet, second, locs, vars) > -1) + { + _init = first; + return second; + } + return first; } string eth::disassemble(bytes const& _mem)