diff --git a/include/rigid_paradise/lispy/lispy.hpp b/include/rigid_paradise/lispy/lispy.hpp index e9059b5..bddf0cd 100644 --- a/include/rigid_paradise/lispy/lispy.hpp +++ b/include/rigid_paradise/lispy/lispy.hpp @@ -42,6 +42,7 @@ namespace lispy { std::unordered_map atoms; int last_atom = 0; bool error_crash = false; + bool print_parse_results = false; std::unordered_map> function_table; std::unordered_map variable_table; @@ -423,7 +424,7 @@ namespace lispy { auto matching = find_matching(data, idx); auto res = parse(std::basic_string_view{data.begin()+idx+1, matching-idx-1}, ctx); ret->append(res.second); - skip = matching - idx + 1; + skip = matching - idx; ++sz; } else if constexpr (std::is_same_v) { std::cerr << typeid(T).name() << " mismatched parenthesis" << std::endl; @@ -530,6 +531,13 @@ namespace lispy { { auto n = lex(data, ctx); auto p = parse(std::basic_string_view(n.data(), n.size()), ctx); + if(ctx.print_parse_results) + { + print_types_visitor(std::cerr, p.second, ctx); + std::cerr << std::endl; + print_visitor(std::cerr, p.second, ctx); + std::cerr << std::endl; + } return eval(p.second, ctx); } } @@ -540,7 +548,7 @@ namespace lispy_math { int64_t ret = 0; if(!arguments) { - std::cerr << "no argument provided, integer expected" << std::endl; + std::cerr << "no argument provided, number expected" << std::endl; if(ctx.error_crash) { std::exit(-1); @@ -554,7 +562,36 @@ namespace lispy_math { } else if constexpr (std::is_same_v) { ret = arg; } else { - std::cerr << "bad argument provided, integer expected" << std::endl; + std::cerr << "bad argument provided, number expected" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + } + }, arguments->self); + arguments = arguments->other; + return ret; + } + + double next_as_floating(std::shared_ptr& arguments, lispy::context& ctx) { + double ret = 0; + if(!arguments) + { + std::cerr << "no argument provided, number expected" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + return ret; + } + std::visit([&](auto arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) { + ret = arg; + } else if constexpr (std::is_same_v) { + ret = arg; + } else { + std::cerr << "bad argument provided, number expected" << std::endl; if(ctx.error_crash) { std::exit(-1); @@ -647,6 +684,74 @@ namespace lispy_math { return a%b; }}; }; + + namespace float_functions { + class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr arguments, lispy::context& ctx) { + auto p = arguments; + double a = next_as_floating(p, ctx); + double b = next_as_floating(p, ctx); + + if(p) + { + std::cerr << "expected arity of 2 but more arguments provided" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + } + return a+b; + }}; + class minus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr arguments, lispy::context& ctx) { + auto p = arguments; + double a = next_as_floating(p, ctx); + + if(!p) { + return -a; + } + + double b = next_as_floating(p, ctx); + + if(p) + { + std::cerr << "expected arity of 1 or 2 but more arguments provided" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + } + return a-b; + }}; + class product : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr arguments, lispy::context& ctx) { + auto p = arguments; + double a = next_as_floating(p, ctx); + double b = next_as_floating(p, ctx); + + if(p) + { + std::cerr << "expected arity of 2 but more arguments provided" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + } + return a*b; + }}; + class divide : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr arguments, lispy::context& ctx) { + auto p = arguments; + double a = next_as_floating(p, ctx); + double b = next_as_floating(p, ctx); + + if(p) + { + std::cerr << "expected arity of 2 but more arguments provided" << std::endl; + if(ctx.error_crash) + { + std::exit(-1); + } + } + return a/b; + }}; + }; inline void add_integer_functions(lispy::context& ctx) { using func_ptr = std::shared_ptr; @@ -657,4 +762,13 @@ namespace lispy_math { ctx.function_table[ctx.get_atom("/")] = func_ptr{(lispy::function*)new integer_functions::divide()}; ctx.function_table[ctx.get_atom("%")] = func_ptr{(lispy::function*)new integer_functions::remainder()}; } + + inline void add_floatingp_functions(lispy::context& ctx) { + using func_ptr = std::shared_ptr; + + ctx.function_table[ctx.get_atom("+.")] = func_ptr{(lispy::function*)new float_functions::plus()}; + ctx.function_table[ctx.get_atom("-.")] = func_ptr{(lispy::function*)new float_functions::minus()}; + ctx.function_table[ctx.get_atom("*.")] = func_ptr{(lispy::function*)new float_functions::product()}; + ctx.function_table[ctx.get_atom("/.")] = func_ptr{(lispy::function*)new float_functions::divide()}; + } } \ No newline at end of file diff --git a/src/csv-sheet/csv-parse.cpp b/src/csv-sheet/csv-parse.cpp index 05132a2..3eb1067 100644 --- a/src/csv-sheet/csv-parse.cpp +++ b/src/csv-sheet/csv-parse.cpp @@ -3,8 +3,10 @@ int main() { lispy::context ctx; + ctx.print_parse_results = true; lispy_math::add_integer_functions(ctx); - lispy::lvalue v = lispy::eval("cat $AA12 @A12:C23 (+ 3 (* 5 6) ) \"data \\ ひらがな \n\ttabulated\" \"\" \"test 2 \\x65\"", ctx); + lispy_math::add_floatingp_functions(ctx); + lispy::lvalue v = lispy::eval("cat $AA12 @A12:C23 (/. (+ 3 (* 5 6)) 10) \"data \\ ひらがな \n\ttabulated\" \"\" \"test 2 \\x65\"", ctx); lispy::print_types_visitor(std::cout, v, ctx); std::cout << std::endl;