Skip to content

Commit

Permalink
Developed most of the features of the DynArray class while optimizing…
Browse files Browse the repository at this point in the history
… some of the code.
  • Loading branch information
ax-6 committed Mar 20, 2024
1 parent 2040a3b commit 601cfc4
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 28 deletions.
13 changes: 9 additions & 4 deletions compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ include_directories(${PROJECT_SOURCE_DIR})

set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/compiler.cc)

add_subdirectory(token)

add_subdirectory(lexer)
add_subdirectory(ast)
add_subdirectory(parser)
add_subdirectory(token)
add_subdirectory(ast)
add_subdirectory(dyn_array)
add_subdirectory(hash_map)

add_library(AqCompiler STATIC ${SOURCES})

target_link_libraries(AqCompiler PRIVATE AqCompilerToken)
target_link_libraries(AqCompiler PRIVATE AqCompilerLexer)
target_link_libraries(AqCompiler PRIVATE AqCompilerAst)
target_link_libraries(AqCompiler PRIVATE AqCompilerParser)
target_link_libraries(AqCompiler PRIVATE AqCompilerToken)
target_link_libraries(AqCompiler PRIVATE AqCompilerAst)
target_link_libraries(AqCompiler PRIVATE AqCompilerDynArray)
target_link_libraries(AqCompiler PRIVATE AqCompilerHashMap)
target_link_libraries(AqCompiler PRIVATE AqDebugger)
74 changes: 73 additions & 1 deletion compiler/dyn_array/dyn_array.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,76 @@

#include "compiler/dyn_array/dyn_array.h"

// TODO: Dynamic Array
#include <cstddef>

#include "debugger/debugger.h"

namespace Aq {
template <typename ArrayType, std::size_t InitCapacity>
Compiler::DynArray<ArrayType, InitCapacity>::DynArray() {
data_ = new ArrayType[InitCapacity];
if (data_ != nullptr) {
capacity_ = InitCapacity;
} else {
data_ = new ArrayType[1];
if (data_ != nullptr) {
Debugger warning_info(Debugger::Level::WARNING,
"Aq::Compiler::DynArray::DynArray",
"DynArray_InitWarning",
"InitCapacity out of memory occurred.", nullptr);
capacity_ = 1;
} else {
Debugger error_info(
Debugger::Level::ERROR, "Aq::Compiler::DynArray::DynArray",
"DynArray_InitError", "Size 1 out of memory occurred.", nullptr);
capacity_ = 0;
}
}
size_ = 0;
}

template <typename ArrayType, std::size_t InitCapacity>
Compiler::DynArray<ArrayType, InitCapacity>::~DynArray() {
delete[] data_;
}

template <typename ArrayType, std::size_t InitCapacity>
void Compiler::DynArray<ArrayType, InitCapacity>::PushBack(ArrayType data) {
if (capacity_ == 0 && Resize(1) == -1) {
return;
}
if (size_ > capacity_) {
Debugger error_info(
Debugger::Level::ERROR, "Aq::Compiler::DynArray::PushBack",
"PushBack_SizeError", "Size out of capacity occurred.", nullptr);
}
if (size_ == capacity_) {
Resize(capacity_ * 2);
}
data_[size_] = data;
size_++;
}

template <typename ArrayType, std::size_t InitCapacity>
int Compiler::DynArray<ArrayType, InitCapacity>::Resize(
std::size_t new_capacity) {
if (new_capacity == 0) {
capacity_ *= 2;
} else {
capacity_ = new_capacity;
}
ArrayType* new_data = new ArrayType[capacity_];
if (new_data == nullptr) {
Debugger error_info(Debugger::Level::ERROR,
"Aq::Compiler::DynArray::Resize", "Resize_ResizeError",
"New capacity out of memory occurred.", nullptr);
return -1;
}
for (std::size_t i = 0; i < size_ && i < capacity_; i++) {
new_data[i] = data_[i];
}
delete[] data_;
data_ = new_data;
return 0;
}
} // namespace Aq
25 changes: 22 additions & 3 deletions compiler/dyn_array/dyn_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
#include <cstddef>

