Skip to content

Commit

Permalink
Add a cache for repetitive blocks
Browse files Browse the repository at this point in the history
Inserting an external file more than once is handled by cache instead of
adding each block in the resulting code.

Signed-off-by: Jose Ricardo Ziviani <[email protected]>
  • Loading branch information
jrziviani committed Jan 18, 2019
1 parent 9660d97 commit dda134b
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 26 deletions.
11 changes: 11 additions & 0 deletions include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <vector>
#include <string>
#include <functional>
#include <unordered_map>

namespace volt
{
Expand All @@ -19,11 +20,21 @@ namespace volt
bool taken;
};

struct block_cache
{
size_t start;
size_t end;
size_t resume;
};

class compiler
{
error &error_;
bool running_cache_;
size_t current_cache_;
context context_;
std::vector<branch> branches_;
std::unordered_map<size_t, block_cache> cache_;
std::function<void(const context &,
const std::vector<branch> &)> inspect_;

Expand Down
111 changes: 111 additions & 0 deletions include/metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,122 @@ namespace volt

struct metadata
{
size_t hash_tokens = 0;
metatype type;
metarange range;
std::string data;
std::vector<token_t> tokens;

void add_token(const token_t &tk);
};

inline void metadata::add_token(const token_t &tk)
{
tokens.emplace_back(tk);
hash_tokens += tk.hash();
}

class metainfo
{
size_t hash_metadata = 0;
std::vector<metadata> metadata_;

public:
typedef metadata value_type;

void add_metadata(const metadata &data);
size_t hash() const;

void push_back(const metadata &data);
metadata &back();
void remove(size_t idx);
void clear();
size_t size() const;
void resize(size_t new_size);

const metadata &operator[](size_t idx) const;
std::vector<metadata> &operator=(std::vector<metadata> &&other) noexcept;
std::vector<metadata>::iterator begin() noexcept;
std::vector<metadata>::iterator end() noexcept;
std::vector<metadata>::const_iterator begin() const noexcept;
std::vector<metadata>::const_iterator end() const noexcept;
};


inline void metainfo::remove(size_t idx)
{
if (idx > metadata_.size()) {
return;
}

metadata_.erase(metadata_.begin() + idx);
}

inline size_t metainfo::hash() const
{
return hash_metadata;
}

inline void metainfo::push_back(const metadata &data)
{
add_metadata(data);
}

inline std::vector<metadata> &metainfo::operator=(std::vector<metadata> &&other) noexcept
{
return metadata_.operator=(other);
}

inline void metainfo::resize(size_t new_size)
{
metadata_.resize(new_size);
}

inline std::vector<metadata>::iterator metainfo::begin() noexcept
{
return metadata_.begin();
}

inline std::vector<metadata>::iterator metainfo::end() noexcept
{
return metadata_.end();
}

inline std::vector<metadata>::const_iterator metainfo::begin() const noexcept
{
return metadata_.begin();
}

inline std::vector<metadata>::const_iterator metainfo::end() const noexcept
{
return metadata_.end();
}

inline const metadata &metainfo::operator[](size_t idx) const
{
return metadata_[idx];
}

inline size_t metainfo::size() const
{
return metadata_.size();
}

inline metadata &metainfo::back()
{
return metadata_.back();
}

inline void metainfo::clear()
{
metadata_.clear();
}

inline void metainfo::add_metadata(const metadata &data)
{
metadata_.emplace_back(data);
hash_metadata += data.hash_tokens;
}
}

#endif // METADATA_H
9 changes: 9 additions & 0 deletions include/token.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <string>
#include <optional>
#include <functional>

#define TOKENS \
X(IDENTIFIER) \
Expand Down Expand Up @@ -140,8 +141,16 @@ namespace volt
std::string to_string() const;
token_types type() const;
value_t value() const;

size_t hash() const;
};

inline size_t token_t::hash() const
{
std::hash<std::string> hash_string;
return hash_string(to_string());
}

