diff --git a/include.lll b/include.lll new file mode 100644 index 000000000..ea196b123 --- /dev/null +++ b/include.lll @@ -0,0 +1,7 @@ +{ +(def 'gav 0x8a40bfaa73256b60764c1bf40675a99083efb075) +(def 'send (to value) (call (- (gas) 21) to value 0 0 0 0)) +(def 'makevar (name pos) { (def name (sload pos)) (def name (v) (sstore pos v)) } ) +(def 'varcount 0) +(def 'var (name) { (makevar name varcount) (def 'varcount (+ varcount 1)) } ) +} diff --git a/libethereum/Instruction.cpp b/libethereum/Instruction.cpp index 9b88d8d38..150aabee8 100644 --- a/libethereum/Instruction.cpp +++ b/libethereum/Instruction.cpp @@ -310,6 +310,7 @@ struct CompilerState std::map args; std::map outers; std::map macros; + std::vector treesToKill; }; } @@ -546,12 +547,30 @@ void CodeFragment::appendPushDataLocation(bytes const& _data) std::string CodeFragment::asPushedString() const { string ret; - unsigned bc = m_code[0] - (byte)Instruction::PUSH1 + 1; - if (m_code.size() && m_code[0] >= (byte)Instruction::PUSH1 && m_code[0] <= (byte)Instruction::PUSH32) - for (unsigned s = 0; s < bc && m_code[1 + s]; ++s) - ret.push_back(m_code[1 + s]); - else - error(); + if (m_code.size()) + { + unsigned bc = m_code[0] - (byte)Instruction::PUSH1 + 1; + if (m_code[0] >= (byte)Instruction::PUSH1 && m_code[0] <= (byte)Instruction::PUSH32) + { + for (unsigned s = 0; s < bc && m_code[1 + s]; ++s) + ret.push_back(m_code[1 + s]); + return ret; + } + } + error(); + return ret; +} + +CodeFragment compileLLLFragment(string const& _src, CompilerState& _s) +{ + CodeFragment ret; + sp::utree o; + parseLLL(_src, o); + debugOutAST(cerr, o); + cerr << endl; + if (!o.empty()) + ret = CodeFragment(o, _s); + _s.treesToKill.push_back(o); return ret; } @@ -601,6 +620,26 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) if (c++) appendFragment(CodeFragment(i, _s, true)); } + else if (us == "INCLUDE") + { + if (_t.size() != 2) + error(); + string n; + auto i = *++_t.begin(); + if (i.tag()) + error(); + if (i.which() == sp::utree_type::string_type) + { + auto sr = i.get, sp::utree_type::string_type>>(); + n = string(sr.begin(), sr.end()); + } + else if (i.which() == sp::utree_type::symbol_type) + { + auto sr = i.get, sp::utree_type::symbol_type>>(); + n = _s.getDef(string(sr.begin(), sr.end())).asPushedString(); + } + appendFragment(compileLLLFragment(asString(contents(n)), _s)); + } else if (us == "DEF") { string n; @@ -934,33 +973,25 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s) bytes eth::compileLLL(string const& _s, vector* _errors) { - bytes ret; - sp::utree o; try { - parseLLL(_s, o); + CompilerState cs; + bytes ret = compileLLLFragment(_s, cs).code(); + for (auto i: cs.treesToKill) + killBigints(i); + return ret; } - catch (...) + catch (Exception const& _e) { if (_errors) - _errors->push_back("Syntax error."); - return ret; + _errors->push_back(_e.description()); } - debugOutAST(cerr, o); - cerr << endl; - if (!o.empty()) - try - { - CompilerState cs; - ret = CodeFragment(o, cs).code(); - } - catch (CompilerException const& _e) - { - if (_errors) - _errors->push_back(_e.description()); - } - killBigints(o); - return ret; + catch (std::exception) + { + if (_errors) + _errors->push_back("Parse error."); + } + return bytes(); } string eth::disassemble(bytes const& _mem) diff --git a/libethereum/Instruction.h b/libethereum/Instruction.h index 5f80a3e69..1042a4a8d 100644 --- a/libethereum/Instruction.h +++ b/libethereum/Instruction.h @@ -217,6 +217,8 @@ public: CodeLocation appendJump(CodeLocation _l) { auto ret = appendPushLocation(_l.m_pos); appendInstruction(Instruction::JUMP); return ret; } CodeLocation appendJumpI(CodeLocation _l) { auto ret = appendPushLocation(_l.m_pos); appendInstruction(Instruction::JUMPI); return ret; } + void appendFile(std::string const& _fn); + std::string asPushedString() const; void onePath() { assert(!m_totalDeposit && !m_baseDeposit); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; }