aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--liblll/CodeFragment.cpp29
-rw-r--r--test/liblll/EndToEndTest.cpp13
2 files changed, 42 insertions, 0 deletions
diff --git a/liblll/CodeFragment.cpp b/liblll/CodeFragment.cpp
index c6ab86f5..b32f14e9 100644
--- a/liblll/CodeFragment.cpp
+++ b/liblll/CodeFragment.cpp
@@ -285,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"(