Setup clang-format as a githook and apply it to the source

This commit is contained in:
Sameer Rahmani 2020-07-23 21:47:13 +01:00
parent 8e90ea9813
commit 2eda5f8d5f
13 changed files with 355 additions and 402 deletions

2
.ccls
View File

@ -1,2 +0,0 @@
%compile_commands.json
-Iinclude

3
.gitignore vendored
View File

@ -12,4 +12,5 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
.ccls-cache
.ccls-cache
.clangd

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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})

View File

@ -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

View File

@ -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

View File

@ -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