|
|
@ -42,6 +42,7 @@ namespace lispy { |
|
|
|
std::unordered_map<std::string, int> atoms; |
|
|
|
int last_atom = 0; |
|
|
|
bool error_crash = false; |
|
|
|
bool print_parse_results = false; |
|
|
|
std::unordered_map<int, std::shared_ptr<function>> function_table; |
|
|
|
std::unordered_map<int, lvalue> variable_table; |
|
|
|
|
|
|
@ -423,7 +424,7 @@ namespace lispy { |
|
|
|
auto matching = find_matching(data, idx); |
|
|
|
auto res = parse(std::basic_string_view<token>{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<T, cons_end>) { |
|
|
|
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<token>(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<T, double>) { |
|
|
|
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<lispy::cons>& 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<decltype(arg)>; |
|
|
|
if constexpr (std::is_same_v<T, int64_t>) { |
|
|
|
ret = arg; |
|
|
|
} else if constexpr (std::is_same_v<T, double>) { |
|
|
|
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<lispy::cons> 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<lispy::cons> 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<lispy::cons> 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<lispy::cons> 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<lispy::function>; |
|
|
@ -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<lispy::function>; |
|
|
|
|
|
|
|
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()}; |
|
|
|
} |
|
|
|
} |