A Tcl like command language made for the Clinl kernel testing
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
7.0 KiB

5 years ago
5 years ago
5 years ago
  1. #pragma once
  2. #include "memory_pool.hpp"
  3. #include "string_view.hpp"
  4. class crank_context;
  5. kstd::string_view identity(kstd::string_view args, crank_context& ctx);
  6. kstd::string_view set(kstd::string_view args, crank_context& ctx);
  7. bool istokenok(int m);
  8. bool islinearspace(int m);
  9. kstd::string_view skip_whitespace(kstd::string_view code);
  10. kstd::string_view skip_linearspace(kstd::string_view code);
  11. template<typename t1, typename t2>
  12. struct pair{
  13. pair(t1 f, t2 s)
  14. : first{f}
  15. , second{s}
  16. {}
  17. t1 first;
  18. t2 second;
  19. };
  20. struct crank_macro{
  21. kstd::string_view(*execute)(kstd::string_view, crank_context&);
  22. crank_macro()
  23. {
  24. execute=identity;
  25. }
  26. crank_macro(kstd::string_view(*f)(kstd::string_view, crank_context&))
  27. {
  28. execute=f;
  29. }
  30. kstd::string_view operator()(kstd::string_view args, crank_context* ctx)
  31. {
  32. return execute(args, *ctx);
  33. }
  34. };
  35. struct crank_elem;
  36. template<typename T>
  37. struct crank_ptr{
  38. T* ptr=nullptr;
  39. memory_pool* memory=nullptr;
  40. crank_ptr(T* _ptr, memory_pool* _memory)
  41. : ptr{_ptr}
  42. , memory{_memory}
  43. {}
  44. crank_ptr(){}
  45. crank_ptr(crank_ptr&) = delete;
  46. crank_ptr(crank_ptr&& oth)
  47. {
  48. auto tmp = oth.ptr;
  49. oth.ptr=ptr;
  50. ptr=tmp;
  51. auto tmpm = oth.memory;
  52. oth.memory=memory;
  53. memory=tmpm;
  54. }
  55. void operator=(crank_ptr&& oth)
  56. {
  57. auto tmp = oth.ptr;
  58. oth.ptr=ptr;
  59. ptr=tmp;
  60. auto tmpm = oth.memory;
  61. oth.memory=memory;
  62. memory=tmpm;
  63. }
  64. ~crank_ptr()
  65. {
  66. if(ptr&&memory)
  67. {
  68. memory->desallocate(ptr);
  69. }
  70. }
  71. };
  72. struct crank_elem{
  73. crank_ptr<crank_elem> next;
  74. pair<kstd::string_view,kstd::string_view> data;
  75. };
  76. struct crank_copy{
  77. crank_ptr<crank_copy> next;
  78. kstd::string_view data;
  79. };
  80. struct crank_native{
  81. crank_ptr<crank_native> next;
  82. pair<kstd::string_view,crank_macro> data;
  83. };
  84. kstd::string_view skip_whitespace(kstd::string_view code);
  85. kstd::string_view extract_subcommand(kstd::string_view code);
  86. kstd::string_view extract_array(kstd::string_view code);
  87. kstd::string_view extract_token(kstd::string_view code);
  88. kstd::string_view extract_command(kstd::string_view code);
  89. kstd::string_view extract_string(kstd::string_view code);
  90. class crank_context{
  91. memory_pool memory;
  92. crank_ptr<crank_elem> elements;
  93. crank_ptr<crank_copy> copies;
  94. crank_ptr<crank_native> natives;
  95. public:
  96. kstd::string_view copy(kstd::string_view src)
  97. {
  98. char* ptr = (char*)memory.allocate(src.size());
  99. if(ptr)
  100. {
  101. crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy));
  102. if(cpy)
  103. {
  104. new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,src.size())};
  105. copies = std::move(crank_ptr{cpy, &memory});
  106. memcpy(ptr,src.begin(),src.size());
  107. return copies.ptr->data;
  108. }
  109. else
  110. {
  111. memory.desallocate(ptr);
  112. return kstd::string_view();
  113. }
  114. }
  115. return kstd::string_view();
  116. }
  117. kstd::string_view copy_replace(kstd::string_view src)
  118. {
  119. size_t new_len=src.size();
  120. auto m = src.begin();
  121. while(m!=src.end())
  122. {
  123. if(!istokenok(*m))
  124. {
  125. m++;
  126. }
  127. else
  128. {
  129. auto token = extract_token(kstd::string_view(m,src.end()));
  130. if(token[0]=='$')
  131. {
  132. new_len-=token.size();
  133. new_len+=get_symbol(kstd::string_view(token.begin()+1,token.end())).size();
  134. }
  135. m+=token.size();
  136. }
  137. }
  138. char* ptr = (char*)memory.allocate(new_len);
  139. if(ptr)
  140. {
  141. crank_copy* cpy = (crank_copy*)memory.allocate(sizeof(crank_copy));
  142. if(cpy)
  143. {
  144. new(cpy) crank_copy{.next=std::move(copies), .data=kstd::string_view(ptr,new_len)};
  145. copies = std::move(crank_ptr{cpy, &memory});
  146. auto dest = kstd::string_view(ptr,new_len);
  147. auto src_it = src.begin();
  148. auto dest_it = dest.begin();
  149. while(src_it!=src.end() && dest_it!=dest.end())
  150. {
  151. if(!istokenok(*src_it))
  152. {
  153. *dest_it = *src_it;
  154. dest_it++;
  155. src_it++;
  156. }
  157. else
  158. {
  159. auto token = extract_token(kstd::string_view(src_it,src.end()));
  160. if(token[0]=='$')
  161. {
  162. auto resolved = get_symbol(kstd::string_view(token.begin()+1,token.end()));
  163. memcpy(dest_it,resolved.begin(),resolved.size());
  164. src_it+=token.size();
  165. dest_it+=resolved.size();
  166. }
  167. else
  168. {
  169. memcpy(dest_it,token.begin(),token.size());
  170. src_it+=token.size();
  171. dest_it+=token.size();
  172. }
  173. }
  174. }
  175. return copies.ptr->data;
  176. }
  177. else
  178. {
  179. memory.desallocate(ptr);
  180. return kstd::string_view();
  181. }
  182. }
  183. return kstd::string_view();
  184. }
  185. kstd::string_view store(kstd::string_view key, kstd::string_view value)
  186. {
  187. crank_elem* elem = (crank_elem*)memory.allocate(sizeof(crank_elem));
  188. if(elem)
  189. {
  190. new(elem) crank_elem{.next=std::move(elements), .data=pair(key, value)};
  191. elements = std::move(crank_ptr{elem, &memory});
  192. return value;
  193. }
  194. return kstd::string_view();
  195. }
  196. kstd::string_view add_native(kstd::string_view key, crank_macro value)
  197. {
  198. crank_native* native = (crank_native*)memory.allocate(sizeof(crank_native));
  199. if(native)
  200. {
  201. new(native) crank_native{.next=std::move(natives), .data=pair(key, value)};
  202. natives = std::move(crank_ptr{native, &memory});
  203. return key;
  204. }
  205. return kstd::string_view();
  206. }
  207. bool string_is_in_range(kstd::string_view range, char* ptr)
  208. {
  209. return ptr>=range.begin() && ptr<range.end();
  210. }
  211. bool any_elem_is_in_range(kstd::string_view range)
  212. {
  213. auto elems = &elements;
  214. while(elems->ptr)
  215. {
  216. if(
  217. string_is_in_range(range, elems->ptr->data.first.begin())
  218. || string_is_in_range(range, elems->ptr->data.second.begin())
  219. )
  220. {
  221. return true;
  222. }
  223. elems = &(elems->ptr->next);
  224. }
  225. return false;
  226. }
  227. kstd::string_view get_symbol(kstd::string_view key)
  228. {
  229. auto elems = &elements;
  230. while(elems->ptr)
  231. {
  232. if(
  233. elems->ptr->data.first == key
  234. )
  235. {
  236. return elems->ptr->data.second;
  237. }
  238. elems = &(elems->ptr->next);
  239. }
  240. return kstd::string_view();
  241. }
  242. crank_macro& get_native(kstd::string_view key)
  243. {
  244. auto elems = &natives;
  245. while(elems->ptr)
  246. {
  247. if(
  248. elems->ptr->data.first == key
  249. )
  250. {
  251. return elems->ptr->data.second;
  252. }
  253. elems = &(elems->ptr->next);
  254. }
  255. static const char* id = "identity";
  256. return get_native(kstd::string_view((char*)id,8));
  257. }
  258. void collect()
  259. {
  260. auto elems = &elements;
  261. while(elems->ptr)
  262. {
  263. auto elems_after = &(elems->ptr->next);
  264. while(elems_after->ptr)
  265. {
  266. if(
  267. elems->ptr->data.first == elems_after->ptr->data.first
  268. )
  269. {
  270. *elems_after = std::move(elems_after->ptr->next);
  271. }
  272. else
  273. {
  274. elems_after = &(elems_after->ptr->next);
  275. }
  276. }
  277. elems = &(elems->ptr->next);
  278. }
  279. auto cps = &copies;
  280. while(cps->ptr)
  281. {
  282. if(
  283. ! any_elem_is_in_range(cps->ptr->data)
  284. )
  285. {
  286. memory.desallocate(cps->ptr->data.begin());
  287. *cps=std::move(cps->ptr->next);
  288. }
  289. else
  290. {
  291. cps = &(cps->ptr->next);
  292. }
  293. }
  294. }
  295. crank_context()
  296. {
  297. static const char* str_set = "set";
  298. add_native(kstd::string_view((char*)str_set,3), set);
  299. static const char* str_identity = "identity";
  300. add_native(kstd::string_view((char*)str_identity,8), identity);
  301. }
  302. kstd::string_view execute_command(kstd::string_view code);
  303. kstd::string_view eval(kstd::string_view);
  304. kstd::string_view eval_no_copy(kstd::string_view);
  305. };