mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[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:
parent
7b7c88ae95
commit
785f65d0f5
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::phaser;
|
using namespace solidity::phaser;
|
||||||
|
|
||||||
namespace solidity::phaser
|
namespace solidity::phaser
|
||||||
@ -48,25 +49,25 @@ ostream& phaser::operator<<(ostream& _stream, Individual const& _individual)
|
|||||||
return _stream;
|
return _stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
Population::Population(string const& _sourcePath, vector<Chromosome> const& _chromosomes):
|
Population::Population(CharStream _sourceCode, vector<Chromosome> const& _chromosomes):
|
||||||
m_sourcePath{_sourcePath}
|
m_sourceCode{move(_sourceCode)}
|
||||||
{
|
{
|
||||||
for (auto const& chromosome: _chromosomes)
|
for (auto const& chromosome: _chromosomes)
|
||||||
m_individuals.push_back({chromosome});
|
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;
|
vector<Individual> individuals;
|
||||||
for (size_t i = 0; i < _size; ++i)
|
for (size_t i = 0; i < _size; ++i)
|
||||||
individuals.push_back({Chromosome::makeRandom(randomChromosomeLength())});
|
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());
|
program.optimise(_chromosome.optimisationSteps());
|
||||||
return program.codeSize();
|
return program.codeSize();
|
||||||
}
|
}
|
||||||
@ -87,7 +88,7 @@ void Population::run(optional<size_t> _numRounds, ostream& _outputStream)
|
|||||||
|
|
||||||
ostream& phaser::operator<<(ostream& _stream, Population const& _population)
|
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();
|
auto individual = _population.m_individuals.begin();
|
||||||
for (; individual != _population.m_individuals.end(); ++individual)
|
for (; individual != _population.m_individuals.end(); ++individual)
|
||||||
@ -105,7 +106,7 @@ void Population::doEvaluation()
|
|||||||
{
|
{
|
||||||
for (auto& individual: m_individuals)
|
for (auto& individual: m_individuals)
|
||||||
if (!individual.fitness.has_value())
|
if (!individual.fitness.has_value())
|
||||||
individual.fitness = measureFitness(individual.chromosome, m_sourcePath);
|
individual.fitness = measureFitness(individual.chromosome, m_sourceCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Population::doSelection()
|
void Population::doSelection()
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include <tools/yulPhaser/Chromosome.h>
|
#include <tools/yulPhaser/Chromosome.h>
|
||||||
#include <tools/yulPhaser/Random.h>
|
#include <tools/yulPhaser/Random.h>
|
||||||
|
|
||||||
|
#include <liblangutil/CharStream.h>
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -53,21 +55,21 @@ class Population
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t MaxChromosomeLength = 30;
|
static constexpr size_t MaxChromosomeLength = 30;
|
||||||
|
|
||||||
explicit Population(std::string const& _sourcePath, std::vector<Chromosome> const& _chromosomes = {});
|
explicit Population(langutil::CharStream _sourceCode, std::vector<Chromosome> const& _chromosomes = {});
|
||||||
static Population makeRandom(std::string const& _sourcePath, size_t _size);
|
static Population makeRandom(langutil::CharStream _sourceCode, size_t _size);
|
||||||
|
|
||||||
void run(std::optional<size_t> _numRounds, std::ostream& _outputStream);
|
void run(std::optional<size_t> _numRounds, std::ostream& _outputStream);
|
||||||
|
|
||||||
std::vector<Individual> const& individuals() const { return m_individuals; }
|
std::vector<Individual> const& individuals() const { return m_individuals; }
|
||||||
|
|
||||||
static size_t randomChromosomeLength() { return binomialRandomInt(MaxChromosomeLength, 0.5); }
|
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);
|
friend std::ostream& operator<<(std::ostream& _stream, Population const& _population);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Population(std::string const& _sourcePath, std::vector<Individual> _individuals = {}):
|
explicit Population(langutil::CharStream _sourceCode, std::vector<Individual> _individuals = {}):
|
||||||
m_sourcePath{_sourcePath},
|
m_sourceCode{std::move(_sourceCode)},
|
||||||
m_individuals{std::move(_individuals)} {}
|
m_individuals{std::move(_individuals)} {}
|
||||||
|
|
||||||
void doMutation();
|
void doMutation();
|
||||||
@ -79,7 +81,7 @@ private:
|
|||||||
size_t _count
|
size_t _count
|
||||||
);
|
);
|
||||||
|
|
||||||
std::string m_sourcePath;
|
langutil::CharStream m_sourceCode;
|
||||||
|
|
||||||
std::vector<Individual> m_individuals;
|
std::vector<Individual> m_individuals;
|
||||||
};
|
};
|
||||||
|
@ -38,11 +38,8 @@
|
|||||||
#include <libyul/optimiser/OptimiserStep.h>
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
#include <libyul/optimiser/Suite.h>
|
#include <libyul/optimiser/Suite.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonIO.h>
|
|
||||||
#include <libsolutil/JSON.h>
|
#include <libsolutil/JSON.h>
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <memory>
|
#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{});
|
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);
|
unique_ptr<AsmAnalysisInfo> analysisInfo = analyzeAST(dialect, *ast);
|
||||||
|
|
||||||
Program program(
|
Program program(
|
||||||
@ -95,14 +93,6 @@ string Program::toJson() const
|
|||||||
return jsonPrettyPrint(serializedAst);
|
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)
|
unique_ptr<Block> Program::parseSource(Dialect const& _dialect, CharStream _source)
|
||||||
{
|
{
|
||||||
ErrorList errors;
|
ErrorList errors;
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
{}
|
{}
|
||||||
Program operator=(Program&& program) = delete;
|
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);
|
void optimise(std::vector<std::string> const& _optimisationSteps);
|
||||||
|
|
||||||
size_t codeSize() const { return computeCodeSize(*m_ast); }
|
size_t codeSize() const { return computeCodeSize(*m_ast); }
|
||||||
@ -84,7 +84,6 @@ private:
|
|||||||
m_nameDispenser(_dialect, *m_ast, {})
|
m_nameDispenser(_dialect, *m_ast, {})
|
||||||
{}
|
{}
|
||||||
|
|
||||||
static langutil::CharStream loadSource(std::string const& _sourcePath);
|
|
||||||
static std::unique_ptr<yul::Block> parseSource(
|
static std::unique_ptr<yul::Block> parseSource(
|
||||||
yul::Dialect const& _dialect,
|
yul::Dialect const& _dialect,
|
||||||
langutil::CharStream _source
|
langutil::CharStream _source
|
||||||
|
@ -18,13 +18,20 @@
|
|||||||
#include <tools/yulPhaser/Exceptions.h>
|
#include <tools/yulPhaser/Exceptions.h>
|
||||||
#include <tools/yulPhaser/Population.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 <boost/program_options.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::phaser;
|
using namespace solidity::phaser;
|
||||||
|
using namespace solidity::util;
|
||||||
|
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
@ -37,9 +44,17 @@ struct CommandLineParsingResult
|
|||||||
po::variables_map arguments;
|
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)
|
void runAlgorithm(string const& _sourcePath)
|
||||||
{
|
{
|
||||||
auto population = Population::makeRandom(_sourcePath, 10);
|
auto population = Population::makeRandom(loadSource(_sourcePath), 10);
|
||||||
population.run(nullopt, cout);
|
population.run(nullopt, cout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user