From 240c91a4826fa60b842e471aa98f789d09563062 Mon Sep 17 00:00:00 2001 From: Aman Date: Tue, 25 Jun 2024 15:34:28 -0700 Subject: [PATCH] let done --- CMakeLists.txt | 10 +++++++- FindReadline.mk | 49 ++++++++++++++++++++++++++++++++++++++ include/ast/env.hh | 1 + include/reader/reader.hh | 4 +++- include/scanner/scanner.hh | 3 ++- lib/CMakeLists.txt | 1 + lib/ast/env.cc | 10 +++++--- lib/ast/parser.cc | 9 +++++-- lib/driver/driver.cc | 21 ++++++++++------ lib/scanner/scanner.cc | 4 ++-- 10 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 FindReadline.mk diff --git a/CMakeLists.txt b/CMakeLists.txt index 9941990..31dba34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # sets targets include(Options.mk) +include(FindReadline.mk) # "#includes" include_directories(${CMAKE_SOURCE_DIR}/include) @@ -49,4 +50,11 @@ include_directories(${gmock_SOURCE_DIR}/include ${gmock_SOURCE_DIR}) # add_subdirectory(external/abseil) # find_package(absl REQUIRED) # include_directories(${abseil_SOURCE_DIR}) -# target_link_libraries(riftlang absl::base absl::synchronization absl::strings) \ No newline at end of file +# target_link_libraries(riftlang absl::base absl::synchronization absl::strings) + +#readline library for interpreter +# find_package(Readline REQUIRED) +# if READLINE_FOUND is false then fail +if(NOT READLINE_FOUND) + message(FATAL_ERROR "Readline not found") +endif() \ No newline at end of file diff --git a/FindReadline.mk b/FindReadline.mk new file mode 100644 index 0000000..6261923 --- /dev/null +++ b/FindReadline.mk @@ -0,0 +1,49 @@ +# Code copied from sethhall@github +# +# - Try to find readline include dirs and libraries +# +# Usage of this module as follows: +# +# find_package(Readline) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# Readline_ROOT_DIR Set this variable to the root installation of +# readline if the module has problems finding the +# proper installation path. +# +# Variables defined by this module: +# +# READLINE_FOUND System has readline, include and lib dirs found +# Readline_INCLUDE_DIR The readline include directories. +# Readline_LIBRARY The readline library. + +find_path(Readline_ROOT_DIR + NAMES include/readline/readline.h +) + +find_path(Readline_INCLUDE_DIR + NAMES readline/readline.h + HINTS ${Readline_ROOT_DIR}/include +) + +find_library(Readline_LIBRARY + NAMES readline + HINTS ${Readline_ROOT_DIR}/lib +) + +if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) + set(READLINE_FOUND TRUE) +else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) + FIND_LIBRARY(Readline_LIBRARY NAMES readline) + include(FindPackageHandleStandardArgs) + FIND_PACKAGE_HANDLE_STANDARD_ARGS(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY ) + MARK_AS_ADVANCED(Readline_INCLUDE_DIR Readline_LIBRARY) +endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY) + +mark_as_advanced( + Readline_ROOT_DIR + Readline_INCLUDE_DIR + Readline_LIBRARY +) \ No newline at end of file diff --git a/include/ast/env.hh b/include/ast/env.hh index b7f3023..40e68ef 100644 --- a/include/ast/env.hh +++ b/include/ast/env.hh @@ -36,6 +36,7 @@ namespace rift } Token getEnv(const str_t& name) const; void setEnv(const str_t& name, const Token& value); + void printState(); protected: // absl::flat_hash_map values; std::unordered_map values = {}; diff --git a/include/reader/reader.hh b/include/reader/reader.hh index 08be4ca..2eff802 100644 --- a/include/reader/reader.hh +++ b/include/reader/reader.hh @@ -50,7 +50,9 @@ namespace rift // inline typename std::enable_if::value, T>::type advance() { return (!atEnd()) ? source->at(curr++) : nullptr; } /// @brief Peeks at the current character - inline bool peek(T expected) { return !atEnd() && source->at(curr) == expected; }; + inline bool peek(T expected) { + return !atEnd() && source->at(curr) == expected; + }; /// @brief Peeks at the current character with an offset inline bool peek_off(T expected, int offset) { return curr+offsetsize() && source->at(curr+offset) == expected; }; /// @brief Peeks at the current character diff --git a/include/scanner/scanner.hh b/include/scanner/scanner.hh index 3aa71a5..7114d95 100644 --- a/include/scanner/scanner.hh +++ b/include/scanner/scanner.hh @@ -67,7 +67,8 @@ namespace rift inline bool isDigit(char c) { return c>='0' && c<='9'; } inline bool isAlpha(char c) { return (c!=' ') && ( (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='_'); } - inline bool isAlphaNumeric(char c) { return isAlpha(c) || isDigit(c); } + inline bool isAlphaNumeric(char c) { return std::isalnum(c); } + inline bool isIdentifier(char c) { return std::isalnum(c) || c == '_'; } #pragma mark - Token Scanners diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 47d7e30..7d94051 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -46,6 +46,7 @@ add_executable( target_compile_options(riftlang PRIVATE -Wno-gcc-compat) target_compile_definitions(riftlang PRIVATE ABSL_USES_STD_ANY=1) +target_link_libraries(riftlang PRIVATE Readline) # target_link_libraries(riftlang absl::base absl::strings absl::hash absl::algorithm absl::memory absl::flat_hash_map absl::container_common absl::container_memory) add_library(riftlib STATIC ${SOURCES}) diff --git a/lib/ast/env.cc b/lib/ast/env.cc index af4134c..0e6b662 100644 --- a/lib/ast/env.cc +++ b/lib/ast/env.cc @@ -24,9 +24,6 @@ namespace rift // if(tok == Token()) // rift::error::runTimeError("🛑 Undefined variable '" + name + "'"); // } - for (const auto& [key, value] : values) { - std::cout << key << " => " << value.to_string() << std::endl; - } if (!values.contains(name)) { return Token(); } @@ -37,5 +34,12 @@ namespace rift { values[name] = value; } + + void Environment::printState() + { + for (const auto& [key, value] : values) { + std::cout << key << " => " << value.to_string() << std::endl; + } + } } } \ No newline at end of file diff --git a/lib/ast/parser.cc b/lib/ast/parser.cc index 4cc1487..538ee48 100644 --- a/lib/ast/parser.cc +++ b/lib/ast/parser.cc @@ -57,10 +57,11 @@ namespace rift if (match({Token(TokenType::IDENTIFIER, "", "", line)})) { /// @note rhs identifier undeclared auto idt = peekPrev(1); - if (rift::ast::Environment::getInstance().getEnv(castString(idt)) == Token()) { + auto val = rift::ast::Environment::getInstance().getEnv(castString(idt)); + if (val == Token()) { rift::error::report(line, "primary", "🛑 Undefined variable '" + castString(idt) + "' at line: " + castNumberString(idt.line), idt, ParserException("Undefined variable '" + castString(idt) + "'")); } - return std::unique_ptr(new Literal(Token(peekPrev(1)))); + return std::unique_ptr(new Literal(Token(val))); } if (match({Token(TokenType::LEFT_PAREN, "(", "", line)})) { @@ -154,6 +155,10 @@ namespace rift std::unique_ptr Parser::assignment() { if (match({Token(TokenType::IDENTIFIER, "", "", line)})) { + if (peek(Token(TokenType::SEMICOLON, ";", "", line))) { + prevance(); + return equality(); + } auto idt = peekPrev(); consume(Token(TokenType::EQUAL, "=", "", line), std::unique_ptr(new ParserException("Expected '=' after variable name"))); auto expr = assignment(); diff --git a/lib/driver/driver.cc b/lib/driver/driver.cc index f59f5fb..16da5d9 100644 --- a/lib/driver/driver.cc +++ b/lib/driver/driver.cc @@ -27,6 +27,9 @@ #include #include +#include +#include + using namespace rift::error; using namespace rift::scanner; using namespace rift::ast; @@ -51,6 +54,7 @@ namespace rift Eval riftEvaluator; riftEvaluator.evaluate(*statements); + rift::ast::Environment::getInstance().printState(); } void Driver::runFile() @@ -85,14 +89,17 @@ namespace rift void Driver::runPrompt() { - while(true) - { - std::string input = ""; - std::cout << "🦊 > "; - std::getline(std::cin >> std::ws, input); - if (input.empty()) break; + rl_bind_key('\t', rl_complete); + while(true) { + char* input = readline("🦊 > "); + if (input == nullptr) break; + add_history(input); + run(input); - errorOccured = false; // reset error + + // reset + errorOccured = false; + free(input); } } diff --git a/lib/scanner/scanner.cc b/lib/scanner/scanner.cc index aee3168..b33c05b 100644 --- a/lib/scanner/scanner.cc +++ b/lib/scanner/scanner.cc @@ -46,7 +46,7 @@ namespace rift keywords["super"] = Type::SUPER; keywords["this"] = Type::THIS; keywords["true"] = Type::TRUE; - keywords["var"] = Type::VAR; + keywords["let"] = Type::VAR; keywords["while"] = Type::WHILE; } @@ -94,7 +94,7 @@ namespace rift } void Scanner::identifier() { - while (isAlphaNumeric(advance())); + while (isIdentifier(peek())) advance(); std::string text = std::string(source->begin()+start, source->begin()+curr); text.erase(std::remove_if(text.begin(), text.end(), ::isspace), text.end()); if (keywords.find(text)!= keywords.end()) {