Env: Load lisp code at runtime from files
This commit is contained in:
@@ -69,6 +69,14 @@ add_executable(${PROJECT} ${PROJECT_SOURCES})
|
|||||||
target_include_directories(${PROJECT} PRIVATE "src")
|
target_include_directories(${PROJECT} PRIVATE "src")
|
||||||
target_link_libraries(${PROJECT} readline ruc)
|
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
|
# Execute target
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
file(COPY ${CMAKE_CURRENT_LIST_DIR}/../lisp DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
@@ -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:
|
||||||
@@ -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:
|
||||||
@@ -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:
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
(def! *host-language* "C++")
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; eval: (emacs-lisp-mode)
|
||||||
|
;; End:
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
(defn not [cond]
|
||||||
|
(if cond false true))
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; eval: (emacs-lisp-mode)
|
||||||
|
;; End:
|
||||||
Vendored
+34
@@ -4,8 +4,11 @@
|
|||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iterator> // std::distance
|
||||||
#include <memory> // std::static_pointer_cast
|
#include <memory> // std::static_pointer_cast
|
||||||
|
|
||||||
|
#include "ruc/file.h"
|
||||||
#include "ruc/format/format.h"
|
#include "ruc/format/format.h"
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
@@ -16,6 +19,7 @@
|
|||||||
namespace blaze {
|
namespace blaze {
|
||||||
|
|
||||||
std::unordered_map<std::string, FunctionType> Environment::s_functions;
|
std::unordered_map<std::string, FunctionType> Environment::s_functions;
|
||||||
|
std::vector<std::string> Environment::s_lambdas;
|
||||||
|
|
||||||
EnvironmentPtr Environment::create()
|
EnvironmentPtr Environment::create()
|
||||||
{
|
{
|
||||||
@@ -86,6 +90,32 @@ void Environment::loadFunctions()
|
|||||||
loadOther();
|
loadOther();
|
||||||
loadPredicate();
|
loadPredicate();
|
||||||
loadRepl();
|
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)
|
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) {
|
for (const auto& [name, function] : s_functions) {
|
||||||
env->set(name, makePtr<Function>(name, function));
|
env->set(name, makePtr<Function>(name, function));
|
||||||
}
|
}
|
||||||
|
for (const auto& lambda : s_lambdas) {
|
||||||
|
// Ensure all s-exprs are run with (do)
|
||||||
|
eval(read("(do " + lambda + ")"), env);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------
|
// -----------------------------------------
|
||||||
|
|||||||
Vendored
+2
@@ -9,6 +9,7 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "ast.h"
|
#include "ast.h"
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
@@ -53,6 +54,7 @@ private:
|
|||||||
std::unordered_map<std::string, ValuePtr> m_values;
|
std::unordered_map<std::string, ValuePtr> m_values;
|
||||||
|
|
||||||
static std::unordered_map<std::string, FunctionType> s_functions;
|
static std::unordered_map<std::string, FunctionType> s_functions;
|
||||||
|
static std::vector<std::string> s_lambdas;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blaze
|
} // namespace blaze
|
||||||
|
|||||||
@@ -89,27 +89,6 @@ static auto rep(std::string_view input, EnvironmentPtr env) -> std::string
|
|||||||
return print(eval(read(input), env));
|
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<std::string> arguments) -> void
|
static auto makeArgv(EnvironmentPtr env, std::vector<std::string> arguments) -> void
|
||||||
{
|
{
|
||||||
size_t count = arguments.size();
|
size_t count = arguments.size();
|
||||||
@@ -151,7 +130,6 @@ auto main(int argc, char* argv[]) -> int
|
|||||||
|
|
||||||
blaze::Environment::loadFunctions();
|
blaze::Environment::loadFunctions();
|
||||||
blaze::Environment::installFunctions(blaze::s_outer_env);
|
blaze::Environment::installFunctions(blaze::s_outer_env);
|
||||||
installLambdas(blaze::s_outer_env);
|
|
||||||
makeArgv(blaze::s_outer_env, arguments);
|
makeArgv(blaze::s_outer_env, arguments);
|
||||||
|
|
||||||
if (arguments.size() > 0) {
|
if (arguments.size() > 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user