[yul-phaser] Make Program and Population classes accept source code rather than file path

- I need some sample .yul files for testing but I see that existing tests generally have source code hard-coded in them rather than in standalone .yul files. There are lots of .yul files but they seem to be automatically processed by a special test case rather loaded ad-hoc by manually created tests.
- Program and Population required a file name until now. I'm making them accept loaded source code to be able to give them data hard-coded in a test.
This commit is contained in:
cameel 2020-01-22 20:14:36 +01:00
parent 7b7c88ae95
commit 785f65d0f5
5 changed files with 37 additions and 30 deletions

View File

@ -26,6 +26,7 @@
using namespace std;
using namespace solidity;
using namespace solidity::langutil;
using namespace solidity::phaser;
namespace solidity::phaser
@ -48,25 +49,25 @@ ostream& phaser::operator<<(ostream& _stream, Individual const& _individual)
return _stream;
}
Population::Population(string const& _sourcePath, vector<Chromosome> const& _chromosomes):
m_sourcePath{_sourcePath}
Population::Population(CharStream _sourceCode, vector<Chromosome> const& _chromosomes):
m_sourceCode{move(_sourceCode)}
{
for (auto const& chromosome: _chromosomes)
m_individuals.push_back({chromosome});
}
Population Population::makeRandom(string const& _sourcePath, size_t _size)
Population Population::makeRandom(CharStream _sourceCode, size_t _size)
{
vector<Individual> individuals;
for (size_t i = 0; i < _size; ++i)
individuals.push_back({Chromosome::makeRandom(randomChromosomeLength())});
return Population(_sourcePath, individuals);
return Population(move(_sourceCode), individuals);
}
size_t Population::measureFitness(Chromosome const& _chromosome, string const& _sourcePath)
size_t Population::measureFitness(Chromosome const& _chromosome, CharStream& _sourceCode)
{
auto program = Program::load(_sourcePath);
auto program = Program::load(_sourceCode);
program.optimise(_chromosome.optimisationSteps());
return program.codeSize();
}
@ -87,7 +88,7 @@ void Population::run(optional<size_t> _numRounds, ostream& _outputStream)
ostream& phaser::operator<<(ostream& _stream, Population const& _population)
{
_stream << "Source: " << _population.m_sourcePath << endl;
_stream << "Stream name: " << _population.m_sourceCode.name() << endl;
auto individual = _population.m_individuals.begin();
for (; individual != _population.m_individuals.end(); ++individual)
@ -105,7 +106,7 @@ void Population::doEvaluation()
{
for (auto& individual: m_individuals)
if (!individual.fitness.has_value())
individual.fitness = measureFitness(individual.chromosome, m_sourcePath);
individual.fitness = measureFitness(individual.chromosome, m_sourceCode);
}
void Population::doSelection()

View File

@ -20,6 +20,8 @@
#include <tools/yulPhaser/Chromosome.h>
#include <tools/yulPhaser/Random.h>
#include <liblangutil/CharStream.h>
#include <optional>
#include <ostream>
#include <vector>
@ -53,21 +55,21 @@ class Population
public:
static constexpr size_t MaxChromosomeLength = 30;
explicit Population(std::string const& _sourcePath, std::vector<Chromosome> const& _chromosomes = {});
static Population makeRandom(std::string const& _sourcePath, size_t _size);
explicit Population(langutil::CharStream _sourceCode, std::vector<Chromosome> const& _chromosomes = {});
static Population makeRandom(langutil::CharStream _sourceCode, size_t _size);
void run(std::optional<size_t> _numRounds, std::ostream& _outputStream);
std::vector<Individual> const& individuals() const { return m_individuals; }
static size_t randomChromosomeLength() { return binomialRandomInt(MaxChromosomeLength, 0.5); }
static size_t measureFitness(Chromosome const& _chromosome, std::string const& _sourcePath);
static size_t measureFitness(Chromosome const& _chromosome, langutil::CharStream& _sourceCode);
friend std::ostream& operator<<(std::ostream& _stream, Population const& _population);
private:
explicit Population(std::string const& _sourcePath, std::vector<Individual> _individuals = {}):
m_sourcePath{_sourcePath},
explicit Population(langutil::CharStream _sourceCode, std::vector<Individual> _individuals = {}):
m_sourceCode{std::move(_sourceCode)},
m_individuals{std::move(_individuals)} {}
void doMutation();
@ -79,7 +81,7 @@ private:
size_t _count
);
std::string m_sourcePath;
langutil::CharStream m_sourceCode;
std::vector<Individual> m_individuals;
};

View File

@ -38,11 +38,8 @@
#include <libyul/optimiser/OptimiserStep.h>
#include <libyul/optimiser/Suite.h>
#include <libsolutil/CommonIO.h>
#include <libsolutil/JSON.h>
#include <boost/filesystem.hpp>
#include <cassert>
#include <memory>
@ -60,10 +57,11 @@ ostream& operator<<(ostream& _stream, Program const& _program);
}
Program Program::load(string const& _sourcePath)
Program Program::load(CharStream& _sourceCode)
{
// ASSUMPTION: parseSource() rewinds the stream on its own
Dialect const& dialect = EVMDialect::strictAssemblyForEVMObjects(EVMVersion{});
unique_ptr<Block> ast = parseSource(dialect, loadSource(_sourcePath));
unique_ptr<Block> ast = parseSource(dialect, _sourceCode);
unique_ptr<AsmAnalysisInfo> analysisInfo = analyzeAST(dialect, *ast);
Program program(
@ -95,14 +93,6 @@ string Program::toJson() const
return jsonPrettyPrint(serializedAst);
}
CharStream Program::loadSource(string const& _sourcePath)
{
assertThrow(boost::filesystem::exists(_sourcePath), InvalidProgram, "Source file does not exist");
string sourceCode = readFileAsString(_sourcePath);
return CharStream(sourceCode, _sourcePath);
}
unique_ptr<Block> Program::parseSource(Dialect const& _dialect, CharStream _source)
{
ErrorList errors;

View File

@ -65,7 +65,7 @@ public:
{}
Program operator=(Program&& program) = delete;
static Program load(std::string const& _sourcePath);
static Program load(langutil::CharStream& _sourceCode);
void optimise(std::vector<std::string> const& _optimisationSteps);
size_t codeSize() const { return computeCodeSize(*m_ast); }
@ -84,7 +84,6 @@ private:
m_nameDispenser(_dialect, *m_ast, {})
{}
static langutil::CharStream loadSource(std::string const& _sourcePath);
static std::unique_ptr<yul::Block> parseSource(
yul::Dialect const& _dialect,
langutil::CharStream _source

View File

@ -18,13 +18,20 @@
#include <tools/yulPhaser/Exceptions.h>
#include <tools/yulPhaser/Population.h>
#include <libsolutil/Assertions.h>
#include <libsolutil/CommonIO.h>
#include <liblangutil/CharStream.h>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace solidity::langutil;
using namespace solidity::phaser;
using namespace solidity::util;
namespace po = boost::program_options;
@ -37,9 +44,17 @@ struct CommandLineParsingResult
po::variables_map arguments;
};
CharStream loadSource(string const& _sourcePath)
{
assertThrow(boost::filesystem::exists(_sourcePath), InvalidProgram, "Source file does not exist");
string sourceCode = readFileAsString(_sourcePath);
return CharStream(sourceCode, _sourcePath);
}
void runAlgorithm(string const& _sourcePath)
{
auto population = Population::makeRandom(_sourcePath, 10);
auto population = Population::makeRandom(loadSource(_sourcePath), 10);
population.run(nullopt, cout);
}