Skip to content

Commit

Permalink
Improve "insert" code to avoid recursive calls
Browse files Browse the repository at this point in the history
Reduce the possibility of recursive insertions and put a maximum
acceptable value to make sure the code won't go endless.

Signed-off-by: Jose Ricardo Ziviani <[email protected]>
  • Loading branch information
jrziviani committed Jan 19, 2019
1 parent dda134b commit a46fea0
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 8 deletions.
1 change: 1 addition & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
constexpr size_t MAX_STRING_LEN = 256;
constexpr size_t MAX_VAR_LEN = 32;
constexpr size_t MAX_READ_SZ = 4096;
constexpr size_t MAX_ITERATION = 100;
constexpr char TAG_OPEN = '{';
constexpr char TAG_ECHO = '=';
constexpr char TAG_CODE = '%';
Expand Down
1 change: 1 addition & 0 deletions include/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace volt
size_t start;
size_t end;
size_t resume;
size_t iterations;
};

class compiler
Expand Down
1 change: 1 addition & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
constexpr size_t MAX_STRING_LEN = 256;
constexpr size_t MAX_VAR_LEN = 32;
constexpr size_t MAX_READ_SZ = 4096;
constexpr size_t MAX_ITERATION = 100;
constexpr char TAG_OPEN = '{';
constexpr char TAG_ECHO = '=';
constexpr char TAG_CODE = '%';
Expand Down
16 changes: 14 additions & 2 deletions include/metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace volt

struct metadata
{
size_t hash_tokens = 0;
size_t hash_tokens;
metatype type;
metarange range;
std::string data;
Expand All @@ -41,14 +41,20 @@ namespace volt

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

public:
typedef metadata value_type;

metainfo() :
hash_metadata(0)
{
}

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

void push_back(const metadata &data);
metadata &back();
Expand All @@ -65,6 +71,12 @@ namespace volt
std::vector<metadata>::const_iterator end() const noexcept;
};

inline void metainfo::rehash()
{
for (const auto &tk : metadata_) {
hash_metadata += tk.hash_tokens;
}
}

inline void metainfo::remove(size_t idx)
{
Expand Down
1 change: 1 addition & 0 deletions include/scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace volt

inline metainfo &scan::get_metainfo()
{
metainfo_.rehash();
return metainfo_;
}

Expand Down
36 changes: 30 additions & 6 deletions src/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,18 @@ namespace volt
// put user data in the environment table
context_.environment_setup(usermap);

cache_[metainfo.hash()] = block_cache{counter - 1,
metainfo.size() - 1,
0, 1};

// program main loop
for (; counter < metainfo.size(); context_.jump_to(counter + 1)) {

// if we're finished running a cached code, go back to the
// place where the cache was executed
if (running_cache_ && cache_[current_cache_].end == counter) {
context_.jump_to(cache_[current_cache_].resume);
running_cache_ = false;
continue;
}

Expand Down Expand Up @@ -241,6 +248,12 @@ namespace volt
range.emplace_back(start);
}

// cannot pass the max number of configured iterations
if (range.size() / step > MAX_ITERATION) {
branches_.push_back(branch{token_types::FOR, false});
return true;
}

context_.environment_add_or_update(string("range" + id_or_key), range);
context_.environment_add_or_update(id_or_key, range.at(0));
context_.stack_push(object_t(string("range" + id_or_key)));
Expand All @@ -263,7 +276,8 @@ namespace volt
return false;
}

if (context_.environment_get_size(vect) == 0) {
if (context_.environment_get_size(vect) == 0 ||
context_.environment_get_size(vect) > MAX_ITERATION) {
branches_.push_back(branch{token_types::FOR, false});
return true;
}
Expand All @@ -290,7 +304,8 @@ namespace volt
return false;
}

if (context_.environment_get_size(tbl) == 0) {
if (context_.environment_get_size(tbl) == 0 ||
context_.environment_get_size(tbl) > MAX_ITERATION) {
branches_.push_back(branch{token_types::FOR, false});
return true;
}
Expand Down Expand Up @@ -486,17 +501,18 @@ namespace volt
return false;
}

// TODO: check loop
scan insert_scan(error_);
insert_scan.do_scan(read_full(filename));
metainfo &new_info = insert_scan.get_metainfo();

auto cache_it = cache_.find(new_info.hash());

// the block inserted isn't cached: cache it, put the content in
// the current program and execute it
if (cache_it == cache_.end()) {
cache_[new_info.hash()] = block_cache{context_.get_counter() - 1,
new_info.size(),
0};

0, 1};
size_t new_size = new_info.size();
copy(info.begin() + context_.get_counter() + 1,
info.end(),
Expand All @@ -509,10 +525,18 @@ namespace volt
// restart the block execution
context_.jump_to(context_.get_counter() - 1);
}

// the block is cached: execute it
else {
// remote the "insert" code...
// remove the "insert" code...
info.remove(context_.get_counter());

if (++cache_it->second.iterations > MAX_ITERATION) {
error_.log(filename, "has run for more than",
MAX_ITERATION, ", cannot execute it");
return true;
}

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

0 comments on commit a46fea0

Please sign in to comment.