| @@ -1,8 +1,12 @@ | |||||
| clang src/main.c -g -o ./bin/slime --std=c99 || exit 1 | |||||
| SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" | |||||
| pushd $SCRIPTPATH > /dev/null | |||||
| clang++ src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1 | |||||
| echo "" | echo "" | ||||
| echo "--- Output Start ---" | echo "--- Output Start ---" | ||||
| pushd bin | |||||
| ./slime | |||||
| popd | |||||
| pushd bin > /dev/null | |||||
| ./slime --run-tests | |||||
| popd > /dev/null | |||||
| echo "--- Output End ---" | echo "--- Output End ---" | ||||
| popd > /dev/null | |||||
| @@ -9,11 +9,12 @@ constexpr bool is_debug_build = false; | |||||
| #define if_debug if constexpr (is_debug_build) | #define if_debug if constexpr (is_debug_build) | ||||
| // #ifdef _MSC_VER | |||||
| #ifdef _MSC_VER | |||||
| # define debug_break() if_debug __debugbreak() | # define debug_break() if_debug __debugbreak() | ||||
| // #else | |||||
| // # define debug_break() if_debug __builtin_trap() | |||||
| // #endif | |||||
| #else | |||||
| # include <signal.h> | |||||
| # define debug_break() if_debug raise(SIGTRAP) | |||||
| #endif | |||||
| #define assert(cond) \ | #define assert(cond) \ | ||||
| if_debug { \ | if_debug { \ | ||||
| @@ -9,9 +9,8 @@ proc delete_error() -> void { | |||||
| proc create_error(Error_Type type, Source_Code_Location* location) -> void { | proc create_error(Error_Type type, Source_Code_Location* location) -> void { | ||||
| delete_error(); | delete_error(); | ||||
| if_debug { | |||||
| debug_break(); | |||||
| } | |||||
| debug_break(); | |||||
| error = new(Error); | error = new(Error); | ||||
| error->type = type; | error->type = type; | ||||
| error->location = location; | error->location = location; | ||||
| @@ -388,8 +388,7 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| // check for c function | // check for c function | ||||
| if (lispOperator->type == Lisp_Object_Type::CFunction) { | if (lispOperator->type == Lisp_Object_Type::CFunction) { | ||||
| Lisp_Object* result = lispOperator->value.lambdaWrapper->function(arguments, env); | |||||
| // Lisp_Object* result = (*lispOperator->value.lambdaWrapper)(arguments, env); | |||||
| Lisp_Object* result = lispOperator->value.cFunction->function(arguments, env); | |||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -2,13 +2,17 @@ | |||||
| int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
| if (argc > 1) { | if (argc > 1) { | ||||
| if (Slime::string_equal(argv[1], "--run-tests")) { | |||||
| Slime::run_all_tests(); | |||||
| return 0; | |||||
| } | |||||
| Slime::interprete_file(argv[1]); | Slime::interprete_file(argv[1]); | ||||
| if (Slime::error) { | if (Slime::error) { | ||||
| Slime::log_error(); | Slime::log_error(); | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| } else { | } else { | ||||
| Slime::run_all_tests(); | |||||
| Slime::interprete_stdin(); | Slime::interprete_stdin(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -154,10 +154,12 @@ namespace Memory { | |||||
| Memory::create_string(keyword)); | Memory::create_string(keyword)); | ||||
| } | } | ||||
| proc create_lisp_object_cfunction(TransientFunction<Lisp_Object* (Lisp_Object*, Environment*)> function) -> Lisp_Object* { | |||||
| proc create_lisp_object_cfunction(std::function<Lisp_Object* (Lisp_Object*, Environment*)> function) -> Lisp_Object* { | |||||
| Lisp_Object* node = create_lisp_object(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::CFunction; | node->type = Lisp_Object_Type::CFunction; | ||||
| node->value.lambdaWrapper = new Lambda_Wrapper(function); | |||||
| // node->value.lambdaWrapper = new Lambda_Wrapper(function); | |||||
| node->value.cFunction = new(cFunction); | |||||
| node->value.cFunction->function = function; | |||||
| return node; | return node; | ||||
| } | } | ||||
| @@ -3,6 +3,7 @@ | |||||
| #define _CRT_SECURE_NO_DEPRECATE | #define _CRT_SECURE_NO_DEPRECATE | ||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <cmath> | |||||
| // #include <type_traits> | // #include <type_traits> | ||||
| #include <functional> | #include <functional> | ||||
| @@ -7,56 +7,6 @@ define_array_list(String*, String); | |||||
| define_array_list(int, Int); | define_array_list(int, Int); | ||||
| define_array_list(void*, Void_Ptr); | define_array_list(void*, Void_Ptr); | ||||
| // ----------------------------- | |||||
| // <crazy lambda wrapper> | |||||
| // ----------------------------- | |||||
| // SOURCE: http://brnz.org/hbr/?p=1767 | |||||
| template<typename> | |||||
| struct TransientFunction; // intentionally not defined | |||||
| template<typename R, typename ...Args> | |||||
| struct TransientFunction<R(Args...)> | |||||
| { | |||||
| using Dispatcher = R(*)(void*, Args...); | |||||
| Dispatcher m_Dispatcher; // A pointer to the static function that will call the | |||||
| // wrapped invokable object | |||||
| void* m_Target; // A pointer to the invokable object | |||||
| // Dispatch() is instantiated by the TransientFunction constructor, | |||||
| // which will store a pointer to the function in m_Dispatcher. | |||||
| template<typename S> | |||||
| static R Dispatch(void* target, Args... args) { | |||||
| return (*(S*)target)(args...); | |||||
| } | |||||
| template<typename T> | |||||
| TransientFunction(T&& target) | |||||
| : m_Dispatcher(&Dispatch<typename std::decay<T>::type>) | |||||
| , m_Target(&target) | |||||
| {} | |||||
| // Specialize for reference-to-function, to ensure that a valid pointer is | |||||
| // stored. | |||||
| using TargetFunctionRef = R(Args...); | |||||
| TransientFunction(TargetFunctionRef target) | |||||
| : m_Dispatcher(Dispatch<TargetFunctionRef>) | |||||
| { | |||||
| static_assert(sizeof(void*) == sizeof target, | |||||
| "It will not be possible to pass functions by reference on this platform. " | |||||
| "Please use explicit function pointers i.e. foo(target) -> foo(&target)"); | |||||
| m_Target = (void*)target; | |||||
| } | |||||
| R operator()(Args... args) const { | |||||
| return m_Dispatcher(m_Target, args...); | |||||
| } | |||||
| }; | |||||
| // ----------------------------- | |||||
| // </crazy lambda wrapper> | |||||
| // ----------------------------- | |||||
| enum struct Lisp_Object_Type { | enum struct Lisp_Object_Type { | ||||
| Nil, | Nil, | ||||
| T, | T, | ||||
| @@ -157,10 +107,8 @@ struct Function { | |||||
| Environment* parent_environment; // we are doing closures now!! | Environment* parent_environment; // we are doing closures now!! | ||||
| }; | }; | ||||
| struct Lambda_Wrapper { | |||||
| Lambda_Wrapper(TransientFunction<Lisp_Object* (Lisp_Object*, Environment*)> f) : function(f) {} | |||||
| TransientFunction<Lisp_Object* (Lisp_Object*, Environment*)> function; | |||||
| struct cFunction { | |||||
| std::function<Lisp_Object* (Lisp_Object*, Environment*)> function; | |||||
| }; | }; | ||||
| struct Lisp_Object { | struct Lisp_Object { | ||||
| @@ -173,7 +121,7 @@ struct Lisp_Object { | |||||
| String* string; | String* string; | ||||
| Pair* pair; | Pair* pair; | ||||
| Function* function; | Function* function; | ||||
| Lambda_Wrapper* lambdaWrapper; | |||||
| cFunction* cFunction; | |||||
| } value; | } value; | ||||
| }; | }; | ||||