diff options
-rw-r--r-- | liblll/CodeFragment.cpp | 29 | ||||
-rw-r--r-- | test/liblll/EndToEndTest.cpp | 13 |
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"( |