|
|
- #pragma once
- #include "memory_pool.hpp"
- #include "string_view.hpp"
-
- class crank_context;
-
- kstd::string_view identity(kstd::string_view args, crank_context& ctx);
- kstd::string_view set(kstd::string_view args, crank_context& ctx);
-
-
- bool istokenok(int m);
- bool islinearspace(int m);
- kstd::string_view skip_whitespace(kstd::string_view code);
- kstd::string_view skip_linearspace(kstd::string_view code);
-
- template<typename t1, typename t2>
- struct pair{
- pair(t1 f, t2 s)
- : first{f}
- , second{s}
- {}
- t1 first;
- t2 second;
- };
-
-
- struct crank_macro{
- kstd::string_view(*execute)(kstd::string_view, crank_context&);
- crank_macro()
- {
- execute=identity;
- }
- crank_macro(kstd::string_view(*f)(kstd::string_view, crank_context&))
- {
- execute=f;
- }
- kstd::string_view operator()(kstd::string_view args, crank_context* ctx)
- {
- return execute(args, *ctx);
- }
- };
-
- struct crank_elem;
-
- template<typename T>
- struct crank_ptr{
- T* ptr=nullptr;
- memory_pool* memory=nullptr;
-
- crank_ptr(T* _ptr, memory_pool* _memory)
- : ptr{_ptr}
- , memory{_memory}
- {}
-
- crank_ptr(){}
- crank_ptr(crank_ptr&) = delete;
-
- crank_ptr(crank_ptr&& oth)
- {
- auto tmp = oth.ptr;
- oth.ptr=ptr;
- ptr=tmp;
-
- auto tmpm = oth.memory;
- oth.memory=memory;
- memory=tmpm;
- }
-
- void operator=(crank_ptr&& oth)
- {
- auto tmp = oth.ptr;
- oth.ptr=ptr;
- ptr=tmp;
-
- auto tmpm = oth.memory;
- oth.memory=memory;
- memory=tmpm;
- }
-
- ~crank_ptr()
- {
- if(ptr&&memory)
- {
- memory->desallocate(ptr);
- }
- }
- };
-
- struct crank_elem{
- crank_ptr<crank_elem> next;
- pair<kstd::string_view,kstd::string_view> data;
- };
-
- struct crank_copy{
- crank_ptr<crank_copy> next;
- kstd::string_view data;
- };
-
- struct crank_native{
- crank_ptr<crank_native> next;
- pair<kstd::string_view,crank_macro> data;
- };
-
- kstd::string_view skip_whitespace(kstd::string_view code);
- kstd::string_view extract_subcommand(kstd::string_view code);
- kstd::string_view extract_array(kstd::string_view code);
- kstd::string_view extract_token(kstd::string_view code);
- kstd::string_view extract_command(kstd::string_view code);
- kstd::string_view extract_string(kstd::string_view code);
-
- class crank_context{
- memory_pool memory;
- crank_ptr<crank_elem> elements;
- crank_ptr<crank_copy> copies;
- crank_ptr<crank_native> natives;
- public:
-
- kstd::string_view copy(kstd::string_view src)
- {
- char* ptr = (char*)memory.allocate(src.size());
- if(ptr)
- {
- crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy));
- if(cpy)
- {
- new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,src.size())};
- copies = std::move(crank_ptr{cpy, &memory});
- memcpy(ptr,src.begin(),src.size());
- return copies.ptr->data;
- }
- else
- {
- memory.desallocate(ptr);
- return kstd::string_view();
- }
- }
- return kstd::string_view();
- }
-
- kstd::string_view copy_replace(kstd::string_view src)
- {
- size_t new_len=src.size();
- auto m = src.begin();
- while(m!=src.end())
- {
- if(!istokenok(*m))
- {
- m++;
- }
- else
- {
- auto token = extract_token(kstd::string_view(m,src.end()));
- if(token[0]=='$')
- {
- new_len-=token.size();
- new_len+=get_symbol(kstd::string_view(token.begin()+1,token.end())).size();
- }
- m+=token.size();
- }
- }
- char* ptr = (char*)memory.allocate(new_len);
- if(ptr)
- {
- crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy));
- if(cpy)
- {
- new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,new_len)};
- copies = std::move(crank_ptr{cpy, &memory});
-
- auto dest = kstd::string_view(ptr,new_len);
- auto src_it = src.begin();
- auto dest_it = dest.begin();
- while(src_it!=src.end() && dest_it!=dest.end())
- {
- if(!istokenok(*src_it))
- {
- *dest_it = *src_it;
- dest_it++;
- src_it++;
- }
- else
- {
- auto token = extract_token(kstd::string_view(src_it,src.end()));
- if(token[0]=='$')
- {
- auto resolved = get_symbol(kstd::string_view(token.begin()+1,token.end()));
- memcpy(dest_it,resolved.begin(),resolved.size());
- src_it+=token.size();
- dest_it+=resolved.size();
- }
- else
- {
- memcpy(dest_it,token.begin(),token.size());
- src_it+=token.size();
- dest_it+=token.size();
- }
- }
- }
- return copies.ptr->data;
- }
- else
- {
- memory.desallocate(ptr);
- return kstd::string_view();
- }
- }
- return kstd::string_view();
- }
-
- kstd::string_view store(kstd::string_view key, kstd::string_view value)
- {
- crank_elem* elem = (crank_elem*)memory.allocate(sizeof(crank_elem));
- if(elem)
- {
- new(elem) crank_elem{.next=std::move(elements), .data=pair(key, value)};
- elements = std::move(crank_ptr{elem, &memory});
- return value;
- }
- return kstd::string_view();
- }
-
- kstd::string_view add_native(kstd::string_view key, crank_macro value)
- {
- crank_native* native = (crank_native*)memory.allocate(sizeof(crank_native));
- if(native)
- {
- new(native) crank_native{.next=std::move(natives), .data=pair(key, value)};
- natives = std::move(crank_ptr{native, &memory});
- return key;
- }
- return kstd::string_view();
- }
-
- bool string_is_in_range(kstd::string_view range, char* ptr)
- {
- return ptr>=range.begin() && ptr<range.end();
- }
-
- bool any_elem_is_in_range(kstd::string_view range)
- {
- auto elems = &elements;
- while(elems->ptr)
- {
- if(
- string_is_in_range(range, elems->ptr->data.first.begin())
- || string_is_in_range(range, elems->ptr->data.second.begin())
- )
- {
- return true;
- }
- elems = &(elems->ptr->next);
- }
- return false;
- }
-
- kstd::string_view get_symbol(kstd::string_view key)
- {
- auto elems = &elements;
- while(elems->ptr)
- {
- if(
- elems->ptr->data.first == key
- )
- {
- return elems->ptr->data.second;
- }
- elems = &(elems->ptr->next);
- }
- return kstd::string_view();
- }
-
- crank_macro& get_native(kstd::string_view key)
- {
-
- auto elems = &natives;
- while(elems->ptr)
- {
- if(
- elems->ptr->data.first == key
- )
- {
- return elems->ptr->data.second;
- }
- elems = &(elems->ptr->next);
- }
- static const char* id = "identity";
- return get_native(kstd::string_view((char*)id,8));
- }
-
- void collect()
- {
- auto elems = &elements;
- while(elems->ptr)
- {
- auto elems_after = &(elems->ptr->next);
- while(elems_after->ptr)
- {
- if(
- elems->ptr->data.first == elems_after->ptr->data.first
- )
- {
- *elems_after = std::move(elems_after->ptr->next);
- }
- else
- {
- elems_after = &(elems_after->ptr->next);
- }
- }
- elems = &(elems->ptr->next);
- }
-
- auto cps = &copies;
- while(cps->ptr)
- {
- if(
- ! any_elem_is_in_range(cps->ptr->data)
- )
- {
- memory.desallocate(cps->ptr->data.begin());
- *cps=std::move(cps->ptr->next);
- }
- else
- {
- cps = &(cps->ptr->next);
- }
- }
- }
- crank_context()
- {
- static const char* str_set = "set";
- add_native(kstd::string_view((char*)str_set,3), set);
- static const char* str_identity = "identity";
- add_native(kstd::string_view((char*)str_identity,8), identity);
- }
- kstd::string_view execute_command(kstd::string_view code);
- kstd::string_view eval(kstd::string_view);
- kstd::string_view eval_no_copy(kstd::string_view);
- };
|