From a344381d5e3a720e01e89bb4d9fb7d1d57e87d92 Mon Sep 17 00:00:00 2001
From: chriseth <chris@ethereum.org>
Date: Wed, 13 Feb 2019 12:21:53 +0100
Subject: [PATCH] Provide access to AssemblyStack's AST.

---
 libyul/AssemblyStack.cpp         |  8 +++++++
 libyul/AssemblyStack.h           |  3 +++
 test/libyul/Common.cpp           | 35 +++++++------------------------
 test/libyul/YulOptimizerTest.cpp | 36 ++++++++++----------------------
 4 files changed, 30 insertions(+), 52 deletions(-)

diff --git a/libyul/AssemblyStack.cpp b/libyul/AssemblyStack.cpp
index 0b5cc2ffb..192812f20 100644
--- a/libyul/AssemblyStack.cpp
+++ b/libyul/AssemblyStack.cpp
@@ -178,3 +178,11 @@ string AssemblyStack::print() const
 	solAssert(m_parserResult->code, "");
 	return m_parserResult->toString(m_language == Language::Yul) + "\n";
 }
+
+shared_ptr<Object> AssemblyStack::parserResult() const
+{
+	solAssert(m_analysisSuccessful, "Analysis was not successful.");
+	solAssert(m_parserResult, "");
+	solAssert(m_parserResult->code, "");
+	return m_parserResult;
+}
diff --git a/libyul/AssemblyStack.h b/libyul/AssemblyStack.h
index c79eb46f7..563ecb431 100644
--- a/libyul/AssemblyStack.h
+++ b/libyul/AssemblyStack.h
@@ -82,6 +82,9 @@ public:
 	/// Pretty-print the input after having parsed it.
 	std::string print() const;
 
+	/// Return the parsed and analyzed object.
+	std::shared_ptr<Object> parserResult() const;
+
 private:
 	bool analyzeParsed();
 	bool analyzeParsed(yul::Object& _object);
diff --git a/test/libyul/Common.cpp b/test/libyul/Common.cpp
index ea4d0208f..f9cd6420c 100644
--- a/test/libyul/Common.cpp
+++ b/test/libyul/Common.cpp
@@ -29,6 +29,7 @@
 #include <libyul/AsmParser.h>
 #include <libyul/AsmAnalysis.h>
 #include <libyul/AsmPrinter.h>
+#include <libyul/AssemblyStack.h>
 #include <libyul/backends/evm/EVMDialect.h>
 
 #include <liblangutil/Scanner.h>
@@ -63,33 +64,13 @@ void yul::test::printErrors(ErrorList const& _errors)
 
 pair<shared_ptr<Block>, shared_ptr<yul::AsmAnalysisInfo>> yul::test::parse(string const& _source, bool _yul)
 {
-	shared_ptr<Dialect> dialect = defaultDialect(_yul);
-	ErrorList errors;
-	ErrorReporter errorReporter(errors);
-	auto scanner = make_shared<Scanner>(CharStream(_source, ""));
-	auto parserResult = yul::Parser(errorReporter, dialect).parse(scanner, false);
-	if (parserResult)
-	{
-		BOOST_REQUIRE(errorReporter.errors().empty());
-		auto analysisInfo = make_shared<yul::AsmAnalysisInfo>();
-		yul::AsmAnalyzer analyzer(
-			*analysisInfo,
-			errorReporter,
-			dev::test::Options::get().evmVersion(),
-			boost::none,
-			dialect
-		);
-		if (analyzer.analyze(*parserResult))
-		{
-			BOOST_REQUIRE(errorReporter.errors().empty());
-			return make_pair(parserResult, analysisInfo);
-		}
-	}
-	printErrors(errors);
-	BOOST_FAIL("Invalid source.");
-
-	// Unreachable.
-	return {};
+	AssemblyStack stack(
+		dev::test::Options::get().evmVersion(),
+		_yul ? AssemblyStack::Language::Yul : AssemblyStack::Language::StrictAssembly
+	);
+	if (!stack.parseAndAnalyze("", _source) || !stack.errors().empty())
+		BOOST_FAIL("Invalid source.");
+	return make_pair(stack.parserResult()->code, stack.parserResult()->analysisInfo);
 }
 
 yul::Block yul::test::disambiguate(string const& _source, bool _yul)
