0

I'm fairly new to C++. Currently I'm trying to contend with a myriad of compiler errors. I couldn't find the root cause nor could do I understand why/how they were invoked. I'd also like to know how to avoid or better handle this kind of situation in the future.

This is for an interpreter I'm writing, though I'm only finished with the garbage collection/variable handling portions.

garbage.h

#pragma once

#ifndef GARBAGE
#define GARBAGE

#include <stack>
#include "value.h"
#include "runtime.h"

class garbage_collector {
public:
    garbage_collector();
    ~garbage_collector();

    //initializes a new garbage collection frame
    void new_frame();

    //creates a new variable apartment within the garbage collector
    variable_apartment* new_apartment(value* initial_value, bool reference_once=false);

    //de-allocates unused variable appartments within the current garbage collection frame
    unsigned int sweep();
private:
    unsigned int size;
    variable_apartment* head;
    variable_apartment* tail;
    std::stack<variable_apartment*> sweep_frames;
};

#endif // !GARBAGE

garbage.cpp

#include "garbage.h"

garbage_collector::garbage_collector() {
    this->size = 0;
    this->head = nullptr;
    this->sweep_frames = std::stack<variable_apartment*>();
}

garbage_collector::~garbage_collector() {
    while (size > 0)
    {
        sweep();
    }
}

void garbage_collector::new_frame() {
    this->sweep_frames.push(tail);
}

variable_apartment* garbage_collector::new_apartment(value* initial_value, bool reference_once) {
    if (size == 0) {
        size++;
        return (tail = (head = new variable_apartment(initial_value, reference_once ? 1 : 0)));
    }
    else {
        size++;
        tail->next_apartment = new variable_apartment(initial_value, reference_once ? 1 : 0);
        tail = tail->next_apartment;
        return tail;
    }
}

unsigned int garbage_collector::sweep() {
    unsigned int destroyed_values = 0;
    variable_apartment* current = sweep_frames.empty() ? head : sweep_frames.top()->next_apartment;
    variable_apartment* previous = sweep_frames.empty() ? nullptr : sweep_frames.top();
    while (current != nullptr)
    {
        if (current->references == 0) {
            variable_apartment* to_delete = current;
            current = current->next_apartment;
            if (previous == nullptr)
                head = current;
            else
                previous->next_apartment = current;
            delete to_delete;
            size--;
            destroyed_values++;
        }
        else {
            previous = current;
            current = current->next_apartment;
        }
    }
    if (!sweep_frames.empty())
        sweep_frames.pop();
    return destroyed_values;
}

runtime.h

#pragma once

#ifndef RUNTIME_H
#define RUNTIME_H

#include "value.h"
#include "garbage.h"

//handles initialization and disposal of all program values

class variable_apartment {
public:
    value* value;
    unsigned int references;
    variable_apartment(class value* value, unsigned int references = 0, variable_apartment* next_apartment = nullptr);
    ~variable_apartment();
    variable_apartment* next_apartment;
};

class variable_bucket {
public:
    unsigned long id_hash;
    variable_apartment* apartment;
    variable_bucket(unsigned long id_hash, variable_apartment* apartment, variable_bucket* next_bucket = nullptr);
    variable_bucket* next_bucket;
};

#define VARIABLE_HASH_BUCKET_SIZE 200

class variable_manager {
public:
    variable_manager(garbage_collector* garbage_collector);
    ~variable_manager();
    variable_apartment* declare_var(unsigned long id_hash, value* value);
    void remove_var(unsigned long id_hash);
private:
    unsigned int size;
    garbage_collector* garbage_collector;
    variable_bucket* hash_buckets[VARIABLE_HASH_BUCKET_SIZE];
};

#endif // !RUNTIME_H

runtime.cpp

#include "runtime.h"
#include "errors.h"
#include "hash.h"

variable_apartment::variable_apartment(class value* value, unsigned int references, variable_apartment* next_apartment) {
    this->value = value;
    this->references = references;
    this->next_apartment = next_apartment;
}

variable_apartment::~variable_apartment() {
    delete value;
}

variable_bucket::variable_bucket(unsigned long id_hash, variable_apartment* apartment, variable_bucket* next_bucket) {
    this->id_hash = id_hash;
    this->apartment = apartment;
    this->next_bucket = next_bucket;
}

variable_manager::variable_manager(class garbage_collector* garbage_collector) {
    this->size = 0;
    this->garbage_collector = garbage_collector;
    for (size_t i = 0; i < VARIABLE_HASH_BUCKET_SIZE; i++)
    {
        hash_buckets[i] = nullptr;
    }
}

variable_manager::~variable_manager() {
    for (size_t i = 0; i < VARIABLE_HASH_BUCKET_SIZE; i++)
    {
        if (hash_buckets[i] != nullptr) {
            variable_bucket* current = hash_buckets[i];
            while (current != nullptr)
            {
                variable_bucket* to_delete = current;
                to_delete->apartment--;
                delete to_delete;
                current = current->next_bucket;
            }
        }
    }
}

variable_apartment* variable_manager::declare_var(unsigned long id_hash, value* value) {
    variable_bucket* bucket = hash_buckets[id_hash % VARIABLE_HASH_BUCKET_SIZE];
    variable_bucket* parent = nullptr;
    while (bucket != nullptr) {
        if (bucket->id_hash == id_hash)
            throw ERROR_VARIABLE_ALREADY_DEFINED;
        parent = bucket;
        bucket = bucket->next_bucket;
    }
    if (parent == nullptr)
        return (hash_buckets[id_hash % VARIABLE_HASH_BUCKET_SIZE] = new variable_bucket(id_hash, garbage_collector->new_apartment(value, true)))->apartment;
    else
        return (parent->next_bucket = new variable_bucket(id_hash, garbage_collector->new_apartment(value, true)))->apartment;
}

