101 lines
2.6 KiB
C++
101 lines
2.6 KiB
C++
#include "scope.h"
|
|
#include "variables.h"
|
|
#include "types.h"
|
|
#include <vector>
|
|
#include <stack>
|
|
|
|
struct t_scope {
|
|
std::vector<t_variable> variables;
|
|
int total_size;
|
|
};
|
|
|
|
static t_scope global;
|
|
static t_scope local;
|
|
static std::stack<int> blocks;
|
|
static bool are_we_inside_local = false;
|
|
static t_variable *current_var = NULL;
|
|
|
|
void scope_init() {
|
|
global.variables.clear();
|
|
global.total_size = 0;
|
|
local.variables.clear();
|
|
local.total_size = 0;
|
|
while (!blocks.empty()) blocks.pop();
|
|
are_we_inside_local = false;
|
|
}
|
|
|
|
const bool scope_is_local() {
|
|
return are_we_inside_local;
|
|
}
|
|
|
|
void scope_open_local() {
|
|
are_we_inside_local = true;
|
|
blocks.push(0);
|
|
}
|
|
|
|
const int scope_close_local() {
|
|
if (!blocks.empty()) {
|
|
// Malament, no havem tancat algún block. No se si es detectarà abans per altra part. Per ara anem a deixar este comentari.
|
|
}
|
|
const int return_value = local.total_size;
|
|
while (!blocks.empty()) blocks.pop();
|
|
local.variables.clear();
|
|
local.total_size = 0;
|
|
are_we_inside_local = false;
|
|
return return_value;
|
|
}
|
|
|
|
void scope_open_block() {
|
|
blocks.push(local.variables.size());
|
|
}
|
|
|
|
void scope_close_block() {
|
|
const int size_before_block = blocks.top();
|
|
blocks.pop();
|
|
while (local.variables.size() > size_before_block) local.variables.pop_back();
|
|
}
|
|
|
|
const int scope_declare_variable(const std::string name, const uint32_t type, const uint32_t length) {
|
|
t_scope& scope = (are_we_inside_local ? local : global);
|
|
if (are_we_inside_local) {
|
|
for (int i = blocks.top(); i < scope.variables.size(); i++ ) if (scope.variables[i].name == name) return -1;
|
|
} else {
|
|
for (t_variable v : scope.variables) if (v.name == name) return -1;
|
|
}
|
|
const uint32_t address = scope.total_size;
|
|
const t_variable var {name, type, length, address};
|
|
scope.variables.push_back(var);
|
|
scope.total_size += types_get_length(type) + (length == 0 ? 1 : length);
|
|
return address;
|
|
}
|
|
|
|
const bool scope_variable_exists(const std::string name) {
|
|
t_scope& scope = (are_we_inside_local ? local : global);
|
|
for (t_variable v : scope.variables) if (v.name == name) {
|
|
current_var = &v;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const uint32_t scope_get_variable_address() {
|
|
if (current_var == NULL) {
|
|
// ERROR INTERN
|
|
}
|
|
return current_var->address;
|
|
}
|
|
|
|
const int scope_get_variable_size() {
|
|
if (current_var == NULL) {
|
|
// ERROR INTERN
|
|
}
|
|
return current_var->length;
|
|
}
|
|
|
|
const int scope_get_variable_type() {
|
|
if (current_var == NULL) {
|
|
// ERROR INTERN
|
|
}
|
|
return current_var->type;
|
|
}
|