]> git.leonardobizzoni.com Git - LBPL/commitdiff
Memory mapped source file
authorLeonardoBizzoni <leo2002714@gmail.com>
Mon, 23 Oct 2023 16:36:27 +0000 (18:36 +0200)
committerLeonardoBizzoni <leo2002714@gmail.com>
Mon, 23 Oct 2023 16:36:27 +0000 (18:36 +0200)
lib/lexer.h
lib/parser.h
src/interpreter.cpp
src/lexer.cpp
src/main.cpp
src/parser.cpp

index 7a3d68fbce1c6c46df8cc86f80fa7b6c1cef72dc..c116a22510b77d11a99fe2567afcdcd2c72106f8 100755 (executable)
 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();
index daa8b76fed300559663dcf84ac393f1a830848cf..943849bef4746553e751917d84b9fb003edadf9a 100755 (executable)
@@ -65,13 +65,13 @@ private:
   std::unique_ptr<Expr> 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<std::string> &importedFiles)
       : importedFiles(importedFiles), lexer(new Lexer(file, filename)),
         current(lexer->getNextToken()), previous(current) {}
index 42432bdf761221f6e6754f61110b61e83457f720..ff68f4ab238a618d8aed904e86ca8ecbde6bb16a 100644 (file)
@@ -5,41 +5,13 @@
 #include "LBPLTypes.h"
 #include "runtime_error.h"
 
-#include <chrono>
 #include <cstddef>
 #include <map>
 #include <memory>
 #include <string>
 #include <variant>