#include "compiler/compiler.h"
#include "debugger/debugger.h"

namespace Aq {
template <typename ArrayType,std::size_t InitCapacity>
template <typename ArrayType, std::size_t InitCapacity>
class Compiler::DynArray {
public:
DynArray();
Expand All @@ -21,10 +22,28 @@ class Compiler::DynArray {
DynArray& operator=(const DynArray&) = default;
DynArray& operator=(DynArray&&) noexcept = default;

// TODO: Waiting for developing.
// Returns the data reference of the corresponding index.
ArrayType& operator[](std::size_t index) {
if (index >= size_) {
Debugger error_info(
Debugger::Level::ERROR, "Aq::Compiler::DynArray::operator[]",
"DynArray_IndexError", "Index out of range occurred.", nullptr);
}
return data_[index];
}

// Adds an element to the end of the container. No return value.
void PushBack(ArrayType data);

// Increase the container capacity.
// If |new_capacity| is 0, it is increased to 2 times |capacity_|. If
// greater than 0, the container capacity is increased to |new_capacity|.
// A return of 0 indicates a successful allocation, a return of -1 indicates
// an error in the allocation.
int Resize(std::size_t new_capacity = 0);

private:
ArrayType* array_;
ArrayType* data_;
std::size_t capacity_;
std::size_t size_;
};
Expand Down
176 changes: 171 additions & 5 deletions compiler/hash_map/hash_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,188 @@
#define AQ_COMPILER_HASH_MAP_HASH_MAP_H_

#include "compiler/compiler.h"

/*
namespace Aq {
template <typename ValueType>
class Compiler::HashMap {
public:
HashMap();
~HashMap();
HashMap() {
std::size_t init_capacity = 1024;
pair_list_ = new PairList[init_capacity];
if (!pair_list_) {
Debugger error_info(
Debugger::Level::ERROR, "Aq::Compiler::Lexer::HashMap::HashMap",
"HashMap_MemoryError", "Memory allocation failed.", nullptr);
pair_list_ = new PairList[1];
}
capacity_ = init_capacity;
};
~HashMap() { delete[] pair_list_; };
HashMap(const HashMap&) = default;
HashMap(HashMap&&) noexcept = default;
HashMap& operator=(const HashMap&) = default;
HashMap& operator=(HashMap&&) noexcept = default;
// Insert a new pair into the hash table.
void Insert(std::string key, T value) {
unsigned int hash = Hash(key);
// Increase the size of the hash table.
size_++;
if (size_ / capacity_ > 0.8) {
Resize();
}
// Create key-value pairs and insert them into the linked list.
Pair pair;
pair.key = key;
pair.value = value;
pair_list_[hash].Prepend(pair);
};
// Find the value of a key.
T Find(std::string key) {
unsigned int hash = Hash(key);
return pair_list_[hash].Find(key);
};
private:
// TODO: Hash Map
struct Pair {
std::string key;
T value;
};
// A linked list of Pair type, used to resolve hash conflicts.
class PairList {
public:
// Construct a PairList class.
PairList() = default;
~PairList() {
while (head_ptr_ != nullptr) {
Node* temp = head_ptr_;
head_ptr_ = head_ptr_->next;
delete temp;
}
};
PairList(const PairList&) = default;
PairList(PairList&&) noexcept = default;
PairList& operator=(const PairList&) = default;
PairList& operator=(PairList&&) noexcept = default;
// Prepend a new pair to the list.
void Prepend(Pair value) {
Node* new_node = new Node(value);
new_node->next = head_ptr_;
head_ptr_ = new_node;
};
// Copy all the data in the linked list to |new_list|.
void CopyDataToNewList(PairList* new_list, size_t new_capacity) {
PairList::Node* temp_node = head_ptr_;
while (temp_node != nullptr) {
unsigned int hash = 5381;
for (char character : temp_node->data.key) {
// hash = hash * 33 + static_cast<unsigned int>(character)
hash = ((hash << 5) + hash) + static_cast<unsigned int>(character);
}
hash = hash % new_capacity;
new_list[hash].Append(temp_node->data);
temp_node = temp_node->next;
}
};
// Append a new pair to the list. It is not recommended to use it when
// dealing with large amounts of data.
void Append(Pair value) {
if (head_ptr_ == nullptr) {
head_ptr_ = new Node(value);
} else {
// Find the last node and append the new node.
Node* temp = head_ptr_;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node(value);
}
};
// Find the value of a key.
T Find(std::string key) {
Node* temp = head_ptr_;
// Compare keys one by one to find the corresponding value.
while (temp != nullptr) {
if (key == temp->data.key) {
return temp->data.value;
};
temp = temp->next;
}
// Key not found, return nullptr.
return static_cast<T>(0);
};
private:
// A node type of the linked list.
struct Node {
Pair data;
Node* next = nullptr;
Node(Pair pair) : data(pair){};
};
// The head pointer of the linked list.
Node* head_ptr_ = nullptr;
};
// The memory size of the hash table.
std::size_t capacity_ = 1;
// The number of elements in the hash table.
std::size_t size_ = 0;
// The data collection of the hash table is stored in a linked list of type
// PairList.
PairList* pair_list_ = nullptr;
// The hash function. Based on DJB2 hashing algorithm.
unsigned int Hash(std::string key) const {
unsigned int hash = 5381;
for (char character : key) {
// hash = hash * 33 + static_cast<unsigned int>(character)
hash = ((hash << 5) + hash) + static_cast<unsigned int>(character);
}
hash = hash % capacity_;
return hash;
};
// Re-allocate the memory of the hash table.
int Resize() {
PairList* temp = pair_list_;
std::size_t new_capacity = capacity_ * 1.5;
pair_list_ = new PairList[new_capacity];
// Memory allocation failed.
if (!pair_list_) {
Debugger error_info(
Debugger::Level::ERROR, "Aq::Compiler::Lexer::HashMap::Resize",
"Resize_MemoryError", "Memory allocation failed.", nullptr);
return -1;
}
// Copy data.
for (int i = 0; i < capacity_; i++) {
temp[i].CopyDataToNewList(pair_list_, new_capacity);
}
// Release the memory of the original linked list.
delete[] temp;
capacity_ = new_capacity;
return 0;
};
};
} // namespace Aq

*/
#endif
4 changes: 4 additions & 0 deletions compiler/lexer/lexer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#include "debugger/debugger.h"

namespace Aq {
Compiler::Lexer::Lexer(char* source_code, size_t length)
: buffer_ptr_(source_code), buffer_end_(source_code + length - 1){};
Compiler::Lexer::~Lexer() = default;

int Compiler::Lexer::LexToken(Token& return_token) {
using Tok = Token::Type;

Expand Down
5 changes: 2 additions & 3 deletions compiler/lexer/lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ namespace Aq {
class Compiler::Lexer {
public:
// Initialize the Lexer class and store |source_code| to |buffer_ptr_|.
Lexer(char* source_code, size_t length)
: buffer_ptr_(source_code), buffer_end_(source_code + length - 1){};
~Lexer() = default;
Lexer(char* source_code, size_t length);
~Lexer();

Lexer(const Lexer&) = default;
Lexer(Lexer&&) noexcept = default;
Expand Down
17 changes: 17 additions & 0 deletions debugger/debugger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,23 @@
#include <sstream>

namespace Aq {
Debugger::Debugger(Level level, const char* location, const char* debug_code,
const char* debug_message, const char* other_info)
: errno_(errno),
errno_message_(std::strerror(errno)),
timestamp_(time(NULL)),
level_(level),
location_(location),
debug_code_(debug_code),
debug_message_(debug_message),
other_info_(other_info) {
OutputMessage();
if (level_ == Level::ERROR) {
exit(-1);
}
}
Debugger::~Debugger() = default;

void Debugger::OutputMessage() const {
std::string time_string = "Time:\"" + GetTimeString() + "\"";
std::string level_string;
Expand Down
Loading

0 comments on commit 601cfc4

Please sign in to comment.