Add a very basic List implementation

This commit is contained in:
Sameer Rahmani 2020-07-21 22:23:11 +01:00
parent cbea0c8e28
commit 576eba6451
10 changed files with 138 additions and 59 deletions

View File

@ -23,7 +23,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
# Let's ensure -std=c++xx instead of -std=g++xx # Let's ensure -std=c++xx instead of -std=g++xx
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_DEBUG set(CMAKE_CXX_FLAGS_DEBUG
"${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") "${CMAKE_CXX_FLAGS_DEBUG} -g -fno-omit-frame-pointer -fsanitize=address")
set(CMAKE_LINKER_FLAGS_DEBUG set(CMAKE_LINKER_FLAGS_DEBUG
"${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") "${CMAKE_LINKER_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address")

View File

@ -36,11 +36,15 @@ int main(int argc, char *argv[]) {
char *input_file = argv[1]; char *input_file = argv[1];
Reader *r = new Reader(input_file); Reader *r = new Reader(input_file);
ast_tree &ast = r->read(); ast_tree &ast = r->read();
cout << "Size: " << ast.size() << endl;
for(const ast_node& x : ast) {
cout << x->string_repr() << " >> ";
}
cout << ast.at(2)->string_repr() << endl;
// for(const ast_node& x : ast) {
// cout << x->string_repr() << " >> ";
// }
delete r; delete r;
cout << "\nEND<<" << endl; cout << "\nEND<<" << endl;
return 0; return 0;

View File

@ -78,7 +78,9 @@ case "$command" in
compile compile
;; ;;
"run") "run")
run "$@" echo "##############"
echo "${@:2}"
run "${@:2}"
;; ;;
"scan-build") "scan-build")

View File

@ -32,7 +32,7 @@ namespace serene {
class AExpr { class AExpr {
public: public:
virtual std::string string_repr() = 0; virtual std::string string_repr() = 0;
virtual ~AExpr() = default; virtual ~AExpr() {};
}; };
typedef std::unique_ptr<AExpr> ast_node; typedef std::unique_ptr<AExpr> ast_node;

View File

@ -31,29 +31,36 @@
namespace serene { namespace serene {
class ListNode {
public:
ast_node data;
std::unique_ptr<ListNode> next;
std::unique_ptr<ListNode> prev;
ListNode(ast_node node_data) : data{move(node_data)},
next{nullptr},
prev{nullptr} {};
};
class List: public AExpr { class List: public AExpr {
public: public:
ast_node first; std::unique_ptr<ListNode> head;
std::unique_ptr<List> rest; std::unique_ptr<ListNode> tail;
std::size_t len; std::size_t len;
List(): first(nullptr), rest(nullptr), len(0) {}; List(): head{nullptr}, tail{nullptr}, len{0} {};
List(ast_node f, std::unique_ptr<List> r): first(std::move(f)), List(const List &list);
rest(std::move(r)), List(List &&list);
len(r ? r->length() + 1 : 0)
{};
List(ast_tree list);
std::string string_repr(); std::string string_repr();
std::size_t length(); std::size_t length();
std::unique_ptr<List> cons(ast_node f);
static std::unique_ptr<List> to_list(ast_tree lst); void cons(ast_node f);
void add_tail(ast_node t);
void cleanup();
virtual ~List();
~List();
}; };
typedef std::unique_ptr<List> ast_list_node; typedef std::unique_ptr<List> ast_list_node;

View File

@ -58,18 +58,20 @@ namespace serene {
char get_char(const bool skip_whitespace); char get_char(const bool skip_whitespace);
void unget_char(); void unget_char();
int is_valid_for_identifier(char c); bool is_valid_for_identifier(char c);
// The property to store the ast tree // The property to store the ast tree
ast_tree ast; ast_tree ast;
ast_node read_symbol(); ast_node read_symbol();
ast_list_node read_list(); ast_list_node read_list(List list);
ast_node read_expr(); ast_node read_expr();
public: public:
Reader(const std::string &input); Reader(const std::string &input);
ast_tree &read(); ast_tree &read();
~Reader();
}; };
} }

View File

@ -37,7 +37,8 @@ namespace serene {
public: public:
Symbol(const std::string &name): name(name) {}; Symbol(const std::string &name): name(name) {};
std::string string_repr(); std::string string_repr();
~Symbol(); virtual ~Symbol();
}; };
} }

View File