diff --git a/test/libyul/YulOptimizerTest.cpp b/test/libyul/YulOptimizerTest.cpp
index d48687b9a..c12121369 100644
--- a/test/libyul/YulOptimizerTest.cpp
+++ b/test/libyul/YulOptimizerTest.cpp
@@ -46,6 +46,7 @@
 #include <libyul/AsmPrinter.h>
 #include <libyul/AsmParser.h>
 #include <libyul/AsmAnalysis.h>
+#include <libyul/AssemblyStack.h>
 #include <liblangutil/SourceReferenceFormatter.h>
 
 #include <liblangutil/ErrorReporter.h>
@@ -97,9 +98,6 @@ YulOptimizerTest::YulOptimizerTest(string const& _filename)
 
 bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool const _formatted)
 {
-	yul::AsmPrinter printer{m_yul};
-	shared_ptr<Block> ast;
-	shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
 	if (!parse(_stream, _linePrefix, _formatted))
 		return false;
 
@@ -257,7 +255,7 @@ bool YulOptimizerTest::run(ostream& _stream, string const& _linePrefix, bool con
 		return false;
 	}
 
-	m_obtainedResult = m_optimizerStep + "\n" + printer(*m_ast) + "\n";
+	m_obtainedResult = m_optimizerStep + "\n" + AsmPrinter{m_yul}(*m_ast) + "\n";
 
 	if (m_expectation != m_obtainedResult)
 	{
@@ -292,31 +290,19 @@ void YulOptimizerTest::printIndented(ostream& _stream, string const& _output, st
 
 bool YulOptimizerTest::parse(ostream& _stream, string const& _linePrefix, bool const _formatted)
 {
-	m_dialect = m_yul ? yul::Dialect::yul() : yul::EVMDialect::strictAssemblyForEVMObjects();
-	ErrorList errors;
-	ErrorReporter errorReporter(errors);
-	shared_ptr<Scanner> scanner = make_shared<Scanner>(CharStream(m_source, ""));
-	m_ast = yul::Parser(errorReporter, m_dialect).parse(scanner, false);
-	if (!m_ast || !errorReporter.errors().empty())
+	AssemblyStack stack(
+		dev::test::Options::get().evmVersion(),
+		m_yul ? AssemblyStack::Language::Yul : AssemblyStack::Language::StrictAssembly
+	);
+	if (!stack.parseAndAnalyze("", m_source) || !stack.errors().empty())
 	{
 		AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error parsing source." << endl;
-		printErrors(_stream, errorReporter.errors());
-		return false;
-	}
-	m_analysisInfo = make_shared<yul::AsmAnalysisInfo>();
-	yul::AsmAnalyzer analyzer(
-		*m_analysisInfo,
-		errorReporter,
-		dev::test::Options::get().evmVersion(),
-		boost::none,
-		m_dialect
-	);
-	if (!analyzer.analyze(*m_ast) || !errorReporter.errors().empty())
-	{
-		AnsiColorized(_stream, _formatted, {formatting::BOLD, formatting::RED}) << _linePrefix << "Error analyzing source." << endl;
-		printErrors(_stream, errorReporter.errors());
+		printErrors(_stream, stack.errors());
 		return false;
 	}
+	m_dialect = m_yul ? Dialect::yul() : EVMDialect::strictAssemblyForEVMObjects();
+	m_ast = stack.parserResult()->code;
+	m_analysisInfo = stack.parserResult()->analysisInfo;
 	return true;
 }