Skip to content

Commit

Permalink
feat(yakshalisp): add os_exec, os_shell
Browse files Browse the repository at this point in the history
  • Loading branch information
JaDogg committed Nov 29, 2023
1 parent f21c58d commit 22b4c8d
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 19 deletions.
18 changes: 17 additions & 1 deletion compiler/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_INSTALL_PREFIX build})
set(UTF8_DIR 3rd/utfcpp/source)
set(REPROC_DIR 3rd/reproc)

get_filename_component(CMAKE_BINARY_DIR "bin" ABSOLUTE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
Expand All @@ -18,9 +19,11 @@ file(COPY ${CMAKE_BINARY_DIR}/test.txt
include_directories(src)
include_directories(tests)
include_directories(${UTF8_DIR})
include_directories(${REPROC_DIR}/reproc/include)
include_directories(${REPROC_DIR}/reproc++/include)
# Add reproc
set(REPROC++ ON)
add_subdirectory(3rd/reproc)
add_subdirectory(${REPROC_DIR})

## Enable below to use address sanitizer
# add_compile_options(-O1 -g -fsanitize=address -fno-omit-frame-pointer)
Expand Down Expand Up @@ -50,19 +53,26 @@ endif()
add_executable(yakshac src/comp_main.cpp runtime/whereami.c)
target_link_libraries(yakshac PUBLIC ${SYS_LIBS})
target_link_libraries(yakshac PUBLIC library_yaksha)
target_link_libraries(yakshac PUBLIC reproc)
target_link_libraries(yakshac PUBLIC reproc++)
target_compile_features(yakshac PRIVATE cxx_std_17)

# -- yakshavz - visualizer --
add_executable(yakshavz src/viz_main.cpp)
target_link_libraries(yakshavz PUBLIC ${SYS_LIBS})
target_link_libraries(yakshavz PUBLIC library_yaksha)
target_compile_features(yakshavz PRIVATE cxx_std_17)
target_link_libraries(yakshavz PUBLIC reproc)
target_link_libraries(yakshavz PUBLIC reproc++)


# -- yakshadmp - syntax extractor --
add_executable(yakshadmp src/dump.cpp)
target_link_libraries(yakshadmp PUBLIC ${SYS_LIBS})
target_link_libraries(yakshadmp PUBLIC library_yaksha)
target_compile_features(yakshadmp PRIVATE cxx_std_17)
target_link_libraries(yakshadmp PUBLIC reproc++)


# -- ykreload - compiler --
if(MSVC)
Expand All @@ -74,6 +84,8 @@ endif (MSVC)
add_executable(yaksha src/yk.cpp src/carpntr_wrapper.cpp runtime/whereami.c)
target_link_libraries(yaksha PUBLIC ${SYS_LIBS})
target_link_libraries(yaksha PUBLIC library_yaksha)
target_link_libraries(yaksha PUBLIC reproc)
target_link_libraries(yaksha PUBLIC reproc++)
target_compile_features(yaksha PRIVATE cxx_std_17)

# -- raylib-parser - raylib-parser --
Expand All @@ -88,6 +100,8 @@ add_executable(YakshaTests ${YAKSHA_SOURCE_FILES} ${YAKSHA_TEST_FILES} tests/tes
target_compile_definitions(YakshaTests PUBLIC TESTING)
target_link_libraries(YakshaTests PRIVATE Catch2::Catch2)
target_link_libraries(YakshaTests PUBLIC ${SYS_LIBS})
target_link_libraries(YakshaTests PUBLIC reproc)
target_link_libraries(YakshaTests PUBLIC reproc++)
target_compile_features(YakshaTests PRIVATE cxx_std_17)
# Add to CTest
include(CTest)
Expand All @@ -104,6 +118,8 @@ else()
add_executable(YakshaFuzz tests/fuzz_main.cpp runtime/whereami.c)
endif()
target_link_libraries(YakshaFuzz PUBLIC ${SYS_LIBS})
target_link_libraries(YakshaFuzz PUBLIC reproc)
target_link_libraries(YakshaFuzz PUBLIC reproc++)
target_link_libraries(YakshaFuzz PUBLIC library_yaksha)
target_compile_features(YakshaFuzz PRIVATE cxx_std_17)

Expand Down
33 changes: 24 additions & 9 deletions compiler/src/utilities/cpp_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,12 @@
*/
#ifndef CPP_UTIL_H
#define CPP_UTIL_H
#include "reproc++/reproc.hpp"
#include "reproc++/run.hpp"
#include <algorithm>
#include <iostream>
#include <sstream>
#include <vector>
// ╔╦╗┌─┐┌┬┐┌─┐┬ ┌─┐┌┬┐┌─┐ ╔╦╗┌─┐┌─┐┬┌─┐
// ║ ├┤ │││├─┘│ ├─┤ │ ├┤ ║║║├─┤│ ┬││
// ╩ └─┘┴ ┴┴ ┴─┘┴ ┴ ┴ └─┘ ╩ ╩┴ ┴└─┘┴└─┘
Expand Down Expand Up @@ -149,21 +152,33 @@ namespace yaksha {
return s;
}
// https://stackoverflow.com/questions/5878775/how-to-find-and-replace-string
static inline void replace_all(std::string &s, std::string const &toReplace,
std::string const &replaceWith) {
static inline void replace_all(std::string &s, std::string const &to_replace,
std::string const &replace_with) {
std::ostringstream oss;
std::size_t pos = 0;
std::size_t prevPos = pos;
std::size_t prev_position = pos;
while (true) {
prevPos = pos;
pos = s.find(toReplace, pos);
prev_position = pos;
pos = s.find(to_replace, pos);
if (pos == std::string::npos) { break; }
oss << s.substr(prevPos, pos - prevPos);
oss << replaceWith;
pos += toReplace.size();
oss << s.substr(prev_position, pos - prev_position);
oss << replace_with;
pos += to_replace.size();
}
oss << s.substr(prevPos);
oss << s.substr(prev_position);
s = oss.str();
}
static int exec(std::vector<std::string> &cmd, int deadline_ms = -1) {
int status = -1;
std::error_code ec;
reproc::options options;
options.redirect.parent = true;
if (deadline_ms > 0) {
options.deadline = reproc::milliseconds(deadline_ms);
}
// std::tie is like unpacking a tuple
std::tie(status, ec) = reproc::run(cmd, options);
return ec ? ec.value() : status;
}
}// namespace yaksha
#endif
5 changes: 5 additions & 0 deletions compiler/src/yaksha_lisp/yaksha_lisp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,11 @@ void yaksha_envmap::setup_builtins() {
create_builtin(this, "is_module", yaksha_lisp_builtins::is_module_));
set("access_module", create_builtin(this, "access_module",
yaksha_lisp_builtins::access_module_));
set("os_exec", create_builtin(this, "os_exec",
yaksha_lisp_builtins::os_exec_));
set("os_shell", create_builtin(this, "os_shell",
yaksha_lisp_builtins::os_shell_));

// magic_dot -> map_get or access_module
set("magic_dot",
create_builtin(this, "magic_dot", yaksha_lisp_builtins::magic_dot_));
Expand Down
36 changes: 36 additions & 0 deletions compiler/src/yaksha_lisp/yaksha_lisp_builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1708,3 +1708,39 @@ yaksha_lisp_builtins::reversed_(const std::vector<yaksha_lisp_value *> &args,
std::reverse(v->list_.begin(), v->list_.end());
return v;
}
yaksha_lisp_value *
yaksha_lisp_builtins::os_exec_(const std::vector<yaksha_lisp_value *> &args,
yaksha_envmap *env) {
if (args.empty()) {
throw parsing_error{"os_exec takes at least 1 argument", "", 0, 0};
}
auto e_args = eval_args(args, env);
std::vector<std::string> cmd_args;
for (auto & e_arg : e_args) {
if (e_arg->type_ != yaksha_lisp_value_type::STRING) {
throw parsing_error{"os_exec takes only string arguments", "", 0, 0};
}
cmd_args.push_back(e_arg->str_);
}
auto result = exec(cmd_args);
return env->create_number(result);
}
yaksha_lisp_value *
yaksha_lisp_builtins::os_shell_(const std::vector<yaksha_lisp_value *> &args,
yaksha_envmap *env) {
if (args.size() != 1) {
throw parsing_error{"os_shell takes 1 argument", "", 0, 0};
}
auto e_args = eval_args(args, env);
std::vector<std::string> cmd_args;
#if defined(YAKSHA_OS_WINDOWS)
cmd_args.emplace_back("cmd");
cmd_args.emplace_back("/C");
#else
cmd_args.emplace_back("sh");
cmd_args.emplace_back("-c");
#endif
cmd_args.push_back(e_args[0]->str_);
auto result = exec(cmd_args);
return env->create_number(result);
}
5 changes: 5 additions & 0 deletions compiler/src/yaksha_lisp/yaksha_lisp_builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ namespace yaksha {
sorted_(const std::vector<yaksha_lisp_value *> &args, yaksha_envmap *env);
static yaksha_lisp_value *
reversed_(const std::vector<yaksha_lisp_value *> &args, yaksha_envmap *env);
static yaksha_lisp_value *
os_exec_(const std::vector<yaksha_lisp_value *> &args, yaksha_envmap *env);
static yaksha_lisp_value *
os_shell_(const std::vector<yaksha_lisp_value *> &args, yaksha_envmap *env);

// --
static yaksha_lisp_value *
system_lock_root_scope_(const std::vector<yaksha_lisp_value *> &args,
Expand Down
35 changes: 26 additions & 9 deletions compiler/tests/test_yaksha_lisp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,36 @@
// Note: libs - MIT license, runtime/3rd - various
// ==============================================================================================
// GPLv3:
//
//
// Yaksha - Programming Language.
// Copyright (C) 2020 - 2023 Bhathiya Perera
//
//
// This program is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
//
// You should have received a copy of the GNU General Public License along with this program.
// If not, see https://www.gnu.org/licenses/.
//
//
// ==============================================================================================
// Additional Terms:
//
//
// Please note that any commercial use of the programming language's compiler source code
// (everything except compiler/runtime, compiler/libs and compiler/3rd) require a written agreement
// with author of the language (Bhathiya Perera).
//
//
// If you are using it for an open source project, please give credits.
// Your own project must use GPLv3 license with these additional terms.
//
//
// You may use programs written in Yaksha/YakshaLisp for any legal purpose
// (commercial, open-source, closed-source, etc) as long as it agrees
// to the licenses of linked runtime libraries (see compiler/runtime/README.md).
//
//
// ==============================================================================================
#include "ast/parser.h"
#include "catch2/catch.hpp"
Expand Down Expand Up @@ -754,6 +754,23 @@ TEST_CASE("yaksha_lisp: '::' syntax sugar to get from map") {
(= success my_map::a)
)");
}
TEST_CASE("yaksha_lisp: os_exec test") {
std::stringstream ss{};
ss << "(system_enable_print)";
#if defined(YAKSHA_OS_WINDOWS)
ss << R"((print (os_exec "cmd" "/C" "echo hello")))";
#else
ss << R"((print (os_exec "sh" "-c" "echo hello")))";
#endif
ss << "(= success 1)";
test_snippet_execute(ss.str());
}
TEST_CASE("yaksha_lisp: os_shell test") {
test_snippet_execute(R"((system_enable_print)
(print "hello")
(os_shell "echo off")
(= success 1))");
}
TEST_CASE("yaksha_macro_support: macros!{}") {
// ----------
yaksha_macro_preprocess_happy_path(R"**(
Expand Down

0 comments on commit 22b4c8d

Please sign in to comment.