1use alloc::fmt::Debug;
2use alloc::string::{String, ToString};
3use alloc::vec::Vec;
4use core::mem;
5
6
7
8use pest::iterators::Pair;
9use pest_derive::Parser;
10use simple_detailed_error::SimpleError;
11
12use statement_parsing::WalkInput;
13
14use crate::engine::context::ContextBuilder;
15use crate::engine::Engine;
16use crate::execution::ast::{Statement, AST};
17use crate::execution::RuntimeVariable;
18use crate::function::{MoonFunction, ToAbstractFunction};
19use crate::value::FullValue;
20use crate::HashMap;
21use crate::HashSet;
22use crate::LazyLock;
23
24
25pub(crate) mod value_parsing;
26pub(crate) mod statement_parsing;
27pub mod error;
28
29#[derive(Parser)]
30#[grammar = "language_definition.pest"]
31pub(crate) struct SimpleParser;
32
33#[derive(Clone, Debug)]
34pub(crate) struct FunctionInfo {
35 can_inline_result: bool,
36 function: MoonFunction,
37 return_type_name: Option<String>,
38}
39
40impl FunctionInfo {
41 pub(crate) fn new<Dummy, Params, ReturnValue, Function, AbstractFunction: ToAbstractFunction<Params, ReturnValue, Function, Dummy>>
42 (function: AbstractFunction) -> Self {
43 Self::new_raw(function.abstract_function())
44 }
45
46 pub(crate) const fn new_raw(function: MoonFunction) -> Self {
47 Self { function, return_type_name: None, can_inline_result: false }
48 }
49
50 pub(crate) const fn inline(mut self) -> FunctionInfo {
51 self.can_inline_result = true;
52 self
53 }
54}
55
56#[derive(Clone, Debug)]
58pub struct FunctionDefinition {
59 pub(crate) associated_type_name: Option<String>,
60 pub(crate) module_name: Option<String>,
61 pub(crate) function_name: String,
62 pub(crate) function_info: FunctionInfo,
63}
64
65impl FunctionDefinition {
66 pub fn new<Name: Into<String>, Dummy, Params, ReturnValue, Function, AbstractFunction: ToAbstractFunction<Params, ReturnValue, Function, Dummy>>
90 (function_name: Name, function: AbstractFunction) -> Self {
91 let mut function_info = FunctionInfo::new_raw(function.abstract_function());
92 function_info.return_type_name = MoonValueKind::get_kind_string_of::<ReturnValue>();
93 Self {
94 function_info: function_info,
95 function_name: function_name.into(),
96 module_name: None,
97 associated_type_name: None,
98 }
99 }
100
101 pub fn module_name<Name: Into<String>>(mut self, module_name: Name) -> Self {
103 self.module_name = Some(module_name.into());
104 self
105 }
106
107 pub fn associated_type_name<'input, Name: Into<MoonValueKind<'input>>>(mut self, associated_type_name: Name) -> Self {
123 self.associated_type_name = associated_type_name.into().get_moon_value_type().map(|string| string.to_string());
124 self
125 }
126
127 pub fn associated_type_of<T>(mut self) -> Self {
145 self.associated_type_name = MoonValueKind::get_kind_string_of::<T>();
146 self
147 }
148
149 pub const fn inline(mut self) -> Self {
152 self.function_info.can_inline_result = true;
153 self
154 }
155
156 pub fn known_return_type_name<'input, Name: Into<MoonValueKind<'input>>>(mut self, return_type_name: Name) -> Self {
159 self.function_info.return_type_name = return_type_name.into().get_moon_value_type().map(|string| string.to_string());
160 self
161 }
162
163 pub fn known_return_type_of<T>(mut self) -> Self {
168 self.function_info.return_type_name = MoonValueKind::get_kind_string_of::<T>();
169 self
170 }
171}
172
173
174struct Privatize;
175
176pub enum MoonValueKind<'selflf> {
178 Null,
179 Boolean,
180 Integer,
181 Decimal,
182 String,
183 Array,
184 Function,
185 Invalid,
186 #[allow(private_interfaces)]
187 CustomStr(&'selflf str, Privatize),
188 #[allow(private_interfaces)]
189 CustomString(String, Privatize),
190}
191
192static RESERVED_MOON_VALUE_KINDS: LazyLock<HashSet<String>> = LazyLock::new(|| {
193 [MoonValueKind::Null, MoonValueKind::Boolean, MoonValueKind::Integer,
194 MoonValueKind::Decimal, MoonValueKind::String, MoonValueKind::Array,
195 MoonValueKind::Function]
196 .map(|value_kind| value_kind.get_moon_value_type().unwrap().to_string())
197 .into_iter()
198 .collect::<HashSet<String>>()
199});
200
201pub(crate) static RUST_TYPES_TO_MOON_VALUE_KINDS: LazyLock<HashMap<&'static str, String>> = LazyLock::new(|| {
202 [
203 (core::any::type_name::<()>(), MoonValueKind::Null),
204 (core::any::type_name::<bool>(), MoonValueKind::Boolean),
205 (core::any::type_name::<i8>(), MoonValueKind::Integer),
206 (core::any::type_name::<i16>(), MoonValueKind::Integer),
207 (core::any::type_name::<i32>(), MoonValueKind::Integer),
208 (core::any::type_name::<i64>(), MoonValueKind::Integer),
209 (core::any::type_name::<i128>(), MoonValueKind::Integer),
210 (core::any::type_name::<isize>(), MoonValueKind::Integer),
211 (core::any::type_name::<u8>(), MoonValueKind::Integer),
212 (core::any::type_name::<u16>(), MoonValueKind::Integer),
213 (core::any::type_name::<u32>(), MoonValueKind::Integer),
214 (core::any::type_name::<u64>(), MoonValueKind::Integer),
215 (core::any::type_name::<u128>(), MoonValueKind::Integer),
216 (core::any::type_name::<usize>(), MoonValueKind::Integer),
217 (core::any::type_name::<f32>(), MoonValueKind::Decimal),
218 (core::any::type_name::<f64>(), MoonValueKind::Decimal),
219 (core::any::type_name::<String>(), MoonValueKind::String),
220 ]
221 .map(|(rust_type, moon_value_kind)| {
222 (rust_type, moon_value_kind.get_moon_value_type().unwrap().to_string())
223 })
224 .into_iter()
225 .collect()
226});
227
228
229static RESULT_TYPE_PREFIX: LazyLock<String> = LazyLock::new(|| {
230 let result = core::any::type_name::<Result<(), ()>>();
231 let result_start = result.find(r"<").unwrap();
232 result[0..result_start + 1].to_string()
233});
234
235fn decouple_ok_argument_from_its_result(type_in_use: &str) -> Option<&str> {
236 if !type_in_use.starts_with(&*RESULT_TYPE_PREFIX) { return None; };
237
238 let type_in_use = &type_in_use[RESULT_TYPE_PREFIX.len()..];
239 let mut opened_brackets_and_diamonds = 0_usize;
240 let end = type_in_use.chars().enumerate().filter(|(_, char)| {
241 match char {
242 '(' | '<' => opened_brackets_and_diamonds += 1,
243 ')' | '>' => opened_brackets_and_diamonds -= 1,
244 ',' => return true,
245 _ => {}
246 }
247 false
248 }).next().unwrap().0;
249 Some(&type_in_use[..end])
250}
251
252impl MoonValueKind<'_> {
253 pub(crate) fn get_kind_string_of<T>() -> Option<String> {
254 RUST_TYPES_TO_MOON_VALUE_KINDS
255 .get(core::any::type_name::<T>()).cloned()
256 .map(|string|
257 decouple_ok_argument_from_its_result(&string).map(|s| s.to_string()).unwrap_or(string)
258 )
259 .or_else(||
260 MoonValueKind::from(core::any::type_name::<T>())
261 .get_moon_value_type().map(|string| string.to_string())
262 )
263 .filter(|name| !name.eq("null"))
264 }
265
266 pub(crate) fn get_moon_value_type(&self) -> Option<&str> {
267 Some(match self {
268 MoonValueKind::Null => "null",
269 MoonValueKind::Boolean => "bool",
270 MoonValueKind::Integer => "int",
271 MoonValueKind::Decimal => "decimal",
272 MoonValueKind::String => "string",
273 MoonValueKind::Array => "array",
274 MoonValueKind::Function => "function",
275 MoonValueKind::Invalid => return None,
276 MoonValueKind::CustomStr(str, _) => str,
277 MoonValueKind::CustomString(str, _) => str
278 })
279 }
280}
281
282impl<'typename> From<&'typename str> for MoonValueKind<'typename> {
283 fn from(value: &'typename str) -> Self {
284 if RESERVED_MOON_VALUE_KINDS.contains(value) {
285 return Self::Invalid;
286 }
287 Self::CustomStr(value, Privatize)
288 }
289}
290
291impl From<String> for MoonValueKind<'_> {
292 fn from(value: String) -> Self {
293 if RESERVED_MOON_VALUE_KINDS.contains(&value) {
294 return Self::Invalid;
295 }
296 Self::CustomString(value, Privatize)
297 }
298}
299
300fn optimize_variables(context: &mut ContextBuilder, inlineable_variables: Vec<(String, usize)>, statements: &mut Vec<Statement>) -> (Vec<RuntimeVariable>, HashMap<String, usize>) {
301 let variables = context.take_all_variables();
302 let mut variables = variables.into_iter()
303 .flat_map(|(block_level, variables)| {
304 variables.into_iter().enumerate()
305 .map(move |(var_index, variable)| ((block_level, var_index), variable))
306 }).collect::<HashMap<_, _>>();
307
308
309 let mut used_variables = HashMap::new();
310 statements.iter_mut().for_each(|statement| {
311 statement_parsing::walk_statement(&mut |input| {
312 match input {
313 WalkInput::Statement(block) => {
314 match block {
315 Statement::UnoptimizedAssignament { block_level, var_index, .. } => {
316 if !used_variables.contains_key(&(*block_level, *var_index)) {
317 log::trace!("Found used variable of block {block_level} and index {var_index}");
318 let variable = variables.remove(&(*block_level, *var_index)).unwrap();
319 log::trace!(" - Variable: {variable:?})");
320 used_variables.insert((*block_level, *var_index), variable);
321 }
322 }
323 _ => {}
324 }
325 }
326 WalkInput::Value(value) => {
327 match value {
328 FullValue::Variable { block_level, var_index } => {
329 if !used_variables.contains_key(&(*block_level, *var_index)) {
330 log::trace!("Found used variable of block {block_level} and index {var_index}");
331 let variable = variables.remove(&(*block_level, *var_index)).unwrap();
332 log::trace!(" - Variable: {variable:?})");
333 used_variables.insert((*block_level, *var_index), variable);
334 }
335 }
336 _ => {}
337 }
338 }
339 }
340 }, statement)
341 });
342 let mut used_variables = used_variables.into_iter().collect::<Vec<_>>();
343
344 used_variables.sort_by(|((block_a, index_a), _), ((block_b, index_b), _)| {
345 block_a.cmp(block_b).then_with(|| index_a.cmp(index_b))
346 });
347
348 let used_variables_and_new_indexes = used_variables.into_iter()
349 .enumerate()
350 .map(|(index, ((block_level, var_level), variable))| ((block_level, var_level), (index, variable)))
351 .collect::<HashMap<_, _>>();
352
353 let parameterized_variables = inlineable_variables.into_iter()
354 .filter(|(_, index)| used_variables_and_new_indexes.contains_key(&(0, *index)))
355 .map(|(name, index)| {
356 let final_variable_index = used_variables_and_new_indexes.get(&(0, index)).unwrap().0;
357 (name, final_variable_index)
358 })
359 .collect();
360
361 statements.iter_mut().for_each(|statement| {
362 statement_parsing::walk_statement(&mut |input| {
363 match input {
364 WalkInput::Statement(block) => {
365 match block {
366 Statement::UnoptimizedAssignament { block_level, var_index, value } => {
367 let direct_index = used_variables_and_new_indexes.get(&(*block_level, *var_index)).unwrap().0;
368 log::trace!("Substitued variable of assignament for block {block_level} and index {var_index} for simplified index {direct_index}");
369 *block = Statement::OptimizedAssignament { var_index: direct_index, value: mem::replace(value, FullValue::Null) };
370 }
371 _ => {}
372 }
373 }
374 WalkInput::Value(value) => {
375 match value {
376 FullValue::Variable { block_level, var_index } => {
377 let direct_index = used_variables_and_new_indexes.get(&(*block_level, *var_index)).unwrap().0;
378 log::trace!("Substitued variable of value for block {block_level} and index {var_index} for simplified index {direct_index}");
379 *value = FullValue::DirectVariable(direct_index);
380 }
381 _ => {}
382 }
383 }
384 }
385 }, statement)
386 });
387
388 let mut used_variables_and_new_indexes = used_variables_and_new_indexes.into_iter()
389 .map(|(_, variable)| variable)
390 .collect::<Vec<_>>();
391 used_variables_and_new_indexes.sort_by_key(|(index, _)| *index);
392
393 let variables = used_variables_and_new_indexes.into_iter()
394 .map(|(_, variable)| RuntimeVariable { value: variable.first_value })
395 .collect::<Vec<_>>();
396 (variables, parameterized_variables)
397}
398
399pub(crate) fn build_ast<'input>(token: Pair<'input, Rule>, base: &Engine, mut context: ContextBuilder) -> Result<AST, Vec<SimpleError<'input>>> {
400 if token.as_rule() != Rule::BASE_STATEMENTS {}
401 let statements_tokens = token.into_inner().next().unwrap();
402 context.started_parsing = true;
403 let inlineable_variables = context.in_use_variables.get(0).map(|(_, variables)| {
404 variables.iter().enumerate()
405 .filter(|(_, variable)| { variable.current_known_value.is_none() })
406 .map(|(block_0_var_index, variable)| (variable.name.clone(), block_0_var_index))
407 .collect::<Vec<_>>()
408 }).unwrap_or_default();
409 let mut statements = statement_parsing::build_token(statements_tokens, base, &mut context, true)?;
410 replace_last_fn_call_for_return_statement(&mut statements);
411
412 let (variables, parameterized_variables) = optimize_variables(&mut context, inlineable_variables, &mut statements);
413 Ok(AST { statements, variables, parameterized_variables })
414}
415
416fn replace_last_fn_call_for_return_statement(statements: &mut Vec<Statement>) {
417 if let Some(last_statement) = statements.last_mut() {
418 let is_fn_call = match last_statement {
419 Statement::FnCall(_) => true,
420 _ => false,
421 };
422 if is_fn_call {
423 let fn_call = match mem::replace(last_statement, Statement::ReturnCall(FullValue::Null)) {
424 Statement::FnCall(function) => function,
425 _ => unreachable!()
426 };
427 *last_statement = Statement::ReturnCall(FullValue::Function(fn_call));
428 }
429 }
430}
431
432fn line_and_column_of_token(token: &Pair<Rule>, context: &mut ContextBuilder) -> (usize, usize) {
433 let mut line_and_column = token.line_col();
434 if context.parsing_position_column_is_fixed || line_and_column.0 <= 1 {
435 line_and_column = (line_and_column.0 + context.start_parsing_position_offset.0, line_and_column.1 + context.start_parsing_position_offset.1)
436 } else {
437 line_and_column = (line_and_column.0 + context.start_parsing_position_offset.0, line_and_column.1)
438 }
439 line_and_column
440}
441
442
443pub(crate) trait AddSourceOfError<'input> {
444 fn add_where_error(self, input: &'input str, line_and_column: (usize, usize)) -> Self;
445}
446
447
448impl<'input, V> AddSourceOfError<'input> for Result<V, Vec<SimpleError<'input>>> {
449 fn add_where_error(self, input: &'input str, line_and_column: (usize, usize)) -> Self {
450 self.map_err(|errors| errors.into_iter().map(|error| {
451 if error.current_at().is_none() { error.at(input).start_point_of_error(line_and_column.0, line_and_column.1) } else { error }
452 }).collect::<Vec<_>>())
453 }
454}