ArkScript
A small, fast, functional and scripting language for video games
JsonCompiler.cpp
Go to the documentation of this file.
2
4
5#include <utility>
6#include <exception>
7#include <stdexcept>
8#include <string>
9
10namespace Ark
11{
12 using namespace internal;
13
14 JsonCompiler::JsonCompiler(unsigned debug, const std::vector<std::string>& libenv, uint16_t options) :
15 m_parser(debug, options, libenv), m_optimizer(options),
16 m_options(options), m_debug(debug)
17 {}
18
19 void JsonCompiler::feed(const std::string& code, const std::string& filename)
20 {
21 m_parser.feed(code, filename);
22
24 mp.feed(m_parser.ast());
25 m_optimizer.feed(mp.ast());
26 }
27
29 {
30 return _compile(m_optimizer.ast());
31 }
32
33 template <typename... Args>
34 std::string string_format(const std::string& format, Args&&... args)
35 {
36 constexpr size_t buffer_size = 8192;
37 static char buf[buffer_size] = { 0 };
38 std::string to_return = "";
39 while (snprintf(buf, buffer_size - 1, format.c_str(), std::forward<Args>(args)...) == buffer_size - 1)
40 to_return += std::string(buf);
41 to_return += std::string(buf);
42 return to_return;
43 }
44
45 std::string JsonCompiler::_compile(const Node& node)
46 {
47 std::string json = "";
48
49 switch (node.nodeType())
50 {
51 case NodeType::Symbol:
52 {
53 json += string_format(
54 R"({"type": "Symbol", "name": "%s"})",
55 node.string().c_str());
56 break;
57 }
58
59 case NodeType::Capture:
60 {
61 json += string_format(
62 R"({"type": "Capture", "name": "%s"})",
63 node.string().c_str());
64 break;
65 }
66
67 case NodeType::GetField:
68 {
69 json += string_format(
70 R"({"type": "GetField", "name": "%s"})",
71 node.string().c_str());
72 break;
73 }
74
75 case NodeType::String:
76 {
77 json += string_format(
78 R"({"type": "String", "value": "%s"})",
79 node.string().c_str());
80 break;
81 }
82
83 case NodeType::Number:
84 {
85 json += string_format(
86 R"({"type": "Number", "value": %f})",
87 node.number());
88 break;
89 }
90
91 case NodeType::List:
92 {
93 if (node.constList().size() > 1 && node.constList()[0].nodeType() == NodeType::Keyword)
94 {
95 Node keyword = node.constList()[0];
96 switch (keyword.keyword())
97 {
98 case Keyword::Fun:
99 {
100 // (fun (args) (body))
101 std::string args = "";
102 Node args_node = node.constList()[1];
103 for (std::size_t i = 0, end = args_node.constList().size(); i < end; ++i)
104 {
105 args += _compile(args_node.constList()[i]);
106 if (end > 1 && i != end - 1)
107 args += ", ";
108 }
109
110 json += string_format(
111 R"({"type": "Fun", "args": [%s], "body": %s})",
112 args.c_str(), _compile(node.constList()[2]).c_str());
113 break;
114 }
115
116 case Keyword::Let:
117 {
118 // (let name value)
119 json += string_format(
120 R"({"type": "Let", "name": %s, "value": %s})",
121 _compile(node.constList()[1]).c_str(), _compile(node.constList()[2]).c_str());
122 break;
123 }
124
125 case Keyword::Mut:
126 {
127 // (mut name value)
128 json += string_format(
129 R"({"type": "Mut", "name": %s, "value": %s})",
130 _compile(node.constList()[1]).c_str(), _compile(node.constList()[2]).c_str());
131 break;
132 }
133
134 case Keyword::Set:
135 {
136 // (set name value)
137 json += string_format(
138 R"({"type": "Set", "name": %s, "value": %s})",
139 _compile(node.constList()[1]).c_str(), _compile(node.constList()[2]).c_str());
140 break;
141 }
142
143 case Keyword::If:
144 {
145 // (if condition then else)
146 json += string_format(
147 R"({"type": "If", "condition": %s, "then": %s, "else": %s})",
148 _compile(node.constList()[1]).c_str(), _compile(node.constList()[2]).c_str(), _compile(node.constList()[3]).c_str());
149 break;
150 }
151
152 case Keyword::While:
153 {
154 // (while condition body)
155 json += string_format(
156 R"({"type": "While", "condition": %s, "body": %s})",
157 _compile(node.constList()[1]).c_str(), _compile(node.constList()[2]).c_str());
158 break;
159 }
160
161 case Keyword::Begin:
162 {
163 // (begin body)
164 json += R"({"type": "Begin", "children": )";
165 json += toJsonList(node, 1) + "}";
166 break;
167 }
168
169 case Keyword::Import:
170 {
171 // (import value)
172 json += string_format(
173 R"({"type": "Import", "value": %s})",
174 _compile(node.constList()[1]).c_str());
175 break;
176 }
177
178 case Keyword::Quote:
179 {
180 // (quote value)
181 json += string_format(
182 R"({"type": "Quote", "value": %s})",
183 _compile(node.constList()[1]).c_str());
184 break;
185 }
186
187 case Keyword::Del:
188 {
189 // (del value)
190 json += string_format(
191 R"({"type": "Del", "value": %s})",
192 _compile(node.constList()[1]).c_str());
193 break;
194 }
195 }
196 }
197 else if (node.constList().size() > 1 && node.constList()[0].nodeType() == NodeType::Symbol)
198 {
199 // (foo bar 1)
200 json += string_format(
201 R"({"type": "FunctionCall", "name": %s, "args": )",
202 _compile(node.constList()[0]).c_str());
203 json += toJsonList(node, 1) + "}";
204 }
205 else
206 json += toJsonList(node, 0);
207
208 break;
209 }
210
211 default:
212 throw std::runtime_error(string_format(
213 "Not handled NodeType::%s (%s at %zu:%zu), please report this error on GitHub",
214 nodeTypes[static_cast<std::size_t>(node.nodeType())].data(),
215 node.filename().c_str(),
216 node.line(),
217 node.col()));
218 }
219 return json;
220 }
221
222 std::string JsonCompiler::toJsonList(const Node& node, std::size_t start)
223 {
224 std::string json = "[";
225 for (std::size_t i = start, end = node.constList().size(); i < end; ++i)
226 {
227 json += _compile(node.constList()[i]);
228 if (i != end - 1)
229 json += ", ";
230 }
231 json += "]";
232 return json;
233 }
234}
Handles the macros and their expansion in ArkScript source code.
unsigned m_debug
the debug level of the compiler
void feed(const std::string &code, const std::string &filename=ARK_NO_NAME_FILE)
Feed the differents variables with information taken from the given source code file.
JsonCompiler(unsigned debug, const std::vector< std::string > &libenv, uint16_t options=DefaultFeatures)
Construct a new JsonCompiler object.
std::string compile()
Start the compilation.
internal::Parser m_parser
std::string _compile(const internal::Node &node)
Compile a single node and return its representation.
internal::Optimizer m_optimizer
std::string toJsonList(const internal::Node &node, std::size_t start)
Convert a NodeType::List to a JSON list.
The class handling the macros definitions and calls, given an AST.
Definition: Processor.hpp:31
const Node & ast() const noexcept
Return the modified AST.
Definition: Processor.cpp:46
void feed(const Node &ast)
Send the complete AST (after the inclusions and stuff), and work on it.
Definition: Processor.cpp:30
A node of an Abstract Syntax Tree for ArkScript.
Definition: Node.hpp:29
NodeType nodeType() const noexcept
Return the node type.
Definition: Node.cpp:126
const std::string & filename() const noexcept
Return the filename in which this node was created.
Definition: Node.cpp:174
const std::string & string() const noexcept
Return the string held by the value (if the node type allows it)
Definition: Node.cpp:92
const std::vector< Node > & constList() const noexcept
Return the list of sub-nodes held by the node.
Definition: Node.cpp:119
Keyword keyword() const noexcept
Return the keyword held by the value (if the node type allows it)
Definition: Node.cpp:102
std::size_t col() const noexcept
Get the column at which this node was created.
Definition: Node.cpp:169
double number() const noexcept
Return the number held by the value (if the node type allows it)
Definition: Node.cpp:97
std::size_t line() const noexcept
Get the line at which this node was created.
Definition: Node.cpp:164
void feed(const Node &ast)
Send the AST to the optimizer, then run the different optimization strategies on it.
Definition: Optimizer.cpp:9
const Node & ast() const noexcept
Returns the modified AST.
Definition: Optimizer.cpp:17
const Node & ast() const noexcept
Return the generated AST.
Definition: Parser.cpp:59
void feed(const std::string &code, const std::string &filename=ARK_NO_NAME_FILE)
Give the code to parse.
Definition: Parser.cpp:21
constexpr std::array< std::string_view, 11 > nodeTypes
Definition: Common.hpp:43
Definition: Builtins.hpp:21
std::string string_format(const std::string &format, Args &&... args)