Selaa lähdekoodia

can evaluate integer operations in lispy

master
Ludovic 'Archivist' Lagouardette 5 vuotta sitten
vanhempi
commit
ceea888958
3 muutettua tiedostoa jossa 237 lisäystä ja 22 poistoa
  1. +2
    -2
      include/rigid_paradise/csv/csv-base.h
  2. +233
    -19
      include/rigid_paradise/lispy/lispy.hpp
  3. +2
    -1
      src/csv-sheet/csv-parse.cpp

+ 2
- 2
include/rigid_paradise/csv/csv-base.h Näytä tiedosto

@ -54,10 +54,10 @@ namespace csv {
public:
std::map<cell_id, cell> data;
k">const cell& operator[] (const std::string_view id) const {
cm">/*const cell& operator[] (const std::string_view id) const {
auto coords = get_coords_from_id(id);
return data[coords];
}
}*/
};
}

+ 233
- 19
include/rigid_paradise/lispy/lispy.hpp Näytä tiedosto

@ -42,6 +42,8 @@ namespace lispy {
std::unordered_map<std::string, int> atoms;
int last_atom = 0;
bool error_crash = false;
std::unordered_map<int, std::shared_ptr<function>> function_table;
std::unordered_map<int, lvalue> variable_table;
int get_atom(const std::string& key)
{
@ -56,12 +58,12 @@ namespace lispy {
class cons {
public:
lvalue self = empty{};
std::unique_ptr<cons> other{};
std::shared_ptr<cons> other{};
cons()
{
self = empty{};
other = std::unique_ptr<cons>{};
other = std::shared_ptr<cons>{};
}
cons(lvalue first)
@ -73,7 +75,7 @@ namespace lispy {
{
if(data.size() == 0) {
self = empty{};
other = std::unique_ptr<cons>{};
other = std::shared_ptr<cons>{};
} else if(data.size() >= 1) {
self = data[0];
for(auto it = data.begin()+1; it != data.end(); ++it)
@ -83,27 +85,27 @@ namespace lispy {
cons(const cons& oth)
: self(oth.self)
, other(oth.other ? std::make_unique<cons>(*(oth.other)) : nullptr)
, other(oth.other ? std::make_shared<cons>(*(oth.other)) : nullptr)
{}
void operator=(const cons& oth)
{
self = oth.self;
if(oth.other) {
other = std::make_unique<cons>(*oth.other);
other = std::make_shared<cons>(*oth.other);
} else {
other = std::unique_ptr<cons>{};
other = std::shared_ptr<cons>{};
}
}
cons(cons&& oth)
: self(oth.self)
, other(oth.other ? std::move(std::make_unique<cons>(*(oth.other))) : std::unique_ptr<cons>{})
, other(oth.other ? std::move(std::make_shared<cons>(*(oth.other))) : std::shared_ptr<cons>{})
{}
void append(lvalue value)
{
if(!other) {
other = std::make_unique<cons>(value);
other = std::make_shared<cons>(value);
} else {
other->append(value);
}
@ -112,7 +114,8 @@ namespace lispy {
class function {
public:
virtual lvalue operator() (cons arguments) = 0;
virtual lvalue operator() (const std::shared_ptr<cons> arguments, lispy::context& ctx) = 0;
virtual ~function(){};
};
inline char hexdigit(char v)
@ -179,7 +182,7 @@ namespace lispy {
stream << arg;
} else if constexpr (std::is_same_v<T, empty>) {
stream << "()";
} else if constexpr (std::is_same_v<T, function>) {
} else if constexpr (std::is_same_v<T, std::shared_ptr<function>>) {
stream << "#func"<<&*arg;
} else if constexpr (std::is_same_v<T, std::string>) {
stream << escape(arg);
@ -203,9 +206,9 @@ namespace lispy {
stream << ")";
}
else if constexpr (std::is_same_v<T, sp_coords>){
assert(false);
stream << (arg.is_relative ? "$[" : "@[") << arg.x << "," << arg.y << "]";
} else if constexpr (std::is_same_v<T, sp_range>){
assert(false);
stream << (arg.is_relative ? "$[" : "@[") << arg.x << "," << arg.y << "," << arg.width << "," << arg.height << "]";
} else if constexpr (std::is_same_v<T, atom>) {
for(auto& v : ctx.atoms)
{
@ -235,7 +238,7 @@ namespace lispy {
stream << "double";
} else if constexpr (std::is_same_v<T, empty>) {
stream << "nil";
} else if constexpr (std::is_same_v<T, function>) {
} else if constexpr (std::is_same_v<T, std::shared_ptr<function>>) {
stream << "function";
} else if constexpr (std::is_same_v<T, std::string>) {
stream << "string";
@ -319,9 +322,52 @@ namespace lispy {
return std::make_pair(lvalue{int64_t(try_d)}, std::string_view{data.begin(), (size_t)(end_f-data.data())});
}
inline std::pair<size_t,sp_coords> get_coords_from_id(const std::string_view id) {
size_t x = 0;
size_t y = 0;
auto c = id.begin();
while(*c >= 'A' && *c <= 'Z')
{
x += *c-'A'+1;
x *= 26;
c++;
}
x /= 26;
while(*c >= '0' && *c <= '9')
{
y += *c-'0';
y *= 10;
c++;
}
y /= 10;
sp_coords ret;
ret.x = x;
ret.y = y;
return std::make_pair((size_t)(c-id.begin()) ,ret);
}
inline std::pair<lvalue, std::string_view> parse_selector(std::string_view data)
{
return std::make_pair(lvalue{}, std::string_view{data.begin(), 0});
auto it = data.begin();
auto is_rel = *it == '$';
++it;
auto a = get_coords_from_id(std::string_view{it, data.size()-1});
a.second.is_relative = is_rel;
it += a.first;
if(*it == ':')
{
auto b = get_coords_from_id(std::string_view{++it, data.size()-1});
it += b.first;
sp_range ret;
a.second.is_relative = is_rel;
ret.x = a.second.x;
ret.y = a.second.y;
ret.width = b.second.x;
ret.height = b.second.y;
return std::make_pair(lvalue{ret}, std::string_view{data.begin(), (size_t)(it - data.begin())});
} else {
return std::make_pair(lvalue{a.second}, std::string_view{data.begin(), (size_t)(it - data.begin())});
}
}
inline size_t find_matching(const std::basic_string_view<token>& data, const size_t idx)
@ -375,9 +421,9 @@ namespace lispy {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, cons_start>) {
auto matching = find_matching(data, idx);
auto res = parse(std::basic_string_view<token>{data.begin()+1, matching-idx-1}, ctx);
auto res = parse(std::basic_string_view<token>{data.begin()+n">idx+1, matching-idx-1}, ctx);
ret->append(res.second);
skip = matching - idx;
skip = matching - idx + 1;
++sz;
} else if constexpr (std::is_same_v<T, cons_end>) {
std::cerr << typeid(T).name() << " mismatched parenthesis" << std::endl;
@ -409,7 +455,7 @@ namespace lispy {
} else if(isdigit(*it) || (*it == '-' && isdigit(*(it+1)))) {
auto value = parse_number(std::string_view{it, (size_t)(data.end() - it)});
ret.push_back(value.first);
it += value.second.size()o">+1;
it += value.second.size();
} else if(*it == '\"') {
auto value = parse_string(std::string_view{it, (size_t)(data.end() - it)});
ret.push_back(value.first);
@ -423,7 +469,7 @@ namespace lispy {
++it;
} else if (iswspace(*it)) {
++it;
} else if (*it == '$') {
} else if (*it == '$' || *it == '@') {
auto value = parse_selector(std::string_view{it, (size_t)(data.end() - it)});
ret.push_back(value.first);
it += value.second.size()+1;
@ -437,10 +483,178 @@ namespace lispy {
return ret;
}
inline lvalue eval(lvalue& data, context& ctx)
{
lvalue ret = empty{};
std::visit([&](auto& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::shared_ptr<cons>>) {
auto it = arg;
auto evaluated = std::make_shared<cons>();
auto iterated = evaluated;
do{
iterated->self = eval(it->self, ctx);
if(it->other)
{
iterated->other = std::make_shared<cons>();
iterated = iterated->other;
}
it = it->other;
} while(it);
std::visit([&](auto arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, std::shared_ptr<function>>) {
ret = (*arg)(evaluated->other, ctx);
} else {
ret = evaluated;
}
}, evaluated->self);
} else if constexpr (std::is_same_v<T, atom>) {
if(ctx.function_table.count(arg.value))
{
ret = ctx.function_table[arg.value];
} else if (ctx.variable_table.count(arg.value)) {
ret = ctx.variable_table[arg.value];
} else {
ret = arg;
}
} else {
ret = arg;
}
}, data);
return ret;
}
inline lvalue eval(const std::string_view& data, context& ctx)
{
auto n = lex(data, ctx);
auto p = parse(std::basic_string_view<token>(n.data(), n.size()), ctx);
return p.second;
return eval(p.second, ctx);
}
}
namespace lispy_math {
int64_t next_as_int(std::shared_ptr<lispy::cons>& arguments, lispy::context& ctx) {
int64_t ret = 0;
if(!arguments)
{
std::cerr << "no argument provided, integer 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, integer expected" << std::endl;
if(ctx.error_crash)
{
std::exit(-1);
}
}
}, arguments->self);
arguments = arguments->other;
return ret;
}
namespace integer_functions {
class plus : 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);
}
}
return a+b;
}};
class minus : 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);
if(!p) {
return -a;
}
int64_t b = next_as_int(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;
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);
}
}
return a*b;
}};
class divide : 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);
}
}
return a/b;
}};
class remainder : 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);
}
}
return a%b;
}};
};
inline void add_integer_functions(lispy::context& ctx) {
using func_ptr = std::shared_ptr<lispy::function>;
ctx.function_table[ctx.get_atom("+")] = func_ptr{(lispy::function*)new integer_functions::plus()};
ctx.function_table[ctx.get_atom("-")] = func_ptr{(lispy::function*)new integer_functions::minus()};
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::remainder()};
}
}

+ 2
- 1
src/csv-sheet/csv-parse.cpp Näytä tiedosto

@ -3,7 +3,8 @@
int main() {
lispy::context ctx;
lispy::lvalue v = lispy::eval("cat 13 15.69 \"data \\ ひらがな \n\ttabulated\" \"\" \"test 2 \\x65\"", ctx);
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::print_types_visitor(std::cout, v, ctx);
std::cout << std::endl;

Ladataan…
Peruuta
Tallenna