-class Timer {
-  std::chrono::time_point<std::chrono::high_resolution_clock> 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<std::chrono::microseconds>(
-                     m_startTimepoint)
-                     .time_since_epoch()
-                     .count();
-    auto end =
-        std::chrono::time_point_cast<std::chrono::microseconds>(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<std::unique_ptr<Stmt>> &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<int>(left) &&
-   * std::holds_alternative<int>(right)) { */
-  /*   return performBinaryOperation(expr->op.get(), std::get<int>(left), */
-  /*                                 std::get<int>(right)); */
-  /* } else if (std::holds_alternative<double>(left) && */
-  /*            std::holds_alternative<double>(right)) { */
-  /*   return performBinaryOperation(expr->op.get(), std::get<double>(left), */
-  /*                                 std::get<double>(right)); */
-  /* } else if (std::holds_alternative<double>(left) && */
-  /*            std::holds_alternative<int>(right)) { */
-  /*   return performBinaryOperation(expr->op.get(), std::get<double>(left), */
-  /*                                 std::get<int>(right)); */
-  /* } else if (std::holds_alternative<int>(left) && */
-  /*            std::holds_alternative<double>(right)) { */
-  /*   return performBinaryOperation(expr->op.get(), std::get<int>(left), */
-  /*                                 std::get<double>(right)); */
-  /* } else if ((std::holds_alternative<std::string>(left) || */
-  /*             std::holds_alternative<std::string>(right)) && */
-  /*            expr->op->type == TokenType::Plus) { */
-  /*   if (std::holds_alternative<std::string>(left) && */
-  /*       std::holds_alternative<std::string>(right)) { */
-  /*     return std::get<std::string>(left) + */
-  /*                     std::get<std::string>(right); */
-  /*   } else if (std::holds_alternative<std::string>(left) && */
-  /*              std::holds_alternative<int>(right)) { */
-  /*     return std::get<std::string>(left) + */
-  /*                     std::to_string(std::get<int>(right)); */
-  /*   } else if (std::holds_alternative<int>(left) && */
-  /*              std::holds_alternative<std::string>(right)) { */
-  /*     return std::get<std::string>(left) + */
-  /*                     std::to_string(std::get<double>(right)); */
-  /*   } else if (std::holds_alternative<double>(left) && */
-  /*              std::holds_alternative<std::string>(right)) { */
-  /*     return std::to_string(std::get<double>(left)) + */
-  /*                     std::get<std::string>(right); */
-  /*   } else if (std::holds_alternative<std::string>(left) && */
-  /*              std::holds_alternative<char>(right)) { */
-  /*     return std::get<std::string>(left) + std::get<char>(right); */
-  /*   } else if (std::holds_alternative<char>(left) && */
-  /*              std::holds_alternative<std::string>(right)) { */
-  /*     return std::get<char>(left) + std::get<std::string>(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<std::shared_ptr<LBPLInstance>>(instance)) {
-    return std::get<std::shared_ptr<LBPLInstance>>(instance)->get(expr->field.get());
+    return std::get<std::shared_ptr<LBPLInstance>>(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<std::shared_ptr<LBPLInstance>>(instance)) {
     LBPLType value = expr->value->accept(this);
-    std::get<std::shared_ptr<LBPLInstance>>(instance)->set(expr->field.get(), value);
+    std::get<std::shared_ptr<LBPLInstance>>(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<const Token> &op,
       left, right);
 }
 
-/* template <typename T, typename G> */
-/* 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<std::unique_ptr<Stmt>> &body,
                                std::shared_ptr<Environment> &&env) {
   executeBlock(body, env);
index 098bd9ad43bf0389c07c04ff1a7bd1f98880f8b7..adde981f23926e1419f5bd9cb67b975172f7eeb4 100755 (executable)
@@ -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<const Token> Lexer::makeToken(TokenType type,
                                               std::string value) {
   if (value != "") {
     return std::make_shared<const Token>(type, value, line,
-                                         start - currentLine.begin(), filename);
+                                         current-start, filename);
   }
 
   return std::make_shared<const Token>(type, std::string(start, current), line,
-                                       start - currentLine.begin(), filename);
+                                       current-start, filename);
 }
 
 std::shared_ptr<const Token> Lexer::makeNumberToken() {
@@ -169,13 +155,13 @@ std::shared_ptr<const Token> Lexer::makeIdentifierToken() {
 std::shared_ptr<const Token> Lexer::makeErrorToken(std::string msg) {
   hadError = true;
   return std::make_shared<const Token>(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<const Token> 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<const Token> 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<const Token> Lexer::getNextToken() {
   case '"': {
     std::string lexeme;
 
-    while (peek() != '"' && !isAtLineEnd()) {
+    while (peek() != '"' && !isAtEnd()) {
       if (peek() == '\\') {
         advance();
 
@@ -316,7 +300,7 @@ std::shared_ptr<const Token> Lexer::getNextToken() {
       }
     }
 
-    if (isAtLineEnd()) {
+    if (isAtEnd()) {
       return makeErrorToken("Unterminated string.");
     }
 
@@ -333,5 +317,5 @@ std::shared_ptr<const Token> 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; }
index e2de6ed43d29fd29cec1a41de0a65899ed6561b9..6a90ea6bebc0992dbbcd85c6b77d5d81971e10e4 100755 (executable)
@@ -1,19 +1,28 @@
 #include "main.h"
+#include <fcntl.h>
+#include <iostream>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
 
 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<std::unique_ptr<Stmt>> 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);
 }
index 7edf2941e7c07343cbc20274c13f4d15e5016757..d94e9e606df09e0898f03b8e1d2a5187001decd2 100755 (executable)
@@ -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 <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 
 std::vector<std::unique_ptr<Stmt>> Parser::parse() {
   std::vector<std::unique_ptr<Stmt>> stmts;
 
-  // {
-  //   Timer timer;
   while (!isAtEnd()) {
     try {
       if (match(TokenType::Import)) {
@@ -42,9 +21,7 @@ std::vector<std::unique_ptr<Stmt>> Parser::parse() {
       synchronize();
     }
   }
-  // }
 
-  // std::cout << totalMem << "B\n";
   return stmts;
 }
 
@@ -73,12 +50,20 @@ std::vector<std::unique_ptr<Stmt>> 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();