From: LeonardoBizzoni Date: Mon, 23 Oct 2023 16:36:27 +0000 (+0200) Subject: Memory mapped source file X-Git-Url: http://git.leonardobizzoni.com/?a=commitdiff_plain;h=5d9e34ede7479baab46bffece4c0cd1e8a928cc7;p=LBPL Memory mapped source file --- diff --git a/lib/lexer.h b/lib/lexer.h index 7a3d68f..c116a22 100755 --- a/lib/lexer.h +++ b/lib/lexer.h @@ -11,11 +11,9 @@ class Lexer { private: int line; - std::ifstream &stream; std::string filename; - std::string currentLine; - std::string::iterator start; - std::string::iterator current; + const char *start; + const char *current; public: bool hadError; @@ -38,13 +36,12 @@ private: char peekNext() const; bool isAtEnd() const; - bool isAtLineEnd() const; bool isDigit(char ch) const; bool isAlpha(char ch) const; bool match(char ch); public: - Lexer(std::ifstream &, const std::string &); + Lexer(const char*, const std::string &); int getLine(); int getColumn(); diff --git a/lib/parser.h b/lib/parser.h index daa8b76..943849b 100755 --- a/lib/parser.h +++ b/lib/parser.h @@ -65,13 +65,13 @@ private: std::unique_ptr primary(); public: - Parser(std::ifstream &file, std::string &filename) + Parser(const char *file, const std::string &filename) : lexer(new Lexer(file, filename)), current(lexer->getNextToken()), previous(current) { importedFiles.insert(filename); } - Parser(std::ifstream &file, const std::string &filename, + Parser(const char *file, const std::string &filename, std::unordered_set &importedFiles) : importedFiles(importedFiles), lexer(new Lexer(file, filename)), current(lexer->getNextToken()), previous(current) {} diff --git a/src/interpreter.cpp b/src/interpreter.cpp index 42432bd..ff68f4a 100644 --- a/src/interpreter.cpp +++ b/src/interpreter.cpp @@ -5,41 +5,13 @@ #include "LBPLTypes.h" #include "runtime_error.h" -#include #include #include #include #include #include -class Timer { - std::chrono::time_point m_startTimepoint; - -public: - Timer() { m_startTimepoint = std::chrono::high_resolution_clock::now(); } - - ~Timer() { stop(); } - - void stop() { - auto endTimepoint = std::chrono::high_resolution_clock::now(); - - auto start = std::chrono::time_point_cast( - m_startTimepoint) - .time_since_epoch() - .count(); - auto end = - std::chrono::time_point_cast(endTimepoint) - .time_since_epoch() - .count(); - - auto duration = end - start; - auto ms = duration * 0.001; - - std::cout << duration << "µs (" << ms << "ms)\n"; - } -}; void Interpreter::interpret(std::vector> &stmts) { - std::cout << "\tinterpreter begin\n"; try { for (auto &&stmt : stmts) { stmt->accept(this); @@ -160,53 +132,8 @@ void Interpreter::visitReturnStmt(ReturnStmt *stmt) { LBPLType Interpreter::visitBinaryExpr(BinaryExpr *expr) { LBPLType left = expr->left->accept(this); LBPLType right = expr->right->accept(this); - return performBinaryOperation(expr->op, left, right); - /* if (std::holds_alternative(left) && - * std::holds_alternative(right)) { */ - /* return performBinaryOperation(expr->op.get(), std::get(left), */ - /* std::get(right)); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return performBinaryOperation(expr->op.get(), std::get(left), */ - /* std::get(right)); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return performBinaryOperation(expr->op.get(), std::get(left), */ - /* std::get(right)); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return performBinaryOperation(expr->op.get(), std::get(left), */ - /* std::get(right)); */ - /* } else if ((std::holds_alternative(left) || */ - /* std::holds_alternative(right)) && */ - /* expr->op->type == TokenType::Plus) { */ - /* if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::get(left) + */ - /* std::get(right); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::get(left) + */ - /* std::to_string(std::get(right)); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::get(left) + */ - /* std::to_string(std::get(right)); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::to_string(std::get(left)) + */ - /* std::get(right); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::get(left) + std::get(right); */ - /* } else if (std::holds_alternative(left) && */ - /* std::holds_alternative(right)) { */ - /* return std::get(left) + std::get(right); */ - /* } */ - /* } */ - - /* throw RuntimeError(expr->op.get(), "Invalid binary operation operand."); */ + return performBinaryOperation(expr->op, left, right); } LBPLType Interpreter::visitBreakExpr(BreakExpr *) { throw BreakException(); } @@ -259,6 +186,7 @@ LBPLType Interpreter::visitGroupExpr(GroupingExpr *expr) { LBPLType Interpreter::visitSuperExpr(SuperExpr *) { return nullptr; } LBPLType Interpreter::visitThisExpr(ThisExpr *) { return nullptr; } + LBPLType Interpreter::visitCallExpr(FnCallExpr *expr) { LBPLType callee = expr->callee->accept(this); @@ -292,10 +220,12 @@ LBPLType Interpreter::visitCallExpr(FnCallExpr *expr) { LBPLType Interpreter::visitGetFieldExpr(GetFieldExpr *expr) { LBPLType instance = expr->instance->accept(this); if (std::holds_alternative>(instance)) { - return std::get>(instance)->get(expr->field.get()); + return std::get>(instance)->get( + expr->field.get()); } - throw RuntimeError(expr->instance.get(), "Only instances of classes can have properties"); + throw RuntimeError(expr->instance.get(), + "Only instances of classes can have properties"); } LBPLType Interpreter::visitSetFieldExpr(SetFieldExpr *expr) { @@ -303,9 +233,11 @@ LBPLType Interpreter::visitSetFieldExpr(SetFieldExpr *expr) { if (std::holds_alternative>(instance)) { LBPLType value = expr->value->accept(this); - std::get>(instance)->set(expr->field.get(), value); + std::get>(instance)->set(expr->field.get(), + value); } else { - throw RuntimeError(expr->instance.get(), "Only instances of classes can have properties"); + throw RuntimeError(expr->instance.get(), + "Only instances of classes can have properties"); } return nullptr; @@ -472,41 +404,6 @@ LBPLType Interpreter::performBinaryOperation(std::shared_ptr &op, left, right); } -/* template */ -/* LBPLType Interpreter::performBinaryOperation(const Token *op, const T &left, - */ -/* const G &right) { */ -/* switch (op->type) { */ -/* case TokenType::EqualEqual: */ -/* return left == right; */ -/* case TokenType::BangEqual: */ -/* return left != right; */ -/* case TokenType::Less: */ -/* return left < right; */ -/* case TokenType::LessEqual: */ -/* return left <= right; */ -/* case TokenType::Greater: */ -/* return left > right; */ -/* case TokenType::GreaterEqual: */ -/* return left >= right; */ -/* case TokenType::Plus: */ -/* return left + right; */ -/* case TokenType::Minus: */ -/* return left - right; */ -/* case TokenType::Star: */ -/* return left * right; */ -/* case TokenType::Slash: */ -/* if (right == T(0)) { */ -/* throw RuntimeError(op, "Division by zero."); */ -/* } */ -/* return left / right; */ -/* case TokenType::ModOp: */ -/* return (int)left % (int)right; */ -/* default: */ -/* throw RuntimeError(op, "Unsupported binary operation."); */ -/* } */ -/* } */ - void Interpreter::executeBlock(std::vector> &body, std::shared_ptr &&env) { executeBlock(body, env); diff --git a/src/lexer.cpp b/src/lexer.cpp index 098bd9a..adde981 100755 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -1,18 +1,16 @@ #include "lexer.h" -Lexer::Lexer(std::ifstream &stream, const std::string &filename) - : stream(stream), line(1), hadError(false), filename(filename) { - goToNextLine(); -} +Lexer::Lexer(const char *stream, const std::string &filename) + : line(1), hadError(false), filename(filename), current(stream), start(stream) {} -bool Lexer::isAtEnd() const { return stream.eof(); } -bool Lexer::isAtLineEnd() const { return *current == '\0'; } +bool Lexer::isAtEnd() const { return *current == '\0'; } bool Lexer::isDigit(char ch) const { return ch >= '0' && ch <= '9'; } bool Lexer::isAlpha(char ch) const { return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_'; } + bool Lexer::match(char ch) { - if (isAtLineEnd() || ch != *current) { + if (isAtEnd() || ch != *current) { return false; } @@ -20,24 +18,12 @@ bool Lexer::match(char ch) { return true; } -void Lexer::goToNextLine() { - std::getline(stream, currentLine); - current = currentLine.begin(); - start = currentLine.begin(); -} - char Lexer::peek() const { return *current; } char Lexer::peekNext() const { return *(current + 1); } -char Lexer::advance() { - if (isAtLineEnd()) { - if (isAtEnd()) { - return '\0'; - } - - std::getline(stream, currentLine); - current = currentLine.begin(); - return *current; +char Lexer::advance() { + if (isAtEnd()) { + return '\0'; } return *(current++); @@ -136,11 +122,11 @@ std::shared_ptr Lexer::makeToken(TokenType type, std::string value) { if (value != "") { return std::make_shared(type, value, line, - start - currentLine.begin(), filename); + current-start, filename); } return std::make_shared(type, std::string(start, current), line, - start - currentLine.begin(), filename); + current-start, filename); } std::shared_ptr Lexer::makeNumberToken() { @@ -169,13 +155,13 @@ std::shared_ptr Lexer::makeIdentifierToken() { std::shared_ptr Lexer::makeErrorToken(std::string msg) { hadError = true; return std::make_shared(TokenType::Error, msg, line, - start - currentLine.begin(), filename); + current-start, filename); } void Lexer::skipWhitespace() { do { switch (peek()) { - case '\0': + case '\n': line++; case ' ': case '\r': @@ -183,7 +169,7 @@ void Lexer::skipWhitespace() { advance(); break; case '#': - while (!isAtLineEnd()) { + while (peek() != '\n') { advance(); } @@ -236,8 +222,7 @@ std::shared_ptr Lexer::getNextToken() { if (match('|')) { return makeToken(TokenType::Or); } - return makeErrorToken("Invalid operator '|' in: `" + currentLine + - "`.\n\tDid you mean '|\033[4;32m|\033[0m'?"); + return makeErrorToken("Invalid token '" + std::to_string(*current) + "'."); case '-': return makeToken(TokenType::Minus); case '+': @@ -277,7 +262,6 @@ std::shared_ptr Lexer::getNextToken() { if (!match('\'')) { auto res = makeErrorToken("A char can't be more then one character long."); - goToNextLine(); return res; } return makeToken(TokenType::Char, val); @@ -285,7 +269,7 @@ std::shared_ptr Lexer::getNextToken() { case '"': { std::string lexeme; - while (peek() != '"' && !isAtLineEnd()) { + while (peek() != '"' && !isAtEnd()) { if (peek() == '\\') { advance(); @@ -316,7 +300,7 @@ std::shared_ptr Lexer::getNextToken() { } } - if (isAtLineEnd()) { + if (isAtEnd()) { return makeErrorToken("Unterminated string."); } @@ -333,5 +317,5 @@ std::shared_ptr Lexer::getNextToken() { } int Lexer::getLine() { return line; } -int Lexer::getColumn() { return current - currentLine.begin(); } +int Lexer::getColumn() { return current - start; } std::string Lexer::getFilename() { return filename; } diff --git a/src/main.cpp b/src/main.cpp index e2de6ed..6a90ea6 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,28 @@ #include "main.h" +#include +#include +#include +#include +#include int main(const int argc, const char **argv) { if (argc < 2) { - std::cerr << "\033[1;31mNot enough arguemnts.\tUsage: lbpl [script]" << std::endl; + std::cerr << "\033[1;31mNot enough arguemnts.\tUsage: lbpl [script]" + << std::endl; return 1; } - std::ifstream sourceFile(argv[1]); - std::string filename(argv[1]); - if (!sourceFile.is_open()) { - std::cerr << "Error opening the file." << std::endl; - return 1; + int fd = open(argv[1], O_RDONLY, S_IRUSR | S_IWUSR); + struct stat sb; + + if (fstat(fd, &sb) == -1) { + perror("Couldn't get file size.\n"); } - Parser *parser = new Parser(sourceFile, filename); + char *file_in_memory = + (char *)mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + + Parser *parser = new Parser(file_in_memory, argv[1]); std::vector> statements = parser->parse(); // AST_Printer test; @@ -35,5 +44,6 @@ int main(const int argc, const char **argv) { } delete parser; - sourceFile.close(); + munmap(file_in_memory, sb.st_size); + close(fd); } diff --git a/src/parser.cpp b/src/parser.cpp index 7edf294..d94e9e6 100755 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,32 +1,11 @@ #include "parser.h" - -// static size_t totalMem = 0; -// void *operator new(size_t size) { -// totalMem += size; -// void *ptr = malloc(size + sizeof(size_t)); -// if (ptr) { -// *((size_t *)ptr) = size; -// return (char *)ptr + sizeof(size_t); -// } else { -// throw std::bad_alloc(); -// } -// // return malloc(size); -// } - -// void operator delete(void *ptr) noexcept { -// if (ptr) { -// size_t *originalPtr = (size_t *)((char *)ptr - sizeof(size_t)); -// size_t size = *originalPtr; -// totalMem -= size; -// free(originalPtr); -// } -// } +#include +#include +#include std::vector> Parser::parse() { std::vector> stmts; - // { - // Timer timer; while (!isAtEnd()) { try { if (match(TokenType::Import)) { @@ -42,9 +21,7 @@ std::vector> Parser::parse() { synchronize(); } } - // } - // std::cout << totalMem << "B\n"; return stmts; } @@ -73,12 +50,20 @@ std::vector> Parser::importStmt() { } importedFiles.insert(path->lexeme); - std::ifstream sourceFile(path->lexeme); - if (!sourceFile.is_open()) { - throw SyntaxError(previous.get(), "Error opening file: '" + path->lexeme + - "'.\nIs the path correct?"); + int fd = open(path->lexeme.c_str(), O_RDONLY, S_IRUSR | S_IWUSR); + struct stat sb; + + if (fstat(fd, &sb) == -1) { + perror("Couldn't get file size.\n"); } + char *sourceFile = + (char *)mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + + CONSUME_SEMICOLON("import"); + + return (new Parser(sourceFile, path->lexeme, importedFiles))->parse(); + CONSUME_SEMICOLON("import"); return (new Parser(sourceFile, path->lexeme, importedFiles))->parse();