aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-11-22 01:43:37 +0800
committerGitHub <noreply@github.com>2018-11-22 01:43:37 +0800
commitd47707abaddfd6820d8ff1f9ec5ec0d2a61ee622 (patch)
treebcaaeebc62d127277057ec4cac8555870a9d881b
parent10a2e5d100e36b2c031faab35ddd956545d07536 (diff)
parent7c051f1e321a406c1a57870f75106151ad70047b (diff)
downloaddexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar.gz
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar.bz2
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar.lz
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar.xz
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.tar.zst
dexon-solidity-d47707abaddfd6820d8ff1f9ec5ec0d2a61ee622.zip
Merge pull request #2520 from ethereum/lll-with
LLL: implement the UNSET and WITH keywords
-rw-r--r--liblll/CodeFragment.cpp39
-rw-r--r--test/liblll/EndToEndTest.cpp13
2 files changed, 52 insertions, 0 deletions
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index f37cb8b9..b32f14e9 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -259,6 +259,7 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
}
else if (us == "SET")
{
+ // TODO: move this to be a stack variable (and not a memory variable)
if (_t.size() != 3)
error<IncorrectParameterCount>(us);
int c = 0;
@@ -268,6 +269,15 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append((u256)varAddress(firstAsString(), true));
m_asm.append(Instruction::MSTORE);
}
+ else if (us == "UNSET")
+ {
+ // TODO: this doesn't actually free up anything, since it is a memory variable (see "SET")
+ if (_t.size() != 2)
+ error<IncorrectParameterCount>();
+ auto it = _s.vars.find(firstAsString());
+ if (it != _s.vars.end())
+ _s.vars.erase(it);
+ }
else if (us == "GET")
{
if (_t.size() != 2)
@@ -275,6 +285,35 @@ void CodeFragment::constructOperation(sp::utree const& _t, CompilerState& _s)
m_asm.append((u256)varAddress(firstAsString()));
m_asm.append(Instruction::MLOAD);
}
+ else if (us == "WITH")
+ {
+ if (_t.size() != 4)
+ error<IncorrectParameterCount>();
+ string key = firstAsString();
+ if (_s.vars.find(key) != _s.vars.end())
+ error<InvalidName>(string("Symbol already used: ") + key);
+
+ // Create variable
+ // TODO: move this to be a stack variable (and not a memory variable)
+ size_t c = 0;
+ for (auto const& i: _t)
+ if (c++ == 2)
+ m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm);
+ m_asm.append((u256)varAddress(key, true));
+ m_asm.append(Instruction::MSTORE);
+
+ // Insert sub with variable access, but new state
+ CompilerState ns = _s;
+ c = 0;
+ for (auto const& i: _t)
+ if (c++ == 3)
+ m_asm.append(CodeFragment(i, _s, m_readFile, false).m_asm);
+
+ // Remove variable
+ auto it = _s.vars.find(key);
+ if (it != _s.vars.end())
+ _s.vars.erase(it);
+ }
else if (us == "REF")
m_asm.append((u256)varAddress(firstAsString()));
else if (us == "DEF")
diff --git a/test/liblll/EndToEndTest.cpp b/test/liblll/EndToEndTest.cpp
index 60aef7b0..aad89b91 100644
--- a/test/liblll/EndToEndTest.cpp
+++ b/test/liblll/EndToEndTest.cpp
@@ -109,6 +109,19 @@ BOOST_AUTO_TEST_CASE(variables)
BOOST_CHECK(callFallback() == encodeArgs(u256(488)));
}
+BOOST_AUTO_TEST_CASE(with)
+{
+ char const* sourceCode = R"(
+ (returnlll
+ (seq
+ (set 'x 11)
+ (with 'y 22 { [0]:(+ (get 'x) (get 'y)) })
+ (return 0 32)))
+ )";
+ compileAndRun(sourceCode);
+ BOOST_CHECK(callFallback() == toBigEndian(u256(33)));
+}
+
BOOST_AUTO_TEST_CASE(when)
{
char const* sourceCode = R"(