Browse Source

Recursive LLL-copmiler.

cl-refactor
Gav Wood 11 years ago
parent
commit
21b15bfb1a
  1. 2
      alethzero/MainWin.cpp
  2. 2
      libethereum/Common.h
  3. 139
      libethereum/Instruction.cpp
  4. 4
      libethereum/Instruction.h
  5. 11
      libethereum/State.cpp

2
alethzero/MainWin.cpp

@ -372,7 +372,7 @@ void Main::on_destination_textChanged()
void Main::on_data_textChanged() void Main::on_data_textChanged()
{ {
string code = ui->data->toPlainText().toStdString(); string code = ui->data->toPlainText().toStdString();
m_data = code[0] == '(' ? compileLisp(code, true) : assemble(code); m_data = code[0] == '(' ? compileLisp(code, true) : assemble(code, true);
ui->code->setPlainText(QString::fromStdString(disassemble(m_data))); ui->code->setPlainText(QString::fromStdString(disassemble(m_data)));
updateFee(); updateFee();
} }

2
libethereum/Common.h

@ -216,7 +216,7 @@ public:
char buf[24]; char buf[24];
if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0) if (strftime(buf, 24, "%X", localtime(&rawTime)) == 0)
buf[0] = '\0'; // empty if case strftime fails buf[0] = '\0'; // empty if case strftime fails
sstr << Id::name << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : ""); sstr << Id::name() << " [ " << buf << " | " << *(t_logThreadName.m_name.get()) << (_term ? " ] " : "");
} }
} }
~LogOutputStream() { if (Id::verbosity <= g_logVerbosity) g_logPost(sstr.str(), Id::name()); } ~LogOutputStream() { if (Id::verbosity <= g_logVerbosity) g_logPost(sstr.str(), Id::name()); }

139
libethereum/Instruction.cpp

@ -25,45 +25,60 @@
using namespace std; using namespace std;
using namespace eth; using namespace eth;
u256s eth::assemble(std::string const& _code) u256s eth::assemble(std::string const& _code, bool _quiet)
{ {
u256s ret; u256s ret;
map<string, unsigned> known;
map<unsigned, string> req;
char const* d = _code.data(); char const* d = _code.data();
char const* e = _code.data() + _code.size(); char const* e = _code.data() + _code.size();
while (d != e) while (d != e)
{ {
// skip to next token // skip to next token
for (; d != e && !isalnum(*d) && *d != '_'; ++d) {} for (; d != e && !isalnum(*d) && *d != '_' && *d != ':'; ++d) {}
if (d == e) if (d == e)
break; break;
char const* s = d; char const* s = d;
for (; d != e && (isalnum(*d) || *d == '_'); ++d) {} for (; d != e && (isalnum(*d) || *d == '_' || *d == ':'); ++d) {}
string t = string(s, d - s); string t = string(s, d - s);
if (isdigit(t[0])) if (isdigit(t[0]))
ret.push_back(u256(t)); try
{
ret.push_back(u256(t));
}
catch (...)
{
cwarn << "Invalid numeric" << t;
}
else if (t.back() == ':')
known[t.substr(0, t.size() - 1)] = ret.size();
else else
{ {
boost::algorithm::to_upper(t); auto it = c_instructions.find(boost::algorithm::to_upper_copy(t));
auto it = c_instructions.find(t);
if (it != c_instructions.end()) if (it != c_instructions.end())
ret.push_back((u256)it->second); ret.push_back((u256)it->second);
else else
cwarn << "Unknown assembler token" << t; {
req[ret.size()] = t;
ret.push_back(0);
}
} }
} }
for (auto i: req)
if (known.count(i.second))
ret[i.first] = known[i.second];
else
cwarn << "Unknown assembler token" << i.second << "at address" << i.first;
return ret; return ret;
} }
u256s eth::compileLisp(std::string const& _code, bool _quiet) static bool compileLispFragment(char const*& d, char const* e, bool _quiet, unsigned _off, u256s& o_code, vector<unsigned>& o_locs)
{ {
u256s ret; bool exec = false;
vector<pair<Instruction, int>> inStack;
char const* d = _code.data();
char const* e = _code.data() + _code.size();
while (d != e) while (d != e)
{ {
// skip to next token // skip to next token
@ -74,59 +89,105 @@ u256s eth::compileLisp(std::string const& _code, bool _quiet)
switch (*d) switch (*d)
{ {
case '(': case '(':
inStack.push_back(make_pair(Instruction::STOP, 0)); exec = true;
++d; ++d;
break; break;
case ')': case ')':
++d; if (exec)
if (inStack.size()) {
ret.push_back(inStack.back().first); ++d;
inStack.pop_back(); return true;
if (inStack.size()) }
inStack.back().second++; else
break; // unexpected - return false as we don't know what to do with it.
return false;
default: default:
{ {
char const* s = d; char const* s = d;
for (; d != e && isalnum(*d); ++d) {} for (; d != e && (isalnum(*d) || *d == '_'); ++d) {}
string t = string(s, d - s); string t(s, d - s);
if (isdigit(t[0])) if (isdigit(t[0]))
if (inStack.size() && !inStack.back().second) {
if (exec)
{ {
if (!_quiet) cwarn << "Cannot execute numeric" << t;
cwarn << "Cannot execute numeric" << t;
} }
else else
{ {
ret.push_back(Instruction::PUSH); o_code.push_back(Instruction::PUSH);
ret.push_back(u256(t)); try
{
o_code.push_back(u256(t));
}
catch (...)
{
cwarn << "Invalid numeric" << t;
}
} }
}
else else
{ {
boost::algorithm::to_upper(t); boost::algorithm::to_upper(t);
auto it = c_instructions.find(t); if (t == "IF")
if (it != c_instructions.end()) {
}
else
{ {
if (inStack.size()) auto it = c_instructions.find(t);
if (it != c_instructions.end())
{ {
if (!inStack.back().second) if (exec)
inStack.back().first = it->second; {
vector<pair<u256s, vector<unsigned>>> codes(1);
while (d != e && compileLispFragment(d, e, _quiet, o_code.size(), codes.back().first, codes.back().second))
codes.push_back(pair<u256s, vector<unsigned>>());
for (auto it = codes.rbegin(); it != codes.rend(); ++it)
{
for (auto i: it->second)
it->first[i] += o_code.size();
o_code.reserve(o_code.size() + it->first.size());
for (auto i: it->first)
o_code.push_back(i);
}
o_code.push_back((u256)it->second);
}
else else
ret.push_back((u256)it->second); {
inStack.back().second++; o_code.push_back(Instruction::PUSH);
try
{
o_code.push_back((u256)it->second);
}
catch (...)
{
cwarn << "Invalid numeric" << t;
o_code.push_back(u256(t));
}
}
} }
else if (!_quiet) else if (!_quiet)
cwarn << "Instruction outside parens" << t; cwarn << "Unknown assembler token" << t;
} }
else if (!_quiet)
cwarn << "Unknown assembler token" << t;
} }
if (!exec)
return true;
} }
} }
} }
return ret; return false;
}
u256s eth::compileLisp(std::string const& _code, bool _quiet)
{
char const* d = _code.data();
char const* e = _code.data() + _code.size();
u256s ret;
vector<unsigned> locs;
compileLispFragment(d, e, _quiet, 0, ret, locs);
return ret;
} }
string eth::disassemble(u256s const& _mem) string eth::disassemble(u256s const& _mem)

