Setup clang-format as a githook and apply it to the source
This commit is contained in:
parent
8e90ea9813
commit
2eda5f8d5f
|
@ -12,4 +12,5 @@ install_manifest.txt
|
|||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
.ccls-cache
|
||||
.ccls-cache
|
||||
.clangd
|
|
@ -1,8 +1,7 @@
|
|||
* Serene lang
|
||||
** Setup development environment
|
||||
*** Emacs
|
||||
[[https://github.com/brotzeit/rustic][Rustic]] is highly recommended. Just install it and install the dependencies necessary
|
||||
on the Rust side. If you're using *FG42*, It already ships with Rustic installed.
|
||||
Install the dependencies including ~clangd~ and just run ~lsp~
|
||||
|
||||
**** Requirements on the Rust side
|
||||
To setup the dev envrionment you need to have *Clippy* and *RLS* installed. Run the
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -22,9 +22,9 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "serene/reader.hpp"
|
||||
#include "serene/serene.hpp"
|
||||
#include "serene/reader.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace serene;
|
||||
|
@ -37,7 +37,7 @@ int main(int argc, char *argv[]) {
|
|||
Reader *r = new Reader(input_file);
|
||||
ast_tree &ast = r->read();
|
||||
|
||||
for(const ast_node& x : ast) {
|
||||
for (const ast_node &x : ast) {
|
||||
cout << x->string_repr() << " ";
|
||||
}
|
||||
delete r;
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -25,25 +25,25 @@
|
|||
#ifndef EXPR_H
|
||||
#define EXPR_H
|
||||
|
||||
#include <string>
|
||||
#include "serene/logger.hpp"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include "serene/logger.hpp"
|
||||
#include <string>
|
||||
|
||||
#if defined(ENABLE_LOG) || defined(ENABLE_EXPR_LOG)
|
||||
#define EXPR_LOG(...) __LOG("EXPR", __VA_ARGS__);
|
||||
#else
|
||||
#define EXPR_LOG(...);
|
||||
#define EXPR_LOG(...) ;
|
||||
#endif
|
||||
|
||||
namespace serene {
|
||||
class AExpr {
|
||||
public:
|
||||
virtual std::string string_repr() = 0;
|
||||
virtual ~AExpr() {};
|
||||
};
|
||||
class AExpr {
|
||||
public:
|
||||
virtual std::string string_repr() = 0;
|
||||
virtual ~AExpr(){};
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<AExpr> ast_node;
|
||||
typedef std::vector<ast_node> ast_tree;
|
||||
}
|
||||
typedef std::unique_ptr<AExpr> ast_node;
|
||||
typedef std::vector<ast_node> ast_tree;
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -25,51 +25,49 @@
|
|||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include <string>
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include <string>
|
||||
|
||||
namespace serene {
|
||||
|
||||
class ListNode {
|
||||
public:
|
||||
ast_node data;
|
||||
ListNode* next;
|
||||
ListNode* prev;
|
||||
ListNode(ast_node node_data) : data{std::move(node_data)},
|
||||
next{nullptr},
|
||||
prev{nullptr} {};
|
||||
};
|
||||
class ListNode {
|
||||
public:
|
||||
ast_node data;
|
||||
ListNode *next;
|
||||
ListNode *prev;
|
||||
ListNode(ast_node node_data)
|
||||
: data{std::move(node_data)}, next{nullptr}, prev{nullptr} {};
|
||||
};
|
||||
|
||||
class List: public AExpr {
|
||||
public:
|
||||
ListNode* head;
|
||||
ListNode* tail;
|
||||
std::size_t len;
|
||||
class List : public AExpr {
|
||||
public:
|
||||
ListNode *head;
|
||||
ListNode *tail;
|
||||
std::size_t len;
|
||||
|
||||
List(): head{nullptr}, tail{nullptr}, len{0} {};
|
||||
List(const List &list);
|
||||
List(List &&list) noexcept;
|
||||
List() : head{nullptr}, tail{nullptr}, len{0} {};
|
||||
List(const List &list);
|
||||
List(List &&list) noexcept;
|
||||
|
||||
List& operator=(const List& other);
|
||||
List& operator=(List&& other);
|
||||
List &operator=(const List &other);
|
||||
List &operator=(List &&other);
|
||||
|
||||
std::string string_repr();
|
||||
std::size_t length();
|
||||
std::string string_repr();
|
||||
std::size_t length();
|
||||
|
||||
void cons(ast_node f);
|
||||
void append(ast_node t);
|
||||
void cons(ast_node f);
|
||||
void append(ast_node t);
|
||||
|
||||
AExpr &first();
|
||||
List &rest();
|
||||
AExpr &first();
|
||||
List &rest();
|
||||
|
||||
void cleanup();
|
||||
void cleanup();
|
||||
|
||||
virtual ~List();
|
||||
virtual ~List();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<List> ast_list_node;
|
||||
}
|
||||
typedef std::unique_ptr<List> ast_list_node;
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -25,16 +25,13 @@
|
|||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include "config.h"
|
||||
#include <fmt/core.h>
|
||||
|
||||
// DO NOT USE this macro directly. USE module specific macro.
|
||||
// Checkout `reader.cpp` for example.
|
||||
#define __LOG(M, ...) fmt::print("[{}] <{}:{}> in '{}': {}\n", \
|
||||
M, \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
__func__, \
|
||||
fmt::format(__VA_ARGS__));
|
||||
#define __LOG(M, ...) \
|
||||
fmt::print("[{}] <{}:{}> in '{}': {}\n", M, __FILE__, __LINE__, __func__, \
|
||||
fmt::format(__VA_ARGS__));
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -25,58 +25,58 @@
|
|||
#ifndef READER_H
|
||||
#define READER_H
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <fmt/core.h>
|
||||
#include "serene/logger.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/list.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
#include "serene/logger.hpp"
|
||||
#include "serene/serene.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
|
||||
#if defined(ENABLE_READER_LOG) || defined(ENABLE_LOG)
|
||||
#define READER_LOG(...) __LOG("READER", __VA_ARGS__);
|
||||
#else
|
||||
#define READER_LOG(...);
|
||||
#define READER_LOG(...) ;
|
||||
#endif
|
||||
|
||||
namespace serene {
|
||||
|
||||
class ReadError: public std::exception {
|
||||
private:
|
||||
char *message;
|
||||
class ReadError : public std::exception {
|
||||
private:
|
||||
char *message;
|
||||
|
||||
public:
|
||||
ReadError(char *msg): message(msg) {};
|
||||
const char* what() const throw() {
|
||||
return message;
|
||||
}
|
||||
};
|
||||
public:
|
||||
ReadError(char *msg) : message(msg){};
|
||||
const char *what() const throw() { return message; }
|
||||
};
|
||||
|
||||
class Reader {
|
||||
private:
|
||||
std::stringstream input_stream;
|
||||
class Reader {
|
||||
private:
|
||||
std::stringstream input_stream;
|
||||
|
||||
char get_char(const bool skip_whitespace);
|
||||
void unget_char();
|
||||
bool is_valid_for_identifier(char c);
|
||||
char get_char(const bool skip_whitespace);
|
||||
void unget_char();
|
||||
bool is_valid_for_identifier(char c);
|
||||
|
||||
// The property to store the ast tree
|
||||
ast_tree ast;
|
||||
// The property to store the ast tree
|
||||
ast_tree ast;
|
||||
|
||||
ast_node read_symbol();
|
||||
ast_list_node read_list(List *list);
|
||||
ast_node read_expr();
|
||||
ast_node read_symbol();
|
||||
ast_list_node read_list(List *list);
|
||||
ast_node read_expr();
|
||||
|
||||
public:
|
||||
Reader(const std::string &input);
|
||||
ast_tree &read();
|
||||
public:
|
||||
Reader(const std::string &input);
|
||||
ast_tree &read();
|
||||
|
||||
~Reader();
|
||||
};
|
||||
}
|
||||
~Reader();
|
||||
};
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -25,22 +25,20 @@
|
|||
#ifndef SYMBOL_H
|
||||
#define SYMBOL_H
|
||||
|
||||
#include <string>
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include <string>
|
||||
|
||||
namespace serene {
|
||||
class Symbol: public AExpr {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
Symbol(const std::string &name): name(name) {};
|
||||
std::string string_repr();
|
||||
virtual ~Symbol();
|
||||
|
||||
};
|
||||
}
|
||||
class Symbol : public AExpr {
|
||||
private:
|
||||
std::string name;
|
||||
|
||||
public:
|
||||
Symbol(const std::string &name) : name(name){};
|
||||
std::string string_repr();
|
||||
virtual ~Symbol();
|
||||
};
|
||||
} // namespace serene
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,25 +1,23 @@
|
|||
# Optionally glob, but only for CMake 3.12 or later:
|
||||
file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${INCLUDE_DIR}/**/*.hpp")
|
||||
file(GLOB SOURCES_LIST CONFIGURE_DEPENDS "${SOURCE_DIR}/**/*.cpp")
|
||||
#set(HEADER_LIST "${INCLUDE_DIR}/serene/serene.hpp")
|
||||
|
||||
#file(GLOB HEADER_LIST CONFIGURE_DEPENDS "${INCLUDE_DIR}/**/*.hpp")
|
||||
#file(GLOB SOURCES_LIST CONFIGURE_DEPENDS "${SOURCE_DIR}/**/*.cpp")
|
||||
set(HEADER_LIST
|
||||
"${INCLUDE_DIR}/serene/expr.hpp"
|
||||
"${INCLUDE_DIR}/serene/serene.hpp")
|
||||
# Make an automatic library - will be static or dynamic based on user setting
|
||||
add_library(lserene
|
||||
serene.cpp
|
||||
reader.cpp
|
||||
symbol.cpp
|
||||
list.cpp
|
||||
${SOURCES_LIST}
|
||||
${HEADER_LIST})
|
||||
|
||||
|
||||
# We need this directory, and users of our library will need it too
|
||||
target_include_directories(lserene PUBLIC "${INCLUDE_DIR}")
|
||||
target_compile_features(lserene PUBLIC cxx_std_20)
|
||||
target_include_directories(lserene PRIVATE ${INCLUDE_DIR})
|
||||
target_include_directories(lserene PUBLIC ${PROJECT_BINARY_DIR})
|
||||
|
||||
# This depends on (header only) boost
|
||||
target_link_libraries(lserene ${llvm_libs} fmt::fmt)
|
||||
|
||||
|
||||
source_group(TREE "${INCLUDE_DIR}" PREFIX "Header Files" FILES ${HEADER_LIST})
|
||||
|
|
258
src/list.cpp
258
src/list.cpp
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -22,156 +22,146 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <fmt/core.h>
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/list.hpp"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace serene {
|
||||
List::List(const List &list) {
|
||||
ListNode *root = list.head;
|
||||
List::List(const List &list) {
|
||||
ListNode *root = list.head;
|
||||
|
||||
ListNode *new_head{nullptr};
|
||||
ListNode *prev_new_head{nullptr};
|
||||
ListNode *new_head{nullptr};
|
||||
ListNode *prev_new_head{nullptr};
|
||||
|
||||
while(root) {
|
||||
ListNode *temp = new ListNode(unique_ptr<AExpr>(root->data.get()));
|
||||
while (root) {
|
||||
ListNode *temp = new ListNode(unique_ptr<AExpr>(root->data.get()));
|
||||
|
||||
if(new_head == nullptr) {
|
||||
new_head = temp;
|
||||
prev_new_head = new_head;
|
||||
if (new_head == nullptr) {
|
||||
new_head = temp;
|
||||
prev_new_head = new_head;
|
||||
|
||||
} else {
|
||||
prev_new_head->next = temp;
|
||||
prev_new_head = prev_new_head->next;
|
||||
}
|
||||
|
||||
root = root->next;
|
||||
} else {
|
||||
prev_new_head->next = temp;
|
||||
prev_new_head = prev_new_head->next;
|
||||
}
|
||||
head = new_head;
|
||||
};
|
||||
|
||||
|
||||
List::List(List &&list) noexcept: head(list.head),
|
||||
tail(list.tail),
|
||||
len(std::exchange(list.len, 0)) {
|
||||
list.head = nullptr;
|
||||
list.tail = nullptr;
|
||||
};
|
||||
|
||||
List& List::operator=(const List& list) {
|
||||
ListNode *root = list.head;
|
||||
|
||||
ListNode *new_head{nullptr};
|
||||
ListNode *prev_new_head{nullptr};
|
||||
|
||||
while(root) {
|
||||
ListNode *temp = new ListNode(unique_ptr<AExpr>(root->data.get()));
|
||||
|
||||
if(new_head == nullptr) {
|
||||
new_head = temp;
|
||||
prev_new_head = new_head;
|
||||
|
||||
} else {
|
||||
prev_new_head->next = temp;
|
||||
prev_new_head = prev_new_head->next;
|
||||
}
|
||||
|
||||
root = root->next;
|
||||
}
|
||||
head = new_head;
|
||||
return *this;
|
||||
};
|
||||
|
||||
List& List::operator=(List&& list) {
|
||||
head = list.head;
|
||||
tail = list.tail;
|
||||
len = std::exchange(list.len, 0);
|
||||
list.head = nullptr;
|
||||
list.tail = nullptr;
|
||||
return *this;
|
||||
};
|
||||
|
||||
|
||||
void List::cons(ast_node f) {
|
||||
ListNode *temp = new ListNode(move(f));
|
||||
|
||||
if(head) {
|
||||
temp->next = head;
|
||||
head->prev = temp;
|
||||
head = temp;
|
||||
}
|
||||
else {
|
||||
head = temp;
|
||||
}
|
||||
len++;
|
||||
root = root->next;
|
||||
}
|
||||
head = new_head;
|
||||
};
|
||||
|
||||
void List::append(ast_node t) {
|
||||
// TODO: Should we do it here?
|
||||
if(!t) {
|
||||
return;
|
||||
List::List(List &&list) noexcept
|
||||
: head(list.head), tail(list.tail), len(std::exchange(list.len, 0)) {
|
||||
list.head = nullptr;
|
||||
list.tail = nullptr;
|
||||
};
|
||||
|
||||
List &List::operator=(const List &list) {
|
||||
ListNode *root = list.head;
|
||||
|
||||
ListNode *new_head{nullptr};
|
||||
ListNode *prev_new_head{nullptr};
|
||||
|
||||
while (root) {
|
||||
ListNode *temp = new ListNode(unique_ptr<AExpr>(root->data.get()));
|
||||
|
||||
if (new_head == nullptr) {
|
||||
new_head = temp;
|
||||
prev_new_head = new_head;
|
||||
|
||||
} else {
|
||||
prev_new_head->next = temp;
|
||||
prev_new_head = prev_new_head->next;
|
||||
}
|
||||
|
||||
if(tail) {
|
||||
ListNode *temp = new ListNode(move(t));
|
||||
temp->prev = tail;
|
||||
tail->next = temp;
|
||||
tail = temp;
|
||||
len++;
|
||||
}
|
||||
else {
|
||||
if (head) {
|
||||
ListNode *temp = new ListNode(move(t));
|
||||
head->next = temp;
|
||||
tail = temp;
|
||||
tail->prev = head;
|
||||
len++;
|
||||
}
|
||||
else {
|
||||
cons(move(t));
|
||||
}
|
||||
}
|
||||
root = root->next;
|
||||
}
|
||||
head = new_head;
|
||||
return *this;
|
||||
};
|
||||
|
||||
string List::string_repr() {
|
||||
if (head && head->data) {
|
||||
string s{"("};
|
||||
List &List::operator=(List &&list) {
|
||||
head = list.head;
|
||||
tail = list.tail;
|
||||
len = std::exchange(list.len, 0);
|
||||
list.head = nullptr;
|
||||
list.tail = nullptr;
|
||||
return *this;
|
||||
};
|
||||
|
||||
for(ListNode* current = head, *next; current;) {
|
||||
next = current->next;
|
||||
s = s + current->data->string_repr();
|
||||
current = next;
|
||||
if (next) {
|
||||
s = s + " ";
|
||||
}
|
||||
}
|
||||
return fmt::format("{})", s);
|
||||
void List::cons(ast_node f) {
|
||||
ListNode *temp = new ListNode(move(f));
|
||||
|
||||
}
|
||||
else {
|
||||
return "()";
|
||||
}
|
||||
};
|
||||
|
||||
size_t List::length() {
|
||||
return len;
|
||||
if (head) {
|
||||
temp->next = head;
|
||||
head->prev = temp;
|
||||
head = temp;
|
||||
} else {
|
||||
head = temp;
|
||||
}
|
||||
|
||||
void List::cleanup() {
|
||||
for (ListNode* current = head, *next; current;)
|
||||
{
|
||||
next = current->next;
|
||||
delete current;
|
||||
current = next;
|
||||
}
|
||||
};
|
||||
|
||||
List::~List() {
|
||||
EXPR_LOG("Destroying list");
|
||||
cleanup();
|
||||
};
|
||||
len++;
|
||||
}
|
||||
|
||||
void List::append(ast_node t) {
|
||||
// TODO: Should we do it here?
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tail) {
|
||||
ListNode *temp = new ListNode(move(t));
|
||||
temp->prev = tail;
|
||||
tail->next = temp;
|
||||
tail = temp;
|
||||
len++;
|
||||
} else {
|
||||
if (head) {
|
||||
ListNode *temp = new ListNode(move(t));
|
||||
head->next = temp;
|
||||
tail = temp;
|
||||
tail->prev = head;
|
||||
len++;
|
||||
} else {
|
||||
cons(move(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string List::string_repr() {
|
||||
if (head && head->data) {
|
||||
string s{"("};
|
||||
|
||||
for (ListNode *current = head, *next; current;) {
|
||||
next = current->next;
|
||||
s = s + current->data->string_repr();
|
||||
current = next;
|
||||
if (next) {
|
||||
s = s + " ";
|
||||
}
|
||||
}
|
||||
return fmt::format("{})", s);
|
||||
|
||||
} else {
|
||||
return "()";
|
||||
}
|
||||
};
|
||||
|
||||
size_t List::length() { return len; }
|
||||
|
||||
void List::cleanup() {
|
||||
for (ListNode *current = head, *next; current;) {
|
||||
next = current->next;
|
||||
delete current;
|
||||
current = next;
|
||||
}
|
||||
};
|
||||
|
||||
List::~List() {
|
||||
EXPR_LOG("Destroying list");
|
||||
cleanup();
|
||||
};
|
||||
} // namespace serene
|
||||
|
|
240
src/reader.cpp
240
src/reader.cpp
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -22,158 +22,136 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "serene/reader.hpp"
|
||||
#include "serene/list.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <assert.h>
|
||||
#include "serene/reader.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
#include "serene/list.hpp"
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace serene {
|
||||
Reader::Reader(const string &input) {
|
||||
input_stream.write(input.c_str(), input.size());
|
||||
};
|
||||
Reader::Reader(const string &input) {
|
||||
input_stream.write(input.c_str(), input.size());
|
||||
};
|
||||
|
||||
Reader::~Reader() {
|
||||
READER_LOG("Destroying the reader");
|
||||
Reader::~Reader() { READER_LOG("Destroying the reader"); }
|
||||
|
||||
char Reader::get_char(const bool skip_whitespace) {
|
||||
for (;;) {
|
||||
char c = input_stream.get();
|
||||
if (skip_whitespace == true && isspace(c)) {
|
||||
continue;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void Reader::unget_char() { input_stream.unget(); };
|
||||
|
||||
bool Reader::is_valid_for_identifier(char c) {
|
||||
switch (c) {
|
||||
case '!' | '$' | '%' | '&' | '*' | '+' | '-' | '.' | '~' | '/' | ':' | '<' |
|
||||
'=' | '>' | '?' | '@' | '^' | '_':
|
||||
return true;
|
||||
}
|
||||
|
||||
char Reader::get_char(const bool skip_whitespace) {
|
||||
for(;;) {
|
||||
char c = input_stream.get();
|
||||
if (skip_whitespace == true && isspace(c)) {
|
||||
continue;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
};
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Reader::unget_char() {
|
||||
input_stream.unget();
|
||||
};
|
||||
ast_node Reader::read_symbol() {
|
||||
bool empty = true;
|
||||
char c = get_char(false);
|
||||
|
||||
bool Reader::is_valid_for_identifier(char c) {
|
||||
switch(c) {
|
||||
case '!'
|
||||
| '$'
|
||||
| '%'
|
||||
| '&'
|
||||
| '*'
|
||||
| '+'
|
||||
| '-'
|
||||
| '.'
|
||||
| '~'
|
||||
| '/'
|
||||
| ':'
|
||||
| '<'
|
||||
| '='
|
||||
| '>'
|
||||
| '?'
|
||||
| '@'
|
||||
| '^'
|
||||
| '_':
|
||||
return true;
|
||||
}
|
||||
READER_LOG("Reading symbol");
|
||||
if (!this->is_valid_for_identifier(c)) {
|
||||
|
||||
if((c >= 'a' && c <='z') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= '0' && c <= '9')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// 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);
|
||||
}
|
||||
|
||||
ast_node Reader::read_symbol() {
|
||||
bool empty = true;
|
||||
char c = get_char(false);
|
||||
string sym("");
|
||||
|
||||
READER_LOG("Reading symbol");
|
||||
if(!this->is_valid_for_identifier(c)) {
|
||||
|
||||
// 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("");
|
||||
|
||||
while(c != EOF && ((!(isspace(c)) && this->is_valid_for_identifier(c)))) {
|
||||
sym += c;
|
||||
c = get_char(false);
|
||||
empty = false;
|
||||
}
|
||||
|
||||
if (!empty) {
|
||||
unget_char();
|
||||
return make_unique<Symbol>(sym);
|
||||
}
|
||||
|
||||
// TODO: it should never happens
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
ast_list_node Reader::read_list(List *list) {
|
||||
char c = get_char(true);
|
||||
assert(c == '(');
|
||||
|
||||
bool list_terminated = false;
|
||||
|
||||
do {
|
||||
char c = get_char(true);
|
||||
|
||||
switch(c) {
|
||||
case EOF:
|
||||
throw ReadError((char *)"EOF reached before closing of list");
|
||||
case ')':
|
||||
list_terminated = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
unget_char();
|
||||
list->append(read_expr());
|
||||
}
|
||||
|
||||
} while(!list_terminated);
|
||||
|
||||
return unique_ptr<List>(list);
|
||||
while (c != EOF && ((!(isspace(c)) && this->is_valid_for_identifier(c)))) {
|
||||
sym += c;
|
||||
c = get_char(false);
|
||||
empty = false;
|
||||
}
|
||||
|
||||
|
||||
ast_node Reader::read_expr() {
|
||||
char c = get_char(false);
|
||||
READER_LOG("CHAR: {}", c);
|
||||
|
||||
if (!empty) {
|
||||
unget_char();
|
||||
return make_unique<Symbol>(sym);
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
case '(':
|
||||
return read_list(new List());
|
||||
// TODO: it should never happens
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
ast_list_node Reader::read_list(List *list) {
|
||||
char c = get_char(true);
|
||||
assert(c == '(');
|
||||
|
||||
bool list_terminated = false;
|
||||
|
||||
do {
|
||||
char c = get_char(true);
|
||||
|
||||
switch (c) {
|
||||
case EOF:
|
||||
return nullptr;
|
||||
throw ReadError((char *)"EOF reached before closing of list");
|
||||
case ')':
|
||||
list_terminated = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return read_symbol();
|
||||
unget_char();
|
||||
list->append(read_expr());
|
||||
}
|
||||
|
||||
} while (!list_terminated);
|
||||
|
||||
return unique_ptr<List>(list);
|
||||
}
|
||||
|
||||
ast_node Reader::read_expr() {
|
||||
char c = get_char(false);
|
||||
READER_LOG("CHAR: {}", c);
|
||||
|
||||
unget_char();
|
||||
|
||||
switch (c) {
|
||||
case '(':
|
||||
return read_list(new List());
|
||||
|
||||
case EOF:
|
||||
return nullptr;
|
||||
|
||||
default:
|
||||
return read_symbol();
|
||||
}
|
||||
}
|
||||
|
||||
ast_tree &Reader::read() {
|
||||
char c = get_char(true);
|
||||
|
||||
while (c != EOF) {
|
||||
unget_char();
|
||||
auto tmp{read_expr()};
|
||||
if (tmp) {
|
||||
this->ast.push_back(move(tmp));
|
||||
}
|
||||
c = get_char(true);
|
||||
}
|
||||
|
||||
ast_tree &Reader::read() {
|
||||
char c = get_char(true);
|
||||
|
||||
while(c != EOF) {
|
||||
unget_char();
|
||||
auto tmp{read_expr()};
|
||||
if(tmp) {
|
||||
this->ast.push_back(move(tmp));
|
||||
}
|
||||
c = get_char(true);
|
||||
}
|
||||
|
||||
return this->ast;
|
||||
};
|
||||
}
|
||||
return this->ast;
|
||||
};
|
||||
} // namespace serene
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
|
@ -22,20 +22,16 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <fmt/core.h>
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/symbol.hpp"
|
||||
#include "serene/expr.hpp"
|
||||
#include "serene/llvm/IR/Value.h"
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace serene {
|
||||
string Symbol::string_repr() {
|
||||
return name;
|
||||
};
|
||||
string Symbol::string_repr() { return name; };
|
||||
|
||||
Symbol::~Symbol() {
|
||||
EXPR_LOG("Destroying symbol");
|
||||
};
|
||||
}
|
||||
Symbol::~Symbol() { EXPR_LOG("Destroying symbol"); };
|
||||
} // namespace serene
|
||||
|
|
Loading…
Reference in New Issue