[yul-phaser] Make Program copyable by doing a deep copy of the AST in the copy constructor

This commit is contained in:
cameel 2020-01-31 13:23:57 +01:00 committed by Kamil Śliwak
parent a189c8b6e2
commit 57fb64d467
3 changed files with 30 additions and 3 deletions

View File

@ -65,6 +65,26 @@ namespace solidity::phaser::test
BOOST_AUTO_TEST_SUITE(Phaser)
BOOST_AUTO_TEST_SUITE(ProgramTest)
BOOST_AUTO_TEST_CASE(copy_constructor_should_make_deep_copy_of_ast)
{
string sourceCode(
"{\n"
" let x := 1\n"
"}\n"
);
CharStream sourceStream(sourceCode, current_test_case().p_name);
auto program = Program::load(sourceStream);
Program programCopy(program);
BOOST_TEST(&programCopy.ast() != &program.ast());
// There might be a more direct way to compare ASTs but converting to JSON should be good enough
// as long as the conversion is deterministic. A very nice side effect of doing it this way is
// that BOOST_TEST will print the complete AST structure of both programs in case of a mismatch.
BOOST_TEST(programCopy.toJson() == program.toJson());
}
BOOST_AUTO_TEST_CASE(load_should_rewind_the_stream)
{
string sourceCode(

View File

@ -57,6 +57,13 @@ ostream& operator<<(ostream& _stream, Program const& _program);
}
Program::Program(Program const& program):
m_ast(make_unique<Block>(get<Block>(ASTCopier{}(*program.m_ast)))),
m_dialect{program.m_dialect},
m_nameDispenser(program.m_nameDispenser)
{
}
Program Program::load(CharStream& _sourceCode)
{
// ASSUMPTION: parseSource() rewinds the stream on its own

View File

@ -20,8 +20,6 @@
#include <libyul/optimiser/NameDispenser.h>
#include <libyul/AsmData.h>
#include <boost/noncopyable.hpp>
#include <optional>
#include <ostream>
#include <set>
@ -55,14 +53,16 @@ namespace solidity::phaser
* The class allows the user to apply extra optimisations and obtain metrics and general
* information about the resulting syntax tree.
*/
class Program: private boost::noncopyable
class Program
{
public:
Program(Program const& program);
Program(Program&& program):
m_ast(std::move(program.m_ast)),
m_dialect{program.m_dialect},
m_nameDispenser(std::move(program.m_nameDispenser))
{}
Program operator=(Program const& program) = delete;
Program operator=(Program&& program) = delete;
static Program load(langutil::CharStream& _sourceCode);