aboutsummaryrefslogtreecommitdiffstats
path: root/Assembly.h
diff options
context:
space:
mode:
authorGav Wood <i@gavwood.com>2014-05-27 01:41:46 +0800
committerGav Wood <i@gavwood.com>2014-05-27 01:41:46 +0800
commit51e6c251641eef12ba93b725974faa35b514d636 (patch)
tree9113f63687347c7d5a61c5bb2db61ffe4d800da4 /Assembly.h
parent8e3e592ec6a3b39835e540766774025e3f34c590 (diff)
downloaddexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.tar.gz
dexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.tar.zst
dexon-solidity-51e6c251641eef12ba93b725974faa35b514d636.zip
New Assembler.
Diffstat (limited to 'Assembly.h')
-rw-r--r--Assembly.h54
1 files changed, 48 insertions, 6 deletions
diff --git a/Assembly.h b/Assembly.h
index ca3beaf5..86b37622 100644
--- a/Assembly.h
+++ b/Assembly.h
@@ -22,6 +22,7 @@
#pragma once
#include <iostream>
+#include <sstream>
#include <libethsupport/Common.h>
#include <libethcore/Instruction.h>
#include "Exceptions.h"
@@ -39,14 +40,16 @@ class AssemblyItem
public:
AssemblyItem(u256 _push): m_type(Push), m_data(_push) {}
- AssemblyItem(AssemblyItemType _type, AssemblyItem const& _tag): m_type(_type), m_data(_tag.m_data) { assert(_type == PushTag); assert(_tag.m_type == Tag); }
AssemblyItem(Instruction _i): m_type(Operation), m_data((byte)_i) {}
AssemblyItem(AssemblyItemType _type, u256 _data): m_type(_type), m_data(_data) {}
+ AssemblyItem tag() const { assert(m_type == PushTag || m_type == Tag); return AssemblyItem(Tag, m_data); }
+ AssemblyItem pushTag() const { assert(m_type == PushTag || m_type == Tag); return AssemblyItem(PushTag, m_data); }
+
AssemblyItemType type() const { return m_type; }
u256 data() const { return m_data; }
- std::ostream& streamOut(std::ostream& _out) const;
+ int deposit() const;
private:
AssemblyItemType m_type;
@@ -57,19 +60,58 @@ class Assembly
{
public:
AssemblyItem newTag() { return AssemblyItem(Tag, m_usedTags++); }
+ AssemblyItem newPushTag() { return AssemblyItem(PushTag, m_usedTags++); }
AssemblyItem newData(bytes const& _data) { auto h = sha3(_data); m_data[h] = _data; return AssemblyItem(PushData, h); }
- AssemblyItem newPushString(std::string const& _data) { auto b = asBytes(_data); auto h = sha3(b); m_data[h] = b; return AssemblyItem(PushString, h); }
+ AssemblyItem newPushString(std::string const& _data) { auto h = sha3(_data); m_strings[h] = _data; return AssemblyItem(PushString, h); }
+
+ AssemblyItem append() { return append(newTag()); }
+ void append(Assembly const& _a);
+ void append(Assembly const& _a, int _deposit);
+ AssemblyItem const& append(AssemblyItem const& _i);
+ AssemblyItem const& append(std::string const& _data) { return append(newPushString(_data)); }
+ AssemblyItem const& append(bytes const& _data) { return append(newData(_data)); }
+
+ AssemblyItem appendJump() { auto ret = append(newPushTag()); append(Instruction::JUMP); return ret; }
+ AssemblyItem appendJumpI() { auto ret = append(newPushTag()); append(Instruction::JUMPI); return ret; }
+ AssemblyItem appendJump(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMP); return ret; }
+ AssemblyItem appendJumpI(AssemblyItem const& _tag) { auto ret = append(_tag.pushTag()); append(Instruction::JUMPI); return ret; }
+
+ template <class T> Assembly& operator<<(T const& _d) { append(_d); return *this; }
+
+ AssemblyItem const& back() { return m_items.back(); }
+ std::string backString() const { return m_items.back().m_type == PushString ? m_strings.at((h256)m_items.back().m_data) : std::string(); }
- void append(AssemblyItem const& _i) { m_items.push_back(_i); }
+ void onePath() { assert(!m_totalDeposit && !m_baseDeposit); m_baseDeposit = m_deposit; m_totalDeposit = INT_MAX; }
+ void otherPath() { donePath(); m_totalDeposit = m_deposit; m_deposit = m_baseDeposit; }
+ void donePaths() { donePath(); m_totalDeposit = m_baseDeposit = 0; }
+ void ignored() { m_baseDeposit = m_deposit; }
+ void endIgnored() { m_deposit = m_baseDeposit; m_baseDeposit = 0; }
+ void popTo(int _deposit) { while (m_deposit > _deposit) append(Instruction::POP); }
+
+ std::string out() const { std::stringstream ret; streamOut(ret); return ret.str(); }
+ int deposit() const { return m_deposit; }
bytes assemble() const;
- void append(Assembly const& _a);
std::ostream& streamOut(std::ostream& _out) const;
private:
- u256 m_usedTags = 0;
+ void donePath() { if (m_totalDeposit != INT_MAX && m_totalDeposit != m_deposit) throw InvalidDeposit(); }
+ unsigned bytesRequired() const;
+
+ unsigned m_usedTags = 0;
std::vector<AssemblyItem> m_items;
std::map<h256, bytes> m_data;
+ std::map<h256, std::string> m_strings;
+
+ int m_deposit = 0;
+ int m_baseDeposit = 0;
+ int m_totalDeposit = 0;
};
+inline std::ostream& operator<<(std::ostream& _out, Assembly const& _a)
+{
+ _a.streamOut(_out);
+ return _out;
+}
+
}