|
@ -46,6 +46,24 @@ namespace lispy { |
|
|
std::unordered_map<int, std::shared_ptr<function>> function_table; |
|
|
std::unordered_map<int, std::shared_ptr<function>> function_table; |
|
|
std::unordered_map<int, lvalue> variable_table; |
|
|
std::unordered_map<int, lvalue> variable_table; |
|
|
|
|
|
|
|
|
|
|
|
std::function<lvalue(sp_coords)> resolve_coords = [&](sp_coords) -> lvalue { |
|
|
|
|
|
std::cerr << "no coord system provided" << std::endl; |
|
|
|
|
|
if(error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
return (int64_t)0; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::function<lvalue(sp_range)> resolve_range = [&](sp_range) -> lvalue { |
|
|
|
|
|
std::cerr << "no coord system provided" << std::endl; |
|
|
|
|
|
if(error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
return empty{}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
int get_atom(const std::string& key) |
|
|
int get_atom(const std::string& key) |
|
|
{ |
|
|
{ |
|
|
if(atoms.count(key)) { |
|
|
if(atoms.count(key)) { |
|
@ -100,7 +118,7 @@ namespace lispy { |
|
|
|
|
|
|
|
|
cons(cons&& oth) |
|
|
cons(cons&& oth) |
|
|
: self(oth.self) |
|
|
: self(oth.self) |
|
|
, other(oth.other ? std::move(std::make_shared<cons>(*(oth.other))) : std::shared_ptr<cons>{}) |
|
|
|
|
|
|
|
|
, other(oth.other ? std::make_shared<cons>(*(oth.other)) : std::shared_ptr<cons>{}) |
|
|
{} |
|
|
{} |
|
|
|
|
|
|
|
|
void append(lvalue value) |
|
|
void append(lvalue value) |
|
@ -221,7 +239,14 @@ namespace lispy { |
|
|
} |
|
|
} |
|
|
assert(false); |
|
|
assert(false); |
|
|
} else { |
|
|
} else { |
|
|
std::cerr << typeid(T).name() << " detected in print_visitor ?" << std::endl; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::cerr << |
|
|
|
|
|
#ifdef __cpp_rtti
|
|
|
|
|
|
typeid(T).name() |
|
|
|
|
|
#else
|
|
|
|
|
|
"unknown type" |
|
|
|
|
|
#endif
|
|
|
|
|
|
<< " detected in print_visitor ?" << std::endl; |
|
|
if(ctx.error_crash) |
|
|
if(ctx.error_crash) |
|
|
{ |
|
|
{ |
|
|
std::exit(-1); |
|
|
std::exit(-1); |
|
@ -268,7 +293,13 @@ namespace lispy { |
|
|
} else if constexpr (std::is_same_v<T, atom>) { |
|
|
} else if constexpr (std::is_same_v<T, atom>) { |
|
|
stream << "atom"; |
|
|
stream << "atom"; |
|
|
} else { |
|
|
} else { |
|
|
std::cerr << typeid(T).name() << " detected in print_types_visitor ?" << std::endl; |
|
|
|
|
|
|
|
|
std::cerr << |
|
|
|
|
|
#ifdef __cpp_rtti
|
|
|
|
|
|
typeid(T).name() |
|
|
|
|
|
#else
|
|
|
|
|
|
"unknown type" |
|
|
|
|
|
#endif
|
|
|
|
|
|
<< " detected in print_types_visitor ?" << std::endl; |
|
|
if(ctx.error_crash) |
|
|
if(ctx.error_crash) |
|
|
{ |
|
|
{ |
|
|
std::exit(-1); |
|
|
std::exit(-1); |
|
@ -306,7 +337,6 @@ namespace lispy { |
|
|
char* end_f; |
|
|
char* end_f; |
|
|
char* end_d; |
|
|
char* end_d; |
|
|
double try_f = strtod (data.data(), &end_f); |
|
|
double try_f = strtod (data.data(), &end_f); |
|
|
int err_f = errno; |
|
|
|
|
|
int64_t try_d = strtoll(data.data(), &end_d, 10); |
|
|
int64_t try_d = strtoll(data.data(), &end_d, 10); |
|
|
int err_d = errno; |
|
|
int err_d = errno; |
|
|
|
|
|
|
|
@ -427,12 +457,24 @@ namespace lispy { |
|
|
skip = matching - idx; |
|
|
skip = matching - idx; |
|
|
++sz; |
|
|
++sz; |
|
|
} else if constexpr (std::is_same_v<T, cons_end>) { |
|
|
} else if constexpr (std::is_same_v<T, cons_end>) { |
|
|
std::cerr << typeid(T).name() << " mismatched parenthesis" << std::endl; |
|
|
|
|
|
|
|
|
std::cerr << |
|
|
|
|
|
#ifdef __cpp_rtti
|
|
|
|
|
|
typeid(T).name() |
|
|
|
|
|
#else
|
|
|
|
|
|
"unknown type" |
|
|
|
|
|
#endif
|
|
|
|
|
|
<< " mismatched parenthesis" << std::endl; |
|
|
} else if constexpr (std::is_same_v<T, lvalue>) { |
|
|
} else if constexpr (std::is_same_v<T, lvalue>) { |
|
|
ret->append(arg); |
|
|
ret->append(arg); |
|
|
++sz; |
|
|
++sz; |
|
|
} else { |
|
|
} else { |
|
|
std::cerr << typeid(T).name() << " cat in the parser ?" << std::endl; |
|
|
|
|
|
|
|
|
std::cerr << |
|
|
|
|
|
#ifdef __cpp_rtti
|
|
|
|
|
|
typeid(T).name() |
|
|
|
|
|
#else
|
|
|
|
|
|
"unknown type" |
|
|
|
|
|
#endif
|
|
|
|
|
|
<< " cat in the parser ?" << std::endl; |
|
|
if(ctx.error_crash) |
|
|
if(ctx.error_crash) |
|
|
{ |
|
|
{ |
|
|
std::exit(-1); |
|
|
std::exit(-1); |
|
@ -473,7 +515,7 @@ namespace lispy { |
|
|
} else if (*it == '$' || *it == '@') { |
|
|
} else if (*it == '$' || *it == '@') { |
|
|
auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)}); |
|
|
auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)}); |
|
|
ret.push_back(value.first); |
|
|
ret.push_back(value.first); |
|
|
it += value.second.size()o">+1; |
|
|
|
|
|
|
|
|
it += value.second.size(); |
|
|
} else { |
|
|
} else { |
|
|
auto value = parse_atom(std::string_view{it, (size_t)(data.end() - it)}, ctx); |
|
|
auto value = parse_atom(std::string_view{it, (size_t)(data.end() - it)}, ctx); |
|
|
ret.push_back(value.first); |
|
|
ret.push_back(value.first); |
|
@ -542,6 +584,10 @@ namespace lispy { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lispy_math { |
|
|
namespace lispy_math { |
|
|
|
|
|
|
|
|
int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) { |
|
|
int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) { |
|
@ -555,7 +601,8 @@ namespace lispy_math { |
|
|
} |
|
|
} |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto extractor = [&](auto arg) { |
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
if constexpr (std::is_same_v<T, int64_t>) { |
|
|
if constexpr (std::is_same_v<T, int64_t>) { |
|
|
ret = arg; |
|
|
ret = arg; |
|
@ -568,6 +615,15 @@ namespace lispy_math { |
|
|
std::exit(-1); |
|
|
std::exit(-1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
|
|
|
if constexpr (std::is_same_v<T, lispy::sp_coords>) { |
|
|
|
|
|
std::visit(extractor, ctx.resolve_coords(arg)); |
|
|
|
|
|
} else { |
|
|
|
|
|
std::visit(extractor, arguments->self); |
|
|
|
|
|
} |
|
|
}, arguments->self); |
|
|
}, arguments->self); |
|
|
arguments = arguments->other; |
|
|
arguments = arguments->other; |
|
|
return ret; |
|
|
return ret; |
|
@ -584,7 +640,8 @@ namespace lispy_math { |
|
|
} |
|
|
} |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto extractor = [&](auto arg) { |
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
if constexpr (std::is_same_v<T, int64_t>) { |
|
|
if constexpr (std::is_same_v<T, int64_t>) { |
|
|
ret = arg; |
|
|
ret = arg; |
|
@ -597,11 +654,89 @@ namespace lispy_math { |
|
|
std::exit(-1); |
|
|
std::exit(-1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
|
|
|
if constexpr (std::is_same_v<T, lispy::sp_coords>) { |
|
|
|
|
|
std::visit(extractor, ctx.resolve_coords(arg)); |
|
|
|
|
|
} else { |
|
|
|
|
|
std::visit(extractor, arguments->self); |
|
|
|
|
|
} |
|
|
}, arguments->self); |
|
|
}, arguments->self); |
|
|
|
|
|
|
|
|
arguments = arguments->other; |
|
|
arguments = arguments->other; |
|
|
return ret; |
|
|
return ret; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lispy::lvalue next_as_floating_aggregate(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) { |
|
|
|
|
|
lispy::lvalue src = lispy::empty{}; |
|
|
|
|
|
if(!arguments) |
|
|
|
|
|
{ |
|
|
|
|
|
std::cerr << "no argument provided, s-exp or range expected" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
return src; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto extractor = [&](auto arg) { |
|
|
|
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
|
|
|
if constexpr (std::is_same_v<T, lispy::empty>) { |
|
|
|
|
|
src = arg; |
|
|
|
|
|
} else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) { |
|
|
|
|
|
src = arg; |
|
|
|
|
|
} else { |
|
|
|
|
|
std::cerr << "bad argument provided, s-exp or range expected" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
|
|
|
if constexpr (std::is_same_v<T, lispy::sp_range>) { |
|
|
|
|
|
std::visit(extractor, ctx.resolve_range(arg)); |
|
|
|
|
|
} else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) { |
|
|
|
|
|
std::visit(extractor, arguments->self); |
|
|
|
|
|
} else { |
|
|
|
|
|
std::cerr << "bad argument provided, s-exp or range expected" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, arguments->self); |
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<lispy::cons> dest; |
|
|
|
|
|
|
|
|
|
|
|
std::visit([&](auto arg) { |
|
|
|
|
|
using T = std::decay_t<decltype(arg)>; |
|
|
|
|
|
if constexpr (std::is_same_v<T, lispy::empty>) {} |
|
|
|
|
|
else if constexpr (std::is_same_v<T, std::shared_ptr<lispy::cons>>) { |
|
|
|
|
|
dest = std::make_shared<lispy::cons>(lispy_math::next_as_floating(arg, ctx)); |
|
|
|
|
|
while(arg){ |
|
|
|
|
|
dest->append(lispy_math::next_as_floating(arg, ctx)); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
std::cerr << "bad argument provided, s-exp or range expected" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, src); |
|
|
|
|
|
arguments = arguments->other; |
|
|
|
|
|
if(dest) |
|
|
|
|
|
{ |
|
|
|
|
|
return dest; |
|
|
|
|
|
} |
|
|
|
|
|
return lispy::empty{}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
namespace integer_functions { |
|
|
namespace integer_functions { |
|
|
class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) { |
|
|
class plus : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) { |
|
|
auto p = arguments; |
|
|
auto p = arguments; |
|
@ -683,6 +818,41 @@ namespace lispy_math { |
|
|
} |
|
|
} |
|
|
return a%b; |
|
|
return a%b; |
|
|
}}; |
|
|
}}; |
|
|
|
|
|
|
|
|
|
|
|
class iota : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) { |
|
|
|
|
|
auto p = arguments; |
|
|
|
|
|
int64_t a = next_as_int(p, ctx); |
|
|
|
|
|
int64_t b = next_as_int(p, ctx); |
|
|
|
|
|
|
|
|
|
|
|
if(p) |
|
|
|
|
|
{ |
|
|
|
|
|
std::cerr << "expected arity of 2 but more arguments provided" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(b<=a) |
|
|
|
|
|
{ |
|
|
|
|
|
std::cerr << "expected first argument lower than second" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
return lispy::empty{}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::shared_ptr<lispy::cons> ret = std::make_shared<lispy::cons>(a); |
|
|
|
|
|
a+=1; |
|
|
|
|
|
for(;a<b;a++) |
|
|
|
|
|
{ |
|
|
|
|
|
ret->append(a); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
}}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
namespace float_functions { |
|
|
namespace float_functions { |
|
@ -752,6 +922,36 @@ namespace lispy_math { |
|
|
return a/b; |
|
|
return a/b; |
|
|
}}; |
|
|
}}; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
namespace aggregate_functions { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class sum : lispy::function {virtual lispy::lvalue operator() (const std::shared_ptr<lispy::cons> arguments, lispy::context& ctx) { |
|
|
|
|
|
auto p = arguments; |
|
|
|
|
|
lispy::lvalue cells = next_as_floating_aggregate(p, ctx); |
|
|
|
|
|
|
|
|
|
|
|
if(p) |
|
|
|
|
|
{ |
|
|
|
|
|
std::cerr << "expected arity of 1 but more arguments provided" << std::endl; |
|
|
|
|
|
if(ctx.error_crash) |
|
|
|
|
|
{ |
|
|
|
|
|
std::exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
double ret = 0; |
|
|
|
|
|
|
|
|
|
|
|
while(std::get<std::shared_ptr<lispy::cons>>(cells)) { |
|
|
|
|
|
ret += lispy_math::next_as_floating(std::get<std::shared_ptr<lispy::cons>>(cells), ctx); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
}}; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline void add_integer_functions(lispy::context& ctx) { |
|
|
inline void add_integer_functions(lispy::context& ctx) { |
|
|
using func_ptr = std::shared_ptr<lispy::function>; |
|
|
using func_ptr = std::shared_ptr<lispy::function>; |
|
@ -761,6 +961,8 @@ namespace lispy_math { |
|
|
ctx.function_table[ctx.get_atom("*")] = func_ptr{(lispy::function*)new integer_functions::product()}; |
|
|
ctx.function_table[ctx.get_atom("*")] = func_ptr{(lispy::function*)new integer_functions::product()}; |
|
|
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::divide()}; |
|
|
ctx.function_table[ctx.get_atom("%")] = func_ptr{(lispy::function*)new integer_functions::remainder()}; |
|
|
ctx.function_table[ctx.get_atom("%")] = func_ptr{(lispy::function*)new integer_functions::remainder()}; |
|
|
|
|
|
|
|
|
|
|
|
ctx.function_table[ctx.get_atom("iota")] = func_ptr{(lispy::function*)new integer_functions::iota()}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
inline void add_floatingp_functions(lispy::context& ctx) { |
|
|
inline void add_floatingp_functions(lispy::context& ctx) { |
|
@ -771,4 +973,10 @@ namespace lispy_math { |
|
|
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::product()}; |
|
|
ctx.function_table[ctx.get_atom("/.")] = func_ptr{(lispy::function*)new float_functions::divide()}; |
|
|
ctx.function_table[ctx.get_atom("/.")] = func_ptr{(lispy::function*)new float_functions::divide()}; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
inline void add_aggregate_functions(lispy::context& ctx) { |
|
|
|
|
|
using func_ptr = std::shared_ptr<lispy::function>; |
|
|
|
|
|
|
|
|
|
|
|
ctx.function_table[ctx.get_atom("sum")] = func_ptr{(lispy::function*)new aggregate_functions::sum()}; |
|
|
|
|
|
} |
|
|
} |
|
|
} |