From e8206d762c22c0b048e5f1f58d20176380c63cef Mon Sep 17 00:00:00 2001 From: Riyyi Date: Thu, 31 Aug 2023 21:58:44 +0200 Subject: [PATCH] Env: Load lisp code at runtime from files --- CMakeLists.txt | 8 ++++++++ cmake/copy-lisp.cmake | 1 + lisp/compare.bl | 12 ++++++++++++ lisp/init.bl | 14 ++++++++++++++ lisp/load.bl | 10 ++++++++++ lisp/other.bl | 6 ++++++ lisp/predicate.bl | 7 +++++++ src/env/environment.cpp | 36 +++++++++++++++++++++++++++++++++++- src/env/environment.h | 2 ++ src/repl.cpp | 22 ---------------------- 10 files changed, 95 insertions(+), 23 deletions(-) create mode 100644 cmake/copy-lisp.cmake create mode 100644 lisp/compare.bl create mode 100644 lisp/init.bl create mode 100644 lisp/load.bl create mode 100644 lisp/other.bl create mode 100644 lisp/predicate.bl diff --git a/CMakeLists.txt b/CMakeLists.txt index ec8f84a..7ea0374 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,14 @@ add_executable(${PROJECT} ${PROJECT_SOURCES}) target_include_directories(${PROJECT} PRIVATE "src") target_link_libraries(${PROJECT} readline ruc) +# ------------------------------------------ +# Std target + +add_custom_target(${PROJECT}-lisp + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/copy-lisp.cmake + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_dependencies(${PROJECT} ${PROJECT}-lisp) + # ------------------------------------------ # Execute target diff --git a/cmake/copy-lisp.cmake b/cmake/copy-lisp.cmake new file mode 100644 index 0000000..a990307 --- /dev/null +++ b/cmake/copy-lisp.cmake @@ -0,0 +1 @@ +file(COPY ${CMAKE_CURRENT_LIST_DIR}/../lisp DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/lisp/compare.bl b/lisp/compare.bl new file mode 100644 index 0000000..4ac1120 --- /dev/null +++ b/lisp/compare.bl @@ -0,0 +1,12 @@ + +(defmacro! cond (fn* [& xs] + (if (> (count xs) 0) + (list 'if (first xs) + (if (> (count xs) 1) + (nth xs 1) + (throw "odd number of forms to cond")) + (cons 'cond (rest (rest xs))))))) + +;; Local Variables: +;; eval: (emacs-lisp-mode) +;; End: diff --git a/lisp/init.bl b/lisp/init.bl new file mode 100644 index 0000000..993c140 --- /dev/null +++ b/lisp/init.bl @@ -0,0 +1,14 @@ + +(defmacro! defmacro + (fn* [name args & body] + `(defmacro! ~name (fn* ~args (do ~@body))))) + +(defmacro defn [name args & body] + `(def! ~name (fn* ~args (do ~@body)))) + +(defmacro def [name & body] + `(def! ~name ~@body)) + +;; Local Variables: +;; eval: (emacs-lisp-mode) +;; End: diff --git a/lisp/load.bl b/lisp/load.bl new file mode 100644 index 0000000..5fa377f --- /dev/null +++ b/lisp/load.bl @@ -0,0 +1,10 @@ + +(defn load-file [filename] + (eval (read-string (str "(do " (slurp filename) "\nnil)")))) + +(defn load [filename] + (eval (read-string (str "(let* [] (do " (slurp filename) "))")))) + +;; Local Variables: +;; eval: (emacs-lisp-mode) +;; End: diff --git a/lisp/other.bl b/lisp/other.bl new file mode 100644 index 0000000..2dbf38d --- /dev/null +++ b/lisp/other.bl @@ -0,0 +1,6 @@ + +(def! *host-language* "C++") + +;; Local Variables: +;; eval: (emacs-lisp-mode) +;; End: diff --git a/lisp/predicate.bl b/lisp/predicate.bl new file mode 100644 index 0000000..93df0b1 --- /dev/null +++ b/lisp/predicate.bl @@ -0,0 +1,7 @@ + +(defn not [cond] + (if cond false true)) + +;; Local Variables: +;; eval: (emacs-lisp-mode) +;; End: diff --git a/src/env/environment.cpp b/src/env/environment.cpp index 956fdae..c6f9a83 100644 --- a/src/env/environment.cpp +++ b/src/env/environment.cpp @@ -4,8 +4,11 @@ * SPDX-License-Identifier: MIT */ -#include // std::static_pointer_cast +#include +#include // std::distance +#include // std::static_pointer_cast +#include "ruc/file.h" #include "ruc/format/format.h" #include "ast.h" @@ -16,6 +19,7 @@ namespace blaze { std::unordered_map Environment::s_functions; +std::vector Environment::s_lambdas; EnvironmentPtr Environment::create() { @@ -86,6 +90,32 @@ void Environment::loadFunctions() loadOther(); loadPredicate(); loadRepl(); + + // Load std files + + std::filesystem::path std = "./lisp"; + if (!std::filesystem::exists(std) || !std::filesystem::is_directory(std)) { + return; + } + + s_lambdas.reserve(std::distance(std::filesystem::directory_iterator(std), {})); + for (const auto& entry : std::filesystem::directory_iterator(std)) { + if (!std::filesystem::is_regular_file(entry.path()) + || entry.path().extension().string() != ".bl") { + continue; + } + + std::filesystem::path filename = entry.path().filename(); + ruc::File file((std / filename).string()); + + // The init will be added to the front and executed first + if (filename.string() == "init.bl") { + s_lambdas.emplace(s_lambdas.begin(), file.data()); + } + else { + s_lambdas.push_back(file.data()); + } + } } void Environment::registerFunction(const std::string& name, FunctionType function) @@ -98,6 +128,10 @@ void Environment::installFunctions(EnvironmentPtr env) for (const auto& [name, function] : s_functions) { env->set(name, makePtr(name, function)); } + for (const auto& lambda : s_lambdas) { + // Ensure all s-exprs are run with (do) + eval(read("(do " + lambda + ")"), env); + } } // ----------------------------------------- diff --git a/src/env/environment.h b/src/env/environment.h index ebacea2..2b56445 100644 --- a/src/env/environment.h +++ b/src/env/environment.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "ast.h" #include "forward.h" @@ -53,6 +54,7 @@ private: std::unordered_map m_values; static std::unordered_map s_functions; + static std::vector s_lambdas; }; } // namespace blaze diff --git a/src/repl.cpp b/src/repl.cpp index 8e83710..4d5a483 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -89,27 +89,6 @@ static auto rep(std::string_view input, EnvironmentPtr env) -> std::string return print(eval(read(input), env)); } -static std::string_view lambdaTable[] = { - "(def! not (fn* (cond) (if cond false true)))", - "(def! load-file (fn* (filename) \ - (eval (read-string (str \"(do \" (slurp filename) \"\nnil)\")))))", - "(defmacro! cond (fn* (& xs) \ - (if (> (count xs) 0) \ - (list 'if (first xs) \ - (if (> (count xs) 1) \ - (nth xs 1) \ - (throw \"odd number of forms to cond\")) \ - (cons 'cond (rest (rest xs)))))))", - "(def! *host-language* \"C++\")", -}; - -static auto installLambdas(EnvironmentPtr env) -> void -{ - for (auto function : lambdaTable) { - rep(function, env); - } -} - static auto makeArgv(EnvironmentPtr env, std::vector arguments) -> void { size_t count = arguments.size(); @@ -151,7 +130,6 @@ auto main(int argc, char* argv[]) -> int blaze::Environment::loadFunctions(); blaze::Environment::installFunctions(blaze::s_outer_env); - installLambdas(blaze::s_outer_env); makeArgv(blaze::s_outer_env, arguments); if (arguments.size() > 0) {