void variable_manager::remove_var(unsigned long id_hash) {
    variable_bucket* bucket = hash_buckets[id_hash % VARIABLE_HASH_BUCKET_SIZE];
    variable_bucket* parent = nullptr;
    while (bucket != nullptr)
    {
        if (bucket->id_hash == id_hash) {
            break;
        }
        parent = bucket;
        bucket = bucket->next_bucket;
    }
    if (bucket == nullptr)
        throw ERROR_VARIABLE_NOT_DEFINED;
    if (parent == nullptr)
        hash_buckets[id_hash % VARIABLE_HASH_BUCKET_SIZE] = bucket->next_bucket;
    else
        parent->next_bucket = bucket->next_bucket;
    bucket->apartment->references--;
    delete bucket;
}

value.h, though I'm think this portion doesn't have any actual errors.

#pragma once

#ifndef VALUE_H
#define VALUE_H

#define VALUE_TYPE_NULL 0
#define VALUE_TYPE_CHAR 1
#define VALUE_TYPE_NUMERICAL 2
#define VALUE_TYPE_COLLECTION 3

class value {
public:
    char type;
    void* ptr;
    value(const value& value);
    value(char type, void* ptr);
    ~value();
};

class collection {
public:
    unsigned long size;
    value** inner_collection;
    collection(const collection& collection);
    collection(unsigned long size);
    ~collection();
};

#endif // !VALUE_H

value.cpp

#include "errors.h"
#include "value.h"
#include "runtime.h"

#define MAX_VALUE_TYPE 3

value::value(const value& value) {
    this->type = value.type;
    switch (this->type)
    {
    case VALUE_TYPE_NULL:
        this->ptr = nullptr;
        break;
    case VALUE_TYPE_CHAR:
        this->ptr = new char(*(char*)value.ptr);
        break;
    case VALUE_TYPE_NUMERICAL:
        this->ptr = new double(*(double*)value.ptr);
        break;
    case VALUE_TYPE_COLLECTION:
        this->ptr = new double(*(double*)value.ptr);
        break;
    default:
        throw ERROR_INVALID_VALUE_TYPE;
    }
}

value::value(char type, void* ptr) {
    if (type > MAX_VALUE_TYPE) {
        throw ERROR_INVALID_VALUE_TYPE;
    }
    this->type = type;
    this->ptr = ptr;
}

value::~value() {
    switch (this->type)
    {
    case VALUE_TYPE_CHAR:
        delete ((char*)this->ptr);
        break;
    case VALUE_TYPE_NUMERICAL:
        delete ((double*)this->ptr);
        break;
    case VALUE_TYPE_COLLECTION:
        delete ((collection*)this->ptr);
        break;
    default:
        throw ERROR_INVALID_VALUE_TYPE;
    }
}

collection::collection(const collection& collection) {
    this->size = collection.size;
    this->inner_collection = new value * [this->size];
    for (unsigned long i = 0; i < collection.size; i++)
    {
        this->inner_collection[i] = collection.inner_collection[i];
    }
}

collection::collection(unsigned long size) {
    this->size = size;
    this->inner_collection = new value * [size];
}

collection::~collection() {
    delete this->inner_collection;
}

And here are the 41 compiler errors I'm getting

Severity    Code    Description Project File    Line    Suppression State
Error   C2061   syntax error: identifier 'garbage_collector'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.h   32  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.h   38  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.h   38  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.h   38  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2065   'variable_apartment': undeclared identifier quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
Error   C2059   syntax error: '>'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
Error   C2039   'new_apartment': is not a member of 'garbage_collector' quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.cpp 56  
Error   C2664   'variable_bucket::variable_bucket(const variable_bucket &)': cannot convert argument 1 from 'unsigned long' to 'const variable_bucket &'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.cpp 56  
Error   C2039   'new_apartment': is not a member of 'garbage_collector' quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.cpp 58  
Error   C2664   'variable_bucket::variable_bucket(const variable_bucket &)': cannot convert argument 1 from 'unsigned long' to 'const variable_bucket &'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\runtime.cpp 58  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2065   'variable_apartment': undeclared identifier quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
Error   C2059   syntax error: '>'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   19  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   25  
Error   C2143   syntax error: missing ';' before '*'    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2238   unexpected token(s) preceding ';'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   26  
Error   C2065   'variable_apartment': undeclared identifier quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
Error   C2059   syntax error: '>'   quickscript C:\Users\Micha\source\repos\quickscript\quickscript\garbage.h   27  
mike
  • 100
  • 7
  • 1
    `garbage.h` includes `runtime.h` which includes `garbage.h`. Does [this](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) seem like it might help? – Nathan Pierson Apr 23 '21 at 04:04
  • @NathanPierson I think it's the issue I'm having. Let me take a look first. – mike Apr 23 '21 at 04:08
  • @NathanPierson Thanks for the link, forward declarations seem to fix the issue. – mike Apr 23 '21 at 04:11
  • Please create a [mre]. Not only does it help you to search better or discover the problem yourself, it helps the people volunteering their time and helps future visitors with the same problem. – chris Apr 23 '21 at 04:34

0 Answers0