ArkScript
A small, fast, functional and scripting language for video games
Repl.cpp
Go to the documentation of this file.
1#include <functional>
2#include <sstream>
3#include <cstdio>
4
5#include <Ark/REPL/Repl.hpp>
7
8
9namespace Ark
10{
11 Repl::Repl(uint16_t options, const std::vector<std::string>& libenv) :
12 m_options(options), m_lines(1), m_old_ip(0), m_libenv(libenv)
13 {}
14
16 {
18 Ark::VM vm(state);
19 state.setDebug(0);
20 std::string code;
21 bool init = false;
22
24 cui_setup();
25
26 while (true)
27 {
28 std::stringstream tmp_code;
29 unsigned open_parentheses = 0;
30 unsigned open_braces = 0;
31
32 tmp_code << code;
33 while (true)
34 {
35 std::string str_lines = "000";
36 if (std::to_string(m_lines).size() < 3)
37 {
38 std::size_t size = std::to_string(m_lines).size();
39 str_lines.replace((str_lines.size() - size), size, std::to_string(m_lines));
40 }
41 else
42 str_lines = std::to_string(m_lines);
43
44 std::string prompt = "main:" + str_lines + "> ";
45 char const* buf { nullptr };
46 do
47 {
48 buf = m_repl.input(prompt);
49 } while ((buf == nullptr) && (errno == EAGAIN));
50 std::string line = (buf != nullptr) ? std::string(buf) : "";
51
52 // line history
53 m_repl.history_add(line);
54 trim_whitespace(line);
55
56 // specific commands handling
57 if (line == "(quit)" || buf == nullptr)
58 {
59 std::cout << "\nExiting REPL\n";
60 return 1;
61 }
62
63 if (!line.empty())
64 tmp_code << line << "\n";
65 open_parentheses += count_open_parentheses(line);
66 open_braces += count_open_braces(line);
67
68 // lines number incrementation
69 ++m_lines;
70 if (open_parentheses == 0 && open_braces == 0)
71 break;
72 }
73
74 // save a valid ip if execution failed
76 if (!tmp_code.str().empty())
77 {
78 if (state.doString(tmp_code.str()))
79 {
80 // for only one vm init
81 if (init == false)
82 {
83 vm.init();
84 init = true;
85 }
86 if (vm.safeRun(*vm.m_execution_contexts[0]) == 0)
87 {
88 // save good code
89 code = tmp_code.str();
90 // place ip to end of bytecode intruction (HALT)
91 --vm.m_execution_contexts[0]->ip;
92 }
93 else
94 {
95 // reset ip if execution failed
97 }
98
99 state.reset();
100 }
101 else
102 std::cout << "Ark::State::doString failed\n";
103 }
104 }
105
106 return 0;
107 }
108
110 {
111 std::printf(
112 "ArkScript REPL -- Version %i.%i.%i [LICENSE: Mozilla Public License 2.0]\n"
113 "Type \"(quit)\" to quit.\n",
117 }
118
119 int Repl::count_open_parentheses(const std::string& line)
120 {
121 int open_parentheses = 0;
122
123 for (const char& c : line)
124 {
125 switch (c)
126 {
127 case '(': ++open_parentheses; break;
128 case ')': --open_parentheses; break;
129 }
130 }
131
132 return open_parentheses;
133 }
134
135 int Repl::count_open_braces(const std::string& line)
136 {
137 int open_braces = 0;
138
139 for (const char& c : line)
140 {
141 switch (c)
142 {
143 case '{': ++open_braces; break;
144 case '}': --open_braces; break;
145 }
146 }
147
148 return open_braces;
149 }
150
151 void Repl::trim_whitespace(std::string& line)
152 {
153 size_t string_begin = line.find_first_not_of(" \t");
154 if (std::string::npos != string_begin)
155 {
156 size_t string_end = line.find_last_not_of(" \t");
157 line = line.substr(string_begin, string_end - string_begin + 1);
158 }
159 }
160
162 {
163 using namespace std::placeholders;
164
165 m_repl.set_completion_callback(std::bind(&hook_completion, _1, _2, std::cref(KeywordsDict)));
166 m_repl.set_highlighter_callback(std::bind(&hook_color, _1, _2, std::cref(ColorsRegexDict)));
167 m_repl.set_hint_callback(std::bind(&hook_hint, _1, _2, _3, std::cref(KeywordsDict)));
168
169 m_repl.set_word_break_characters(" \t.,-%!;:=*~^'\"/?<>|[](){}");
170 m_repl.set_completion_count_cutoff(128);
171 m_repl.set_double_tab_completion(false);
172 m_repl.set_complete_on_empty(true);
173 m_repl.set_beep_on_ambiguous_completion(false);
174 m_repl.set_no_color(false);
175 }
176}
constexpr int ARK_VERSION_MAJOR
Definition: Constants.hpp:16
constexpr int ARK_VERSION_PATCH
Definition: Constants.hpp:18
constexpr int ARK_VERSION_MINOR
Definition: Constants.hpp:17
ArkScript REPL - Read Eval Print Loop.
replxx utilities
Replxx::completions_t hook_completion(std::string const &context, int &contextLen, std::vector< std::string > const &user_data)
Definition: Utils.cpp:45
void hook_color(std::string const &str, Replxx::colors_t &colors, std::vector< std::pair< std::string, Replxx::Color > > const &user_data)
Definition: Utils.cpp:69
Replxx::hints_t hook_hint(std::string const &context, int &contextLen, Replxx::Color &color, std::vector< std::string > const &examples)
Definition: Utils.cpp:94
void cui_setup()
Definition: Repl.cpp:161
int run()
Start the REPL.
Definition: Repl.cpp:15
Repl(uint16_t options, const std::vector< std::string > &libenv)
Construct a new Repl object.
Definition: Repl.cpp:11
std::vector< std::string > m_libenv
Definition: Repl.hpp:47
int count_open_braces(const std::string &line)
Definition: Repl.cpp:135
uint16_t m_options
Definition: Repl.hpp:43
void trim_whitespace(std::string &line)
Definition: Repl.cpp:151
int count_open_parentheses(const std::string &line)
Definition: Repl.cpp:119
int m_old_ip
Definition: Repl.hpp:46
Replxx m_repl
Definition: Repl.hpp:44
unsigned m_lines
Definition: Repl.hpp:45
void print_repl_header()
Definition: Repl.cpp:109
Ark state to handle the dirty job of loading and compiling ArkScript code.
Definition: State.hpp:31
void reset() noexcept
Reset State (all member variables related to execution)
Definition: State.cpp:342
void setDebug(unsigned level) noexcept
Set the debug level.
Definition: State.cpp:191
bool doString(const std::string &code)
Compile a string (representing ArkScript code) and store resulting bytecode in m_bytecode.
Definition: State.cpp:151
The ArkScript virtual machine, executing ArkScript bytecode.
Definition: VM.hpp:48
std::vector< std::unique_ptr< internal::ExecutionContext > > m_execution_contexts
Definition: VM.hpp:171
int safeRun(internal::ExecutionContext &context, std::size_t untilFrameCount=0)
Run ArkScript bytecode inside a try catch to retrieve all the exceptions and display a stack trace if...
Definition: VM.cpp:260
void init() noexcept
Initialize the VM according to the parameters.
Definition: VM.cpp:33
Definition: Builtins.hpp:21
const std::vector< std::pair< std::string, Replxx::Color > > ColorsRegexDict
const std::vector< std::string > KeywordsDict