4
libethereum/Instruction.h

@ -143,7 +143,7 @@ static const std::map<Instruction, InstructionInfo> c_instructionInfo =
{ Instruction::IND, { "IND", 0, 0, 1 } }, { Instruction::IND, { "IND", 0, 0, 1 } },
{ Instruction::EXTRO, { "EXTRO", 0, 2, 1 } }, { Instruction::EXTRO, { "EXTRO", 0, 2, 1 } },
{ Instruction::BALANCE, { "BALANCE", 0, 1, 1 } }, { Instruction::BALANCE, { "BALANCE", 0, 1, 1 } },
{ Instruction::MKTX, { "MKTX", 0, 4, 0 } }, { Instruction::MKTX, { "MKTX", 0, -3, 0 } },
{ Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} } { Instruction::SUICIDE, { "SUICIDE", 0, 1, 0} }
}; };
@ -202,7 +202,7 @@ static const std::map<std::string, Instruction> c_instructions =
{ "SUICIDE", Instruction::SUICIDE } { "SUICIDE", Instruction::SUICIDE }
}; };
u256s assemble(std::string const& _code); u256s assemble(std::string const& _code, bool _quiet = false);
std::string disassemble(u256s const& _mem); std::string disassemble(u256s const& _mem);
u256s compileLisp(std::string const& _code, bool _quiet = false); u256s compileLisp(std::string const& _code, bool _quiet = false);

11
libethereum/State.cpp

@ -278,6 +278,10 @@ void State::resetCurrent()
m_currentBlock.parentHash = m_previousBlock.hash; m_currentBlock.parentHash = m_previousBlock.hash;
m_currentBlock.sha3Transactions = h256(); m_currentBlock.sha3Transactions = h256();
m_currentBlock.sha3Uncles = h256(); m_currentBlock.sha3Uncles = h256();
// Update timestamp according to clock.
m_currentBlock.timestamp = time(0);
m_state.setRoot(m_currentBlock.stateRoot); m_state.setRoot(m_currentBlock.stateRoot);
} }
@ -489,9 +493,6 @@ void State::commitToMine(BlockChain const& _bc)
MineInfo State::mine(uint _msTimeout) MineInfo State::mine(uint _msTimeout)
{ {
// Update timestamp according to clock.
m_currentBlock.timestamp = time(0);
// Update difficulty according to timestamp. // Update difficulty according to timestamp.
m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock); m_currentBlock.difficulty = m_currentBlock.calculateDifficulty(m_previousBlock);
@ -927,7 +928,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s
stack.push_back((u160)m_currentBlock.coinbaseAddress); stack.push_back((u160)m_currentBlock.coinbaseAddress);
break; break;
case Instruction::BLK_TIMESTAMP: case Instruction::BLK_TIMESTAMP:
stack.push_back(m_currentBlock.timestamp); stack.push_back(m_previousBlock.timestamp);
break; break;
case Instruction::BLK_NUMBER: case Instruction::BLK_NUMBER:
stack.push_back(m_currentNumber); stack.push_back(m_currentNumber);
@ -936,7 +937,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256s
stack.push_back(m_currentBlock.difficulty); stack.push_back(m_currentBlock.difficulty);
break; break;
case Instruction::BLK_NONCE: case Instruction::BLK_NONCE:
stack.push_back(m_currentBlock.nonce); stack.push_back(m_previousBlock.nonce);
break; break;
case Instruction::BASEFEE: case Instruction::BASEFEE:
stack.push_back(m_fees.multiplier()); stack.push_back(m_fees.multiplier());

Loading…
Cancel
Save