inline std::string token_t::to_string() const
{
std::string ret = "token: " + get_token_name(type_) +
Expand Down
1 change: 0 additions & 1 deletion include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace volt
{
using metainfo = std::vector<metadata>;
using tokens = std::vector<token_t>;

using user_var = std::variant<number_t,
Expand Down
54 changes: 36 additions & 18 deletions src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ using namespace std;
namespace volt
{
compiler::compiler(error &err) :
error_(err)
error_(err),
running_cache_(false),
current_cache_(0)
{
}

Expand All @@ -24,6 +26,11 @@ namespace volt
// program main loop
for (; counter < metainfo.size(); context_.jump_to(counter + 1)) {

if (running_cache_ && cache_[current_cache_].end == counter) {
context_.jump_to(cache_[current_cache_].resume);
continue;
}

// text isn't processed so it only verify if the branch it
// belongs to has been taken and print it
if (metainfo[counter].type == metatype::TEXT) {
Expand Down Expand Up @@ -484,24 +491,35 @@ namespace volt
insert_scan.do_scan(read_full(filename));
metainfo &new_info = insert_scan.get_metainfo();

size_t new_size = new_info.size();
copy(info.begin() + context_.get_counter() + 1,
info.end(),
back_inserter(new_info));
info.resize(info.size() + new_size);
copy(new_info.begin(),
new_info.end(),
info.begin() + context_.get_counter());

/*
info.resize(info.size() + new_info.size() + 10);
size_t i = context_.get_counter();
for (const auto data : new_info) {
info[i++] = data;
}*/
auto cache_it = cache_.find(new_info.hash());
if (cache_it == cache_.end()) {
cache_[new_info.hash()] = block_cache{context_.get_counter() - 1,
new_info.size(),
0};

// restart the block execution
context_.jump_to(context_.get_counter() - 1);
size_t new_size = new_info.size();
copy(info.begin() + context_.get_counter() + 1,
info.end(),
back_inserter(new_info));
info.resize(info.size() + new_size);
copy(new_info.begin(),
new_info.end(),
info.begin() + context_.get_counter());

// restart the block execution
context_.jump_to(context_.get_counter() - 1);
}
else {
// remote the "insert" code...
info.remove(context_.get_counter());

// ...and execute the cached code
cache_it->second.resume = context_.get_counter() - 1;
context_.jump_to(cache_it->second.start);

running_cache_ = true;
current_cache_ = cache_it->first;
}

return true;
}
Expand Down
16 changes: 9 additions & 7 deletions src/scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ namespace volt
mtdt = text_block(content, i, false);
}

metainfo_.emplace_back(mtdt);
metainfo_.add_metadata(mtdt);

// text blocks don't require special treatment
if (mtdt.type == metatype::TEXT) {
continue;
}

// on the other hand, code blocks is scanned and
// tokenized into metainfo_
// tokenized into metainfo
// NOTE: code block will be reverted to text block
// if it finds any issue during this phase
scan_iterator it(mtdt.data);
Expand All @@ -63,6 +63,7 @@ namespace volt
// IMPORTANT: empty space between opening and closing tags

metadata metadata = {
0,
metatype::CODE,
{position, position},
"",
Expand Down Expand Up @@ -166,6 +167,7 @@ namespace volt
bool force)
{
metadata metadata = {
0,
metatype::TEXT,
{position, position},
"",
Expand Down Expand Up @@ -224,7 +226,7 @@ namespace volt
switch(token) {

#define X(tk, name) case tk: \
data.tokens.emplace_back(token_t(token_types::name)); \
data.add_token(token_t(token_types::name)); \
it.next(); \
break;
SINGLE_TOKEN
Expand Down Expand Up @@ -285,7 +287,7 @@ namespace volt
}

string str = (len == 0) ? "" : it.substr(start, len);
data.tokens.emplace_back(token_t(token_types::STRING, str));
data.add_token(token_t(token_types::STRING, str));
}

void scan::parse_number(const scan_iterator &it, metadata &data)
Expand All @@ -305,7 +307,7 @@ namespace volt
number = number * 10 + digit;
}

data.tokens.emplace_back(token_t(token_types::NUMBER,
data.add_token(token_t(token_types::NUMBER,
to_string(number)));
}

Expand All @@ -328,10 +330,10 @@ namespace volt

const string &text = it.substr(start, len);
if (keywords_.find(text) != keywords_.end()) {
data.tokens.emplace_back(token_t(keywords_[text]));
data.add_token(token_t(keywords_[text]));
}
else {
data.tokens.emplace_back(token_t(token_types::IDENTIFIER, text));
data.add_token(token_t(token_types::IDENTIFIER, text));
}
}
}

0 comments on commit dda134b

Please sign in to comment.