-cmake_minimum_required (VERSION 3.26.4)
-
-add_compile_options(-O2)
+cmake_minimum_required(VERSION 3.29)
+project(lbpl CXX)
+# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-project (lbpl VERSION 0.1.0)
-include_directories(lib)
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "Debug")
+endif()
+
+# Set output directories
+set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}-${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}")
+
+file(GLOB_RECURSE SRC "src/*.cpp" "src/*.hpp")
+add_executable(${PROJECT_NAME} ${SRC})
+
+set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
+target_compile_definitions(${PROJECT_NAME} PRIVATE ROOTDIR="${CMAKE_SOURCE_DIR}")
+
+# Set output directories
+set_target_properties(${PROJECT_NAME} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY "${OUTPUT_DIR}"
+ ARCHITE_OUTPUT_DIRECTORY "${OUTPUT_DIR}"
+ LIBRARY_OUTPUT_DIRECTORY "${OUTPUT_DIR}")
+
+# Configuration-specific settings
+target_compile_definitions(${PROJECT_NAME} PRIVATE
+ $<$<CONFIG:Debug>:DEBUG>
+ $<$<CONFIG:OptimizedDebug>:OPTDEBUG>
+ $<$<CONFIG:Release>:RELEASE>)
-file(GLOB SRCFILES src/*.cpp)
-add_executable(${PROJECT_NAME} ${SRCFILES})
+# Configuration-specific optimizations
+target_compile_options(${PROJECT_NAME} PRIVATE
+ $<$<CONFIG:Debug>:-g>
+ $<$<CONFIG:OptimizedDebug>:-O3>
+ $<$<CONFIG:Release>:-O3>)
+++ /dev/null
-#ifndef RUNTIME_ERROR_H
-#define RUNTIME_ERROR_H
-
-#include "token.h"
-#include "expressions.h"
-#include "statements.h"
-
-#include <string>
-#include <optional>
-#include <iomanip>
-#include <sstream>
-
-struct RuntimeError {
-public:
- int line;
- int column;
- std::string filename;
- std::string msg;
-
-public:
- RuntimeError(const Token *errToken, const std::string &msg)
- : line(errToken->line), column(errToken->column), filename(errToken->filename), msg(msg) {}
-
- RuntimeError(Expr *errToken, const std::string &msg)
- : line(errToken->line), column(errToken->column), filename(errToken->file), msg(msg) {}
-
- RuntimeError(Stmt *errToken, const std::string &msg)
- : line(errToken->line), column(errToken->column), filename(errToken->filename), msg(msg) {}
-
- std::string what();
-};
-
-#endif
--- /dev/null
+fn fib(n) {
+ return fibIter(n, 0, 1);
+}
+
+fn fibIter(n, curr, next) {
+ if (n == 0) {
+ return curr;
+ } else if (n == 1) {
+ return next;
+ } else {
+ return fibIter(n - 1, next, curr + next);
+ }
+}
+
+class Prova {
+ init(n) {
+ this.n = n;
+ this.start = clock();
+ this.fib_n = fib(n);
+ this.end = clock();
+ }
+
+ runtime() {
+ println("fib("+ this.n +") = " +
+ this.fib_n +
+ " runtime: " +
+ (this.end - this.start));
+ }
+}
+
+let a = Prova(25);
+a.var1 = 10;
+println(a.var1);
+a.var1 = 210;
+println(a.var1);
+
+a.runtime();
\ No newline at end of file
--- /dev/null
+{ pkgs ? import <nixpkgs> { } }:
+
+pkgs.mkShell {
+ nativeBuildInputs = with pkgs; [
+ man-pages
+ man-pages-posix
+
+ gnumake
+ cmake
+ seer
+ clang-tools
+ cmake-language-server
+ tree-sitter-grammars.tree-sitter-cpp
+ tree-sitter-grammars.tree-sitter-c
+ ];
+
+ shellHook = ''
+ ${pkgs.onefetch}/bin/onefetch
+ '';
+}
#ifndef LBPL_CALLABLE_H
#define LBPL_CALLABLE_H
-#include "LBPLTypes.h"
+#include "LBPLTypes.hpp"
#include <vector>
class Interpreter;
-#include "LBPLClass.h"
-#include "LBPLInstance.h"
-#include "interpreter.h"
+#include "LBPLClass.hpp"
+#include "LBPLInstance.hpp"
+#include "interpreter.hpp"
Value LBPLClass::call(Interpreter *interpreter, std::vector<Value> &args) {
auto instance = std::make_shared<LBPLInstance>(this);
#ifndef LBPL_CLASS_H
#define LBPL_CLASS_H
-#include "LBPLCallable.h"
-#include "LBPLFunction.h"
+#include "LBPLCallable.hpp"
+#include "LBPLFunction.hpp"
#include <map>
#include <memory>
-#include "LBPLFunction.h"
-#include "interpreter.h"
+#include "LBPLFunction.hpp"
+#include "interpreter.hpp"
void LBPLFunc::bind(std::shared_ptr<LBPLInstance> &&instance) {
closureEnv = std::make_shared<Environment>();
#ifndef LBPL_FUNCTION_H
#define LBPL_FUNCTION_H
-#include "LBPLCallable.h"
-#include "environment.h"
-#include "statements.h"
+#include "LBPLCallable.hpp"
+#include "environment.hpp"
+#include "statements.hpp"
+
#include <memory>
class LBPLFunc : public LBPLCallable {
-#include "LBPLInstance.h"
+#include "LBPLInstance.hpp"
+#include "runtime_error.hpp"
Value LBPLInstance::get(const Token *name) {
if (fields.contains(name->lexeme)) {
#ifndef LBPL_INSTANCE_H
#define LBPL_INSTANCE_H
-#include "LBPLClass.h"
-#include "runtime_error.h"
+#include "LBPLClass.hpp"
#include <map>
-#include <memory>
class LBPLInstance {
private:
-#include "ast_printer.h"
-#include "statements.h"
+#include "ast_printer.hpp"
+#include "statements.hpp"
#include <iostream>
#ifndef AST_PRINTER_H
#define AST_PRINTER_H
-#include "tree_nodes.h"
-#include "visitor.h"
+#include "tree_nodes.hpp"
+#include "visitor.hpp"
class AST_Printer : public Statement::Visitor, public Expression::Visitor {
void printLocation(Stmt *);
#ifndef BUILTIN_METHODS_H
#define BUILTIN_METHODS_H
-#include "LBPLCallable.h"
-#include "statements.h"
+#include "LBPLCallable.hpp"
#include <chrono>
#include <iostream>
#ifndef COMMON_H
#define COMMON_H
-#include "token.h"
-#include "token_type.h"
+#include "token.hpp"
+#include "token_type.hpp"
#include <string>
#include <iostream>
-#include "environment.h"
-#include "LBPLTypes.h"
-#include "runtime_error.h"
+#include "environment.hpp"
+#include "LBPLTypes.hpp"
+#include "runtime_error.hpp"
+
#include <memory>
#include <string>
#include <utility>
#include <variant>
+#include <iostream>
void Environment::define(const std::string &name, Value &value) {
env.insert(std::make_pair(name, value));
env.insert(std::make_pair(name, value));
}
-
Value Environment::get(std::shared_ptr<const Token> &name) {
auto it = env.find(name->lexeme);
return enclosing->get(name);
}
- throw RuntimeError(name.get(), "Undefined name '"+name->lexeme+"'.");
+ throw RuntimeError(name.get(), "Undefined name '" + name->lexeme + "'.");
}
Value Environment::getAt(int depth, std::shared_ptr<const Token> &name) {
Value Environment::getAt(int depth, const std::string &name) {
if (depth > 0) {
- return enclosing->getAt(depth-1, name);
+ return enclosing->getAt(depth - 1, name);
}
auto it = env.find(name);
} else if (enclosing) {
enclosing->assign(name, value);
} else {
- throw RuntimeError(name.get(), "Undefined variable '"+name->lexeme+"'.");
+ throw RuntimeError(name.get(),
+ "Undefined variable '" + name->lexeme + "'.");
}
}
assign(name, value);
}
-void Environment::assignAt(int depth, std::shared_ptr<const Token> &name, Value &value) {
+void Environment::assignAt(int depth, std::shared_ptr<const Token> &name,
+ Value &value) {
if (depth > 0) {
- enclosing->assignAt(depth-1, name, value);
+ enclosing->assignAt(depth - 1, name, value);
}
env.insert_or_assign(name->lexeme, value);
}
void Environment::printEnv(const std::string &&msg) {
- std::cout << "========"<< msg <<"=========" << std::endl;
- for (const auto& [key, value] : env) {
+ std::cout << "========" << msg << "=========" << std::endl;
+ for (const auto &[key, value] : env) {
std::cout << "\t" << key << ": ";
if (std::holds_alternative<int>(value)) {
#ifndef ENVIRONMENT_H
#define ENVIRONMENT_H
-#include "LBPLTypes.h"
-#include "token.h"
-#include "tree_nodes.h"
+#include "LBPLTypes.hpp"
+#include "token.hpp"
#include <map>
#include <memory>
#include <string>
-#include <variant>
class Environment {
public:
#ifndef EXPRESSIONS_H
#define EXPRESSIONS_H
-#include "common.h"
-#include "token.h"
-#include "visitor.h"
+#include "token.hpp"
+
+#include "token.hpp"
+#include "visitor.hpp"
+#include <string>
-#include <cstdint>
#include <memory>
#include <vector>
Expr(int line, int column, const std::string &filename)
: line(line), column(column), file(filename) {}
- virtual ~Expr(){};
+ virtual ~Expr() {};
virtual Value accept(Expression::Visitor *) { return nullptr; }
};
public:
std::shared_ptr<const Token> keyword;
- ThisExpr(int line, int column, const std::string &file, std::shared_ptr<const Token>& keyword)
+ ThisExpr(int line, int column, const std::string &file,
+ std::shared_ptr<const Token> &keyword)
: keyword(keyword), Expr(line, column, file) {}
Value accept(Expression::Visitor *visitor) {
-#include "interpreter.h"
-#include "LBPLClass.h"
-#include "LBPLFunction.h"
-#include "LBPLInstance.h"
-#include "LBPLTypes.h"
-#include "runtime_error.h"
+#include "interpreter.hpp"
+#include "LBPLClass.hpp"
+#include "LBPLFunction.hpp"
+#include "LBPLInstance.hpp"
+#include "LBPLTypes.hpp"
+#include "runtime_error.hpp"
#include <cstddef>
#include <map>
#ifndef INTERPRETER_H
#define INTERPRETER_H
-#include "LBPLTypes.h"
-#include "builtin_methods.h"
-#include "environment.h"
-#include "runtime_error.h"
-#include "visitor.h"
+#include "LBPLTypes.hpp"
+#include "builtin_methods.hpp"
+#include "environment.hpp"
+#include "visitor.hpp"
#include <map>
#include <memory>
-#include "lexer.h"
+#include "lexer.hpp"
Lexer::Lexer(const char *stream, const std::string &filename)
: line(1), hadError(false), filename(filename), current(stream), start(stream) {}
#ifndef LEXER_H
#define LEXER_H
-#include "common.h"
+#include "token.hpp"
+#include "token_type.hpp"
-#include <fstream>
-#include <iomanip>
+#include <string>
#include <memory>
-#include <vector>
class Lexer {
private:
bool match(char ch);
public:
- Lexer(const char*, const std::string &);
+ Lexer(const char *, const std::string &);
int getLine();
int getColumn();
-#include "main.h"
#include <fcntl.h>
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
+#include "parser.hpp"
+#include "interpreter.hpp"
+#include "resolver.hpp"
+
int main(const int argc, const char **argv) {
if (argc < 2) {
std::cerr << "\033[1;31mNot enough arguemnts.\tUsage: lbpl [script]"
-#include "parser.h"
+#include "parser.hpp"
+#include "syntax_error.hpp"
+
#include <fcntl.h>
+#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
return std::make_unique<SuperExpr>(line, col, lexer->getFilename(), field);
} else if (match(TokenType::This)) {
- return std::make_unique<ThisExpr>(line, col, lexer->getFilename(), previous);
+ return std::make_unique<ThisExpr>(line, col, lexer->getFilename(),
+ previous);
} else if (match(TokenType::Identifier)) {
return std::make_unique<VariableExpr>(line, col, lexer->getFilename(),
previous);
case TokenType::If:
case TokenType::Return:
return;
+ default:
+ break;
}
advance();
#ifndef PARSER_H
#define PARSER_H
-#include "expressions.h"
-#include "lexer.h"
-#include "statements.h"
-#include "syntax_error.h"
+#include "expressions.hpp"
+#include "lexer.hpp"
+#include "statements.hpp"
-#include <fstream>
#include <memory>
#include <unordered_set>
#include <vector>
-#include "resolver.h"
+#include "resolver.hpp"
+#include "syntax_error.hpp"
void Resolver::resolve(std::vector<std::unique_ptr<Stmt>> &stmts) {
for (auto &&stmt : stmts) {
#ifndef RESOLVER_H
#define RESOLVER_H
-#include "environment.h"
-#include "interpreter.h"
-#include "statements.h"
-#include "syntax_error.h"
-#include "visitor.h"
+#include "interpreter.hpp"
+#include "statements.hpp"
+#include "visitor.hpp"
#include <map>
#include <memory>
-#include "runtime_error.h"
+#include "runtime_error.hpp"
+#include <sstream>
std::string RuntimeError::what() {
std::stringstream ss(msg);
--- /dev/null
+#ifndef RUNTIME_ERROR_H
+#define RUNTIME_ERROR_H
+
+#include "expressions.hpp"
+#include "statements.hpp"
+#include "token.hpp"
+
+#include <string>
+
+struct RuntimeError {
+public:
+ int line;
+ int column;
+ std::string filename;
+ std::string msg;
+
+public:
+ RuntimeError(const Token *errToken, const std::string &msg)
+ : line(errToken->line), column(errToken->column),
+ filename(errToken->filename), msg(msg) {}
+
+ RuntimeError(Expr *errToken, const std::string &msg)
+ : line(errToken->line), column(errToken->column),
+ filename(errToken->file), msg(msg) {}
+
+ RuntimeError(Stmt *errToken, const std::string &msg)
+ : line(errToken->line), column(errToken->column),
+ filename(errToken->filename), msg(msg) {}
+
+ std::string what();
+};
+
+#endif
#ifndef STATEMENTS_H
#define STATEMENTS_H
-#include "expressions.h"
-
+#include "expressions.hpp"
#include <memory>
-#include <optional>
-#include <utility>
struct Stmt {
std::string filename;
struct FnStmt : public Stmt {
std::shared_ptr<const Token> name;
- std::vector<std::shared_ptr<const Token> > args;
+ std::vector<std::shared_ptr<const Token>> args;
std::vector<std::unique_ptr<Stmt>> body;
- FnStmt(int line, int column, const std::string &file, std::shared_ptr<const Token> &name,
- std::vector<std::shared_ptr<const Token>> &args, std::vector<std::unique_ptr<Stmt>> &&body)
- : name(name), args(args), body(std::move(body)), Stmt(line, column, file) {}
+ FnStmt(int line, int column, const std::string &file,
+ std::shared_ptr<const Token> &name,
+ std::vector<std::shared_ptr<const Token>> &args,
+ std::vector<std::unique_ptr<Stmt>> &&body)
+ : name(name), args(args), body(std::move(body)),
+ Stmt(line, column, file) {}
void accept(Statement::Visitor *visitor) { visitor->visitFnStmt(this); }
};
std::shared_ptr<const Token> name;
std::unique_ptr<Expr> value;
- VarStmt(int line, int column, const std::string &file, std::shared_ptr<const Token> &name,
- std::unique_ptr<Expr> &value)
- : name(name), value(std::move(value)),
- Stmt(line, column, file) {}
+ VarStmt(int line, int column, const std::string &file,
+ std::shared_ptr<const Token> &name, std::unique_ptr<Expr> &value)
+ : name(name), value(std::move(value)), Stmt(line, column, file) {}
void accept(Statement::Visitor *visitor) { visitor->visitVarStmt(this); }
};
std::unique_ptr<VariableExpr> superclass;
std::vector<std::unique_ptr<Stmt>> body;
- ClassStmt(int line, int column, const std::string &file, std::shared_ptr<const Token> &name,
+ ClassStmt(int line, int column, const std::string &file,
+ std::shared_ptr<const Token> &name,
std::unique_ptr<VariableExpr> &superclass,
std::vector<std::unique_ptr<Stmt>> &&body)
: name(name), superclass(std::move(superclass)), body(std::move(body)),
std::unique_ptr<Stmt> falseBranch;
IfStmt(int line, int column, const std::string &file,
- std::unique_ptr<Expr> &condition,
- std::unique_ptr<Stmt> &trueBranch, std::unique_ptr<Stmt> &falseBranch)
+ std::unique_ptr<Expr> &condition, std::unique_ptr<Stmt> &trueBranch,
+ std::unique_ptr<Stmt> &falseBranch)
: condition(std::move(condition)), trueBranch(std::move(trueBranch)),
falseBranch(std::move(falseBranch)), Stmt(line, column, file) {}
-#include "syntax_error.h"
+#include "syntax_error.hpp"
+#include <sstream>
std::string SyntaxError::what() {
std::stringstream ss(msg);
#ifndef SYNTAX_ERROR_H
#define SYNTAX_ERROR_H
-#include "token.h"
-#include "expressions.h"
-#include "statements.h"
+#include "expressions.hpp"
+#include "statements.hpp"
+#include "token.hpp"
#include <string>
-#include <optional>
-#include <iomanip>
-#include <sstream>
struct SyntaxError {
public:
public:
SyntaxError(const Token *errToken, const std::string &msg)
- : line(errToken->line), column(errToken->column), filename(errToken->filename), msg(msg) {}
+ : line(errToken->line), column(errToken->column),
+ filename(errToken->filename), msg(msg) {}
SyntaxError(Expr *errExpr, const std::string &msg)
- : line(errExpr->line), column(errExpr->column), filename(errExpr->file), msg(msg) {}
+ : line(errExpr->line), column(errExpr->column), filename(errExpr->file),
+ msg(msg) {}
SyntaxError(Stmt *errStmt, const std::string &msg)
- : line(errStmt->line), column(errStmt->column), filename(errStmt->filename), msg(msg) {}
+ : line(errStmt->line), column(errStmt->column),
+ filename(errStmt->filename), msg(msg) {}
std::string what();
};
#ifndef TOKEN_H
#define TOKEN_H
-#include "token_type.h"
+#include "token_type.hpp"
#include <string>
#ifndef VISITOR_H
#define VISITOR_H
-#include "LBPLTypes.h"
-#include "tree_nodes.h"
-
-#include <iostream>
+#include "LBPLTypes.hpp"
+#include "tree_nodes.hpp"
namespace Statement {
struct Visitor {