@ -31,33 +31,87 @@
using namespace std; using namespace std;
namespace serene { namespace serene {
ast_list_node List::to_list(ast_tree lst) { void List::cons(ast_node f) {
auto l = make_unique<List>(); auto temp{std::make_unique<ListNode>(move(f))};
if(head) {
// Using a for loop with iterator temp->next = move(head);
for(auto node = rbegin(lst); node != rend(lst); ++node) { head->prev = move(temp);
l = l->cons(move(*node)); head = move(temp);
} }
else {
return l; head = move(temp);
}
len++;
} }
ast_list_node List::cons(ast_node f) { List::List(const List &list) {
ListNode *root = list.head.get();
return make_unique<List>(move(f), unique_ptr<List>(move(*this))); unique_ptr<ListNode> new_head{nullptr};
ListNode *pnew_head{nullptr};
while(root) {
auto temp{std::make_unique<ListNode>(unique_ptr<AExpr>(root->data.get()))};
if(new_head == nullptr) {
new_head = move(temp);
pnew_head = new_head.get();
} else {
pnew_head->next = move(temp);
pnew_head = pnew_head->next.get();
}
root = root->next.get();
}
head = move(new_head);
};
List::List(List &&list) {
head = move(list.head);
}
void List::add_tail(ast_node t) {
auto temp{std::make_unique<ListNode>(move(t))};
if(tail) {
temp->prev = move(tail);
tail->next = move(temp);
tail = move(temp);
len++;
}
else {
if (head) {
head->next = move(temp);
len++;
}
else {
cons(move(t));
}
}
} }
string List::string_repr() { string List::string_repr() {
return fmt::format("<List: '{}'>", first->string_repr()); if (head && head->data) {
return fmt::format("<List: '{}'>", head->data->string_repr());
}
else {
return "<List: empty>";
}
}; };
size_t List::length() { size_t List::length() {
if (this->len) { return len;
return this->len;
}
return 0;
} }
List::~List() {}; void List::cleanup() {
while(head) {
head = move(head->next);
}
};
List::~List() {
fmt::print("asdsadadsddddddddddddddddddddddddd\n");
cleanup();
};
} }

View File

@ -37,6 +37,10 @@ namespace serene {
input_stream.write(input.c_str(), input.size()); input_stream.write(input.c_str(), input.size());
}; };
Reader::~Reader() {
fmt::print("DELETE reader");
}
char Reader::get_char(const bool skip_whitespace) { char Reader::get_char(const bool skip_whitespace) {
for(;;) { for(;;) {
char c = input_stream.get(); char c = input_stream.get();
@ -52,7 +56,7 @@ namespace serene {
input_stream.unget(); input_stream.unget();
}; };
int Reader::is_valid_for_identifier(char c) { bool Reader::is_valid_for_identifier(char c) {
READER_LOG("IS: {}\n", c); READER_LOG("IS: {}\n", c);
switch(c) { switch(c) {
case '!' case '!'
@ -73,18 +77,15 @@ namespace serene {
| '@' | '@'
| '^' | '^'
| '_': | '_':
READER_LOG("#######\n"); return true;
return 1;
} }
if((c >= 'a' && c <='z') || if((c >= 'a' && c <='z') ||
(c >= 'A' && c <= 'Z') || (c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9')) { (c >= '0' && c <= '9')) {
READER_LOG("#######@@@@2\n"); return true;
return 1;
} }
READER_LOG("#####111111111111112\n"); return false;
return 0;
} }
ast_node Reader::read_symbol() { ast_node Reader::read_symbol() {
@ -93,39 +94,36 @@ namespace serene {
READER_LOG("Read symbol\n"); READER_LOG("Read symbol\n");
if(!this->is_valid_for_identifier(c)) { if(!this->is_valid_for_identifier(c)) {
// TODO: Fix this when we implement the error handling
throw ReadError((char *)"Invalid character at the start of a symbol"); // TODO: Replece this with a tranceback function or something to raise
// synatx error.
fmt::print("Invalid character at the start of a symbol: '{}'\n", c);
exit(1);
} }
string sym(""); string sym("");
while(c != EOF && (!(isspace(c)) && this->is_valid_for_identifier(c))) { while(c != EOF && ((!(isspace(c)) && this->is_valid_for_identifier(c)))) {
READER_LOG("ABC: {}\n", c);
sym += c; sym += c;
c = get_char(false); c = get_char(false);
empty = false; empty = false;
} }
READER_LOG("44444444444444\n");
if (!empty) { if (!empty) {
READER_LOG("<<<<\n");
unget_char(); unget_char();
return make_unique<Symbol>(sym); return make_unique<Symbol>(sym);
} }
READER_LOG(">>>>>>>>>>>>\n");
return nullptr; return nullptr;
}; };
ast_list_node Reader::read_list() { ast_list_node Reader::read_list(List list) {
char c = get_char(true); char c = get_char(true);
assert(c == '('); assert(c == '(');
bool list_terminated = false; bool list_terminated = false;
ast_tree lst;
do { do {
char c = get_char(true); char c = get_char(true);
unget_char();
switch(c) { switch(c) {
case EOF: case EOF:
@ -135,11 +133,14 @@ namespace serene {
break; break;
default: default:
lst.push_back(read_expr()); unget_char();
auto tmp{read_expr()};
list.add_tail(move(tmp));
} }
} while(!list_terminated); } while(!list_terminated);
return List::to_list(move(lst)); return unique_ptr<List>(&list);
} }
@ -151,7 +152,7 @@ namespace serene {
switch(c) { switch(c) {
case '(': case '(':
return read_list(); return read_list(List());
case EOF: case EOF:
return nullptr; return nullptr;
@ -166,10 +167,16 @@ namespace serene {
while(c != EOF) { while(c != EOF) {
unget_char(); unget_char();
this->ast.push_back(read_expr()); auto tmp{read_expr()};
fmt::print("##### {}", tmp->string_repr());
if(tmp) {
this->ast.push_back(move(tmp));
}
c = get_char(true); c = get_char(true);
READER_LOG("11111 {}\n", c);
} }
READER_LOG("333333333333333\n");
return this->ast; return this->ast;
}; };
} }

View File

@ -35,5 +35,7 @@ namespace serene {
return fmt::format("<Symbol: '{}'>", name); return fmt::format("<Symbol: '{}'>", name);
}; };
Symbol::~Symbol() {}; Symbol::~Symbol() {
fmt::print("symbol dest\n");
};
} }