1#[macro_export]
105macro_rules! eure {
106 ({}) => {{
114 $crate::document::EureDocument::new_empty()
115 }};
116
117 ({ $($body:tt)* }) => {{
119 #[allow(unused_mut)]
120 let mut c = $crate::document::constructor::DocumentConstructor::new();
121 $crate::eure!(@stmt c; $($body)*);
122 c.finish()
123 }};
124
125 (@value_tt null) => { $crate::value::PrimitiveValue::Null };
138
139 (@value_tt true) => { true };
141 (@value_tt false) => { false };
142
143 (@value_tt $v:literal) => { $v };
145
146 (@value_tt $v:expr) => { $v };
148
149 (@array_items $c:ident;) => {};
158
159 (@array_items $c:ident; , $($rest:tt)*) => {{
161 $crate::eure!(@array_items $c; $($rest)*);
162 }};
163
164 (@array_items $c:ident; @ code ($content:literal) $($rest:tt)*) => {{
166 let scope = $c.begin_scope();
167 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
168 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
169 $c.end_scope(scope).unwrap();
170 $crate::eure!(@array_items $c; $($rest)*);
171 }};
172
173 (@array_items $c:ident; @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
175 let scope = $c.begin_scope();
176 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
177 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
178 $c.end_scope(scope).unwrap();
179 $crate::eure!(@array_items $c; $($rest)*);
180 }};
181
182 (@array_items $c:ident; [$($inner:tt)*] $($rest:tt)*) => {{
184 let scope = $c.begin_scope();
185 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
186 $c.bind_empty_array().unwrap();
187 $crate::eure!(@array_items $c; $($inner)*);
188 $c.end_scope(scope).unwrap();
189 $crate::eure!(@array_items $c; $($rest)*);
190 }};
191
192 (@array_items $c:ident; ($($inner:tt)*) $($rest:tt)*) => {{
194 let scope = $c.begin_scope();
195 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
196 $c.bind_empty_tuple().unwrap();
197 $crate::eure!(@tuple_items $c 0; $($inner)*);
198 $c.end_scope(scope).unwrap();
199 $crate::eure!(@array_items $c; $($rest)*);
200 }};
201
202 (@array_items $c:ident; $item:tt $($rest:tt)*) => {{
204 let scope = $c.begin_scope();
205 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
206 $c.bind_from($crate::eure!(@value_tt $item)).unwrap();
207 $c.end_scope(scope).unwrap();
208 $crate::eure!(@array_items $c; $($rest)*);
209 }};
210
211 (@tuple_items $c:ident $idx:expr;) => {};
220
221 (@tuple_items $c:ident $idx:expr; , $($rest:tt)*) => {{
223 $crate::eure!(@tuple_items $c $idx; $($rest)*);
224 }};
225
226 (@tuple_items $c:ident $idx:expr; @ code ($content:literal) $($rest:tt)*) => {{
228 let scope = $c.begin_scope();
229 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
230 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
231 $c.end_scope(scope).unwrap();
232 $crate::eure!(@tuple_items $c ($idx + 1); $($rest)*);
233 }};
234
235 (@tuple_items $c:ident $idx:expr; @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
237 let scope = $c.begin_scope();
238 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
239 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
240 $c.end_scope(scope).unwrap();
241 $crate::eure!(@tuple_items $c ($idx + 1); $($rest)*);
242 }};
243
244 (@tuple_items $c:ident $idx:expr; [$($inner:tt)*] $($rest:tt)*) => {{
246 let scope = $c.begin_scope();
247 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
248 $c.bind_empty_array().unwrap();
249 $crate::eure!(@array_items $c; $($inner)*);
250 $c.end_scope(scope).unwrap();
251 $crate::eure!(@tuple_items $c ($idx + 1); $($rest)*);
252 }};
253
254 (@tuple_items $c:ident $idx:expr; ($($inner:tt)*) $($rest:tt)*) => {{
256 let scope = $c.begin_scope();
257 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
258 $c.bind_empty_tuple().unwrap();
259 $crate::eure!(@tuple_items $c 0; $($inner)*);
260 $c.end_scope(scope).unwrap();
261 $crate::eure!(@tuple_items $c ($idx + 1); $($rest)*);
262 }};
263
264 (@tuple_items $c:ident $idx:expr; $item:tt $($rest:tt)*) => {{
266 let scope = $c.begin_scope();
267 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
268 $c.bind_from($crate::eure!(@value_tt $item)).unwrap();
269 $c.end_scope(scope).unwrap();
270 $crate::eure!(@tuple_items $c ($idx + 1); $($rest)*);
271 }};
272
273 (@object_key $key:ident) => { stringify!($key) };
282
283 (@object_key $key:tt) => { $key };
285
286 (@object_items $c:ident;) => {};
294
295 (@object_items $c:ident; , $($rest:tt)*) => {{
297 $crate::eure!(@object_items $c; $($rest)*);
298 }};
299
300 (@object_items $c:ident; $key:tt => @ code ($content:literal) $($rest:tt)*) => {{
302 let scope = $c.begin_scope();
303 $c.navigate($crate::path::PathSegment::Value($crate::eure!(@object_key $key).into())).unwrap();
304 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
305 $c.end_scope(scope).unwrap();
306 $crate::eure!(@object_items $c; $($rest)*);
307 }};
308
309 (@object_items $c:ident; $key:tt => @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
311 let scope = $c.begin_scope();
312 $c.navigate($crate::path::PathSegment::Value($crate::eure!(@object_key $key).into())).unwrap();
313 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
314 $c.end_scope(scope).unwrap();
315 $crate::eure!(@object_items $c; $($rest)*);
316 }};
317
318 (@object_items $c:ident; $key:tt => [$($inner:tt)*] $($rest:tt)*) => {{
320 let scope = $c.begin_scope();
321 $c.navigate($crate::path::PathSegment::Value($crate::eure!(@object_key $key).into())).unwrap();
322 $c.bind_empty_array().unwrap();
323 $crate::eure!(@array_items $c; $($inner)*);
324 $c.end_scope(scope).unwrap();
325 $crate::eure!(@object_items $c; $($rest)*);
326 }};
327
328 (@object_items $c:ident; $key:tt => ($($inner:tt)*) $($rest:tt)*) => {{
330 let scope = $c.begin_scope();
331 $c.navigate($crate::path::PathSegment::Value($crate::eure!(@object_key $key).into())).unwrap();
332 $c.bind_empty_tuple().unwrap();
333 $crate::eure!(@tuple_items $c 0; $($inner)*);
334 $c.end_scope(scope).unwrap();
335 $crate::eure!(@object_items $c; $($rest)*);
336 }};
337
338 (@object_items $c:ident; $key:tt => $val:tt $($rest:tt)*) => {{
340 let scope = $c.begin_scope();
341 $c.navigate($crate::path::PathSegment::Value($crate::eure!(@object_key $key).into())).unwrap();
342 $c.bind_from($crate::eure!(@value_tt $val)).unwrap();
343 $c.end_scope(scope).unwrap();
344 $crate::eure!(@object_items $c; $($rest)*);
345 }};
346
347 (@stmt $c:ident;) => {};
361
362 (@stmt $c:ident; , $($rest:tt)*) => {{
364 $crate::eure!(@stmt $c; $($rest)*);
365 }};
366
367 (@stmt $c:ident; = ! $($rest:tt)*) => {{
370 $crate::eure!(@stmt $c; $($rest)*);
372 }};
373
374 (@stmt $c:ident; = - $v:literal $($rest:tt)*) => {{
377 $c.bind_from(-$v).unwrap();
378 $crate::eure!(@stmt $c; $($rest)*);
379 }};
380
381 (@stmt $c:ident; = @ code ($content:literal) $($rest:tt)*) => {{
383 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
384 $crate::eure!(@stmt $c; $($rest)*);
385 }};
386
387 (@stmt $c:ident; = @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
389 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
390 $crate::eure!(@stmt $c; $($rest)*);
391 }};
392
393 (@stmt $c:ident; = @ block ($content:literal) $($rest:tt)*) => {{
395 $c.bind_from($crate::text::Text::block_implicit($content)).unwrap();
396 $crate::eure!(@stmt $c; $($rest)*);
397 }};
398
399 (@stmt $c:ident; = @ block ($lang:literal, $content:literal) $($rest:tt)*) => {{
401 $c.bind_from($crate::text::Text::block($content, $lang)).unwrap();
402 $crate::eure!(@stmt $c; $($rest)*);
403 }};
404
405 (@stmt $c:ident; = [] $($rest:tt)*) => {{
407 $c.bind_empty_array().unwrap();
408 $crate::eure!(@stmt $c; $($rest)*);
409 }};
410
411 (@stmt $c:ident; = [$($items:tt)+] $($rest:tt)*) => {{
413 $c.bind_empty_array().unwrap();
414 $crate::eure!(@array_items $c; $($items)+);
415 $crate::eure!(@stmt $c; $($rest)*);
416 }};
417
418 (@stmt $c:ident; = () $($rest:tt)*) => {{
420 $c.bind_empty_tuple().unwrap();
421 $crate::eure!(@stmt $c; $($rest)*);
422 }};
423
424 (@stmt $c:ident; = ($($items:tt)+) $($rest:tt)*) => {{
426 $c.bind_empty_tuple().unwrap();
427 $crate::eure!(@tuple_items $c 0; $($items)+);
428 $crate::eure!(@stmt $c; $($rest)*);
429 }};
430
431 (@stmt $c:ident; = { $key:tt => $($inner:tt)+ } $($rest:tt)*) => {{
433 $c.bind_empty_map().unwrap();
434 $crate::eure!(@object_items $c; $key => $($inner)+);
435 $crate::eure!(@stmt $c; $($rest)*);
436 }};
437
438 (@stmt $c:ident; = $v:tt $($rest:tt)*) => {{
440 $c.bind_from($crate::eure!(@value_tt $v)).unwrap();
441 $crate::eure!(@stmt $c; $($rest)*);
442 }};
443
444 (@stmt $c:ident; @ $seg:ident $($rest:tt)*) => {{
446 let scope = $c.begin_scope();
447 $c.navigate($crate::path::PathSegment::Ident(
448 $crate::identifier::Identifier::new_unchecked(stringify!($seg))
449 )).unwrap();
450 $crate::eure!(@section_after_seg $c scope; $($rest)*);
451 }};
452
453 (@stmt $c:ident; $($tokens:tt)+) => {{
456 let scope = $c.begin_scope();
457 $crate::eure!(@path $c scope; $($tokens)+);
458 }};
459
460 (@section_after_seg $c:ident $scope:ident; . $seg:ident $($rest:tt)*) => {{
468 $c.navigate($crate::path::PathSegment::Ident(
469 $crate::identifier::Identifier::new_unchecked(stringify!($seg))
470 )).unwrap();
471 $crate::eure!(@section_after_seg $c $scope; $($rest)*);
472 }};
473
474 (@section_after_seg $c:ident $scope:ident; = $v:tt $($rest:tt)*) => {{
476 $c.bind_from($crate::eure!(@value_tt $v)).unwrap();
477 $crate::eure!(@section_bindings $c $scope; $($rest)*);
479 }};
480
481 (@section_after_seg $c:ident $scope:ident; {} $($rest:tt)*) => {{
483 $c.bind_empty_map().unwrap();
484 $c.end_scope($scope).unwrap();
485 $crate::eure!(@stmt $c; $($rest)*);
486 }};
487
488 (@section_after_seg $c:ident $scope:ident; { $($inner:tt)+ } $($rest:tt)*) => {{
490 $crate::eure!(@stmt $c; $($inner)+);
491 $c.end_scope($scope).unwrap();
492 $crate::eure!(@stmt $c; $($rest)*);
493 }};
494
495 (@section_after_seg $c:ident $scope:ident; $($rest:tt)*) => {{
497 $crate::eure!(@section_bindings $c $scope; $($rest)*);
498 }};
499
500 (@section_bindings $c:ident $scope:ident;) => {{
502 $c.end_scope($scope).unwrap();
503 }};
504
505 (@section_bindings $c:ident $scope:ident; , $($rest:tt)*) => {{
507 $crate::eure!(@section_bindings $c $scope; $($rest)*);
508 }};
509
510 (@section_bindings $c:ident $scope:ident; @ $seg:ident $($rest:tt)*) => {{
512 $c.end_scope($scope).unwrap();
513 $crate::eure!(@stmt $c; @ $seg $($rest)*);
514 }};
515
516 (@section_bindings $c:ident $scope:ident; $($tokens:tt)+) => {{
518 let inner_scope = $c.begin_scope();
519 $crate::eure!(@section_path $c $scope inner_scope; $($tokens)+);
520 }};
521
522 (@section_path $c:ident $section_scope:ident $scope:ident; $seg:ident $($rest:tt)*) => {{
524 $c.navigate($crate::path::PathSegment::Ident(
525 $crate::identifier::Identifier::new_unchecked(stringify!($seg))
526 )).unwrap();
527 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
528 }};
529
530 (@section_path $c:ident $section_scope:ident $scope:ident; % $ext:ident $($rest:tt)*) => {{
532 $c.navigate($crate::path::PathSegment::Extension(
533 $crate::identifier::Identifier::new_unchecked(stringify!($ext))
534 )).unwrap();
535 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
536 }};
537
538 (@section_path $c:ident $section_scope:ident $scope:ident; % $ext:literal $($rest:tt)*) => {{
540 $c.navigate($crate::path::PathSegment::Extension(
541 $ext.parse().unwrap()
542 )).unwrap();
543 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
544 }};
545
546 (@section_path $c:ident $section_scope:ident $scope:ident; # $idx:literal $($rest:tt)*) => {{
548 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
549 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
550 }};
551
552 (@section_path $c:ident $section_scope:ident $scope:ident; ($($tuple:tt)*) $($rest:tt)*) => {{
554 let key = $crate::eure!(@build_tuple_key; $($tuple)*);
555 $c.navigate($crate::path::PathSegment::Value(key)).unwrap();
556 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
557 }};
558
559 (@section_path $c:ident $section_scope:ident $scope:ident; $key:literal $($rest:tt)*) => {{
561 $c.navigate($crate::path::PathSegment::Value($key.into())).unwrap();
562 $crate::eure!(@section_after_path $c $section_scope $scope; $($rest)*);
563 }};
564
565 (@section_after_path $c:ident $section_scope:ident $scope:ident; [$($arr:tt)*] $($rest:tt)*) => {{
567 $crate::eure!(@section_array_marker $c $section_scope $scope [$($arr)*]; $($rest)*);
568 }};
569
570 (@section_after_path $c:ident $section_scope:ident $scope:ident; $($rest:tt)*) => {{
572 $crate::eure!(@section_terminal $c $section_scope $scope; $($rest)*);
573 }};
574
575 (@section_array_marker $c:ident $section_scope:ident $scope:ident []; $($rest:tt)*) => {{
577 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
578 $crate::eure!(@section_terminal $c $section_scope $scope; $($rest)*);
579 }};
580
581 (@section_array_marker $c:ident $section_scope:ident $scope:ident [$idx:literal]; $($rest:tt)*) => {{
583 $c.navigate($crate::path::PathSegment::ArrayIndex(Some($idx))).unwrap();
584 $crate::eure!(@section_terminal $c $section_scope $scope; $($rest)*);
585 }};
586
587 (@section_terminal $c:ident $section_scope:ident $scope:ident; . $($rest:tt)+) => {{
589 $crate::eure!(@section_path $c $section_scope $scope; $($rest)+);
590 }};
591
592 (@section_terminal $c:ident $section_scope:ident $scope:ident; = ! $($rest:tt)*) => {{
594 $c.end_scope($scope).unwrap();
595 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
596 }};
597
598 (@section_terminal $c:ident $section_scope:ident $scope:ident; = @ code ($content:literal) $($rest:tt)*) => {{
600 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
601 $c.end_scope($scope).unwrap();
602 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
603 }};
604
605 (@section_terminal $c:ident $section_scope:ident $scope:ident; = @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
607 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
608 $c.end_scope($scope).unwrap();
609 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
610 }};
611
612 (@section_terminal $c:ident $section_scope:ident $scope:ident; = @ block ($content:literal) $($rest:tt)*) => {{
614 $c.bind_from($crate::text::Text::block_implicit($content)).unwrap();
615 $c.end_scope($scope).unwrap();
616 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
617 }};
618
619 (@section_terminal $c:ident $section_scope:ident $scope:ident; = @ block ($lang:literal, $content:literal) $($rest:tt)*) => {{
621 $c.bind_from($crate::text::Text::block($content, $lang)).unwrap();
622 $c.end_scope($scope).unwrap();
623 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
624 }};
625
626 (@section_terminal $c:ident $section_scope:ident $scope:ident; = $v:tt $($rest:tt)*) => {{
628 $c.bind_from($crate::eure!(@value_tt $v)).unwrap();
629 $c.end_scope($scope).unwrap();
630 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
631 }};
632
633 (@section_terminal $c:ident $section_scope:ident $scope:ident; {} $($rest:tt)*) => {{
635 $c.bind_empty_map().unwrap();
636 $c.end_scope($scope).unwrap();
637 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
638 }};
639
640 (@section_terminal $c:ident $section_scope:ident $scope:ident; { $($inner:tt)+ } $($rest:tt)*) => {{
642 $crate::eure!(@stmt $c; $($inner)+);
643 $c.end_scope($scope).unwrap();
644 $crate::eure!(@section_bindings $c $section_scope; $($rest)*);
645 }};
646
647 (@path $c:ident $scope:ident; $seg:ident $($rest:tt)*) => {{
663 $c.navigate($crate::path::PathSegment::Ident(
664 $crate::identifier::Identifier::new_unchecked(stringify!($seg))
665 )).unwrap();
666 $crate::eure!(@after_path $c $scope; $($rest)*);
667 }};
668
669 (@path $c:ident $scope:ident; % $ext:ident $($rest:tt)*) => {{
672 $c.navigate($crate::path::PathSegment::Extension(
673 $crate::identifier::Identifier::new_unchecked(stringify!($ext))
674 )).unwrap();
675 $crate::eure!(@after_path $c $scope; $($rest)*);
676 }};
677
678 (@path $c:ident $scope:ident; % $ext:literal $($rest:tt)*) => {{
681 $c.navigate($crate::path::PathSegment::Extension(
682 $ext.parse().unwrap()
683 )).unwrap();
684 $crate::eure!(@after_path $c $scope; $($rest)*);
685 }};
686
687 (@path $c:ident $scope:ident; # $idx:literal $($rest:tt)*) => {{
689 $c.navigate($crate::path::PathSegment::TupleIndex($idx)).unwrap();
690 $crate::eure!(@after_path $c $scope; $($rest)*);
691 }};
692
693 (@path $c:ident $scope:ident; ($($tuple:tt)*) $($rest:tt)*) => {{
696 let key = $crate::eure!(@build_tuple_key; $($tuple)*);
697 $c.navigate($crate::path::PathSegment::Value(key)).unwrap();
698 $crate::eure!(@after_path $c $scope; $($rest)*);
699 }};
700
701 (@path $c:ident $scope:ident; $key:literal $($rest:tt)*) => {{
704 $c.navigate($crate::path::PathSegment::Value($key.into())).unwrap();
705 $crate::eure!(@after_path $c $scope; $($rest)*);
706 }};
707
708 (@build_tuple_key;) => {{
717 $crate::value::ObjectKey::Tuple($crate::value::Tuple(Default::default()))
718 }};
719
720 (@build_tuple_key; $($item:expr),+ $(,)?) => {{
722 $crate::value::ObjectKey::Tuple($crate::value::Tuple::from_iter(
723 [$(<_ as Into<$crate::value::ObjectKey>>::into($item)),+]
724 ))
725 }};
726
727 (@after_path $c:ident $scope:ident; [$($arr:tt)*] $($rest:tt)*) => {{
736 $crate::eure!(@array_marker $c $scope [$($arr)*]; $($rest)*);
737 }};
738
739 (@after_path $c:ident $scope:ident; $($rest:tt)*) => {{
741 $crate::eure!(@terminal $c $scope; $($rest)*);
742 }};
743
744 (@array_marker $c:ident $scope:ident []; $($rest:tt)*) => {{
754 $c.navigate($crate::path::PathSegment::ArrayIndex(None)).unwrap();
755 $crate::eure!(@terminal $c $scope; $($rest)*);
756 }};
757
758 (@array_marker $c:ident $scope:ident [$idx:literal]; $($rest:tt)*) => {{
760 $c.navigate($crate::path::PathSegment::ArrayIndex(Some($idx))).unwrap();
761 $crate::eure!(@terminal $c $scope; $($rest)*);
762 }};
763
764 (@terminal $c:ident $scope:ident; . $($rest:tt)+) => {{
782 $crate::eure!(@path $c $scope; $($rest)+);
783 }};
784
785 (@terminal $c:ident $scope:ident; = ! $($rest:tt)*) => {{
787 $c.end_scope($scope).unwrap();
789 $crate::eure!(@stmt $c; $($rest)*);
790 }};
791
792 (@terminal $c:ident $scope:ident; = - $v:literal $($rest:tt)*) => {{
794 $c.bind_from(-$v).unwrap();
795 $c.end_scope($scope).unwrap();
796 $crate::eure!(@stmt $c; $($rest)*);
797 }};
798
799 (@terminal $c:ident $scope:ident; = @ code ($content:literal) $($rest:tt)*) => {{
801 $c.bind_from($crate::text::Text::inline_implicit($content)).unwrap();
802 $c.end_scope($scope).unwrap();
803 $crate::eure!(@stmt $c; $($rest)*);
804 }};
805
806 (@terminal $c:ident $scope:ident; = @ code ($lang:literal, $content:literal) $($rest:tt)*) => {{
808 $c.bind_from($crate::text::Text::inline($content, $lang)).unwrap();
809 $c.end_scope($scope).unwrap();
810 $crate::eure!(@stmt $c; $($rest)*);
811 }};
812
813 (@terminal $c:ident $scope:ident; = @ block ($content:literal) $($rest:tt)*) => {{
815 $c.bind_from($crate::text::Text::block_implicit($content)).unwrap();
816 $c.end_scope($scope).unwrap();
817 $crate::eure!(@stmt $c; $($rest)*);
818 }};
819
820 (@terminal $c:ident $scope:ident; = @ block ($lang:literal, $content:literal) $($rest:tt)*) => {{
822 $c.bind_from($crate::text::Text::block($content, $lang)).unwrap();
823 $c.end_scope($scope).unwrap();
824 $crate::eure!(@stmt $c; $($rest)*);
825 }};
826
827 (@terminal $c:ident $scope:ident; = [] $($rest:tt)*) => {{
829 $c.bind_empty_array().unwrap();
830 $c.end_scope($scope).unwrap();
831 $crate::eure!(@stmt $c; $($rest)*);
832 }};
833
834 (@terminal $c:ident $scope:ident; = [$($items:tt)+] $($rest:tt)*) => {{
836 $c.bind_empty_array().unwrap();
837 $crate::eure!(@array_items $c; $($items)+);
838 $c.end_scope($scope).unwrap();
839 $crate::eure!(@stmt $c; $($rest)*);
840 }};
841
842 (@terminal $c:ident $scope:ident; = () $($rest:tt)*) => {{
844 $c.bind_empty_tuple().unwrap();
845 $c.end_scope($scope).unwrap();
846 $crate::eure!(@stmt $c; $($rest)*);
847 }};
848
849 (@terminal $c:ident $scope:ident; = ($($items:tt)+) $($rest:tt)*) => {{
851 $c.bind_empty_tuple().unwrap();
852 $crate::eure!(@tuple_items $c 0; $($items)+);
853 $c.end_scope($scope).unwrap();
854 $crate::eure!(@stmt $c; $($rest)*);
855 }};
856
857 (@terminal $c:ident $scope:ident; = { $key:tt => $($inner:tt)+ } $($rest:tt)*) => {{
859 $c.bind_empty_map().unwrap();
860 $crate::eure!(@object_items $c; $key => $($inner)+);
861 $c.end_scope($scope).unwrap();
862 $crate::eure!(@stmt $c; $($rest)*);
863 }};
864
865 (@terminal $c:ident $scope:ident; = $v:tt $($rest:tt)*) => {{
867 $c.bind_from($crate::eure!(@value_tt $v)).unwrap();
868 $c.end_scope($scope).unwrap();
869 $crate::eure!(@stmt $c; $($rest)*);
870 }};
871
872 (@terminal $c:ident $scope:ident; {} $($rest:tt)*) => {{
874 $c.bind_empty_map().unwrap();
875 $c.end_scope($scope).unwrap();
876 $crate::eure!(@stmt $c; $($rest)*);
877 }};
878
879 (@terminal $c:ident $scope:ident; { $($inner:tt)+ } $($rest:tt)*) => {{
881 $crate::eure!(@stmt $c; $($inner)+);
882 $c.end_scope($scope).unwrap();
883 $crate::eure!(@stmt $c; $($rest)*);
884 }};
885}
886
887#[cfg(test)]
888mod tests {
889 use crate::document::EureDocument;
890 use alloc::vec;
891
892 #[test]
893 fn test_eure_empty() {
894 let doc = eure!({});
895 assert_eq!(doc, EureDocument::new_empty());
896 }
897
898 #[test]
899 fn test_eure_simple_assignment() {
900 let doc = eure!({ name = "Alice" });
901
902 let root_id = doc.get_root_id();
904 let root = doc.node(root_id);
905 let name_node_id = root.as_map().unwrap().get_node_id(&"name".into()).unwrap();
906 let name_node = doc.node(name_node_id);
907 let prim = name_node.as_primitive().unwrap();
908 assert_eq!(prim.as_str(), Some("Alice"));
909 }
910
911 #[test]
912 fn test_eure_nested_path() {
913 let doc = eure!({
914 user.name = "Bob"
915 user.age = 30
916 });
917
918 let root_id = doc.get_root_id();
920 let root = doc.node(root_id);
921 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
922 let user = doc.node(user_id);
923 let name_id = user.as_map().unwrap().get_node_id(&"name".into()).unwrap();
924 let name = doc.node(name_id);
925 assert_eq!(name.as_primitive().unwrap().as_str(), Some("Bob"));
926
927 let age_id = user.as_map().unwrap().get_node_id(&"age".into()).unwrap();
928 let age = doc.node(age_id);
929 assert!(matches!(
930 age.as_primitive(),
931 Some(crate::value::PrimitiveValue::Integer(_))
932 ));
933 }
934
935 #[test]
936 fn test_eure_block() {
937 let doc = eure!({
938 user {
939 name = "Charlie"
940 active = true
941 }
942 });
943
944 let root_id = doc.get_root_id();
945 let root = doc.node(root_id);
946 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
947 let user = doc.node(user_id);
948 let name_id = user.as_map().unwrap().get_node_id(&"name".into()).unwrap();
949 let name = doc.node(name_id);
950 assert_eq!(name.as_primitive().unwrap().as_str(), Some("Charlie"));
951 }
952
953 #[test]
954 fn test_eure_extension() {
955 let doc = eure!({
956 field.%variant = @code("text")
957 });
958
959 let root_id = doc.get_root_id();
960 let root = doc.node(root_id);
961 let field_id = root.as_map().unwrap().get_node_id(&"field".into()).unwrap();
962 let field = doc.node(field_id);
963
964 let variant_id = field.get_extension(&"variant".parse().unwrap()).unwrap();
966 let variant = doc.node(variant_id);
967 let text = variant.as_primitive().unwrap().as_text().unwrap();
968 assert_eq!(text.as_str(), "text");
969 }
970
971 #[test]
972 fn test_eure_extension_with_child() {
973 let doc = eure!({
975 field.%variant.name = @code("text")
976 field.%variant.min_length = 3
977 });
978
979 let root_id = doc.get_root_id();
980 let root = doc.node(root_id);
981 let field_id = root.as_map().unwrap().get_node_id(&"field".into()).unwrap();
982 let field = doc.node(field_id);
983
984 let variant_id = field.get_extension(&"variant".parse().unwrap()).unwrap();
986 let variant = doc.node(variant_id);
987
988 let name_id = variant
990 .as_map()
991 .unwrap()
992 .get_node_id(&"name".into())
993 .unwrap();
994 let name = doc.node(name_id);
995 let text = name.as_primitive().unwrap().as_text().unwrap();
996 assert_eq!(text.as_str(), "text");
997
998 let min_length_id = variant
999 .as_map()
1000 .unwrap()
1001 .get_node_id(&"min_length".into())
1002 .unwrap();
1003 let min_length = doc.node(min_length_id);
1004 assert!(matches!(
1005 min_length.as_primitive(),
1006 Some(crate::value::PrimitiveValue::Integer(_))
1007 ));
1008 }
1009
1010 #[test]
1011 fn test_eure_array() {
1012 let doc = eure!({ tags = ["a", "b", "c"] });
1013
1014 let root_id = doc.get_root_id();
1015 let root = doc.node(root_id);
1016 let tags_id = root.as_map().unwrap().get_node_id(&"tags".into()).unwrap();
1017 let tags = doc.node(tags_id);
1018 let array = tags.as_array().unwrap();
1019 assert_eq!(array.len(), 3);
1020 }
1021
1022 #[test]
1023 fn test_eure_tuple() {
1024 let doc = eure!({ point = (1.5, 2.5) });
1025
1026 let root_id = doc.get_root_id();
1027 let root = doc.node(root_id);
1028 let point_id = root.as_map().unwrap().get_node_id(&"point".into()).unwrap();
1029 let point = doc.node(point_id);
1030 let tuple = point.as_tuple().unwrap();
1031 assert_eq!(tuple.len(), 2);
1032 }
1033
1034 #[test]
1035 fn test_eure_multiple_assignments() {
1036 let doc = eure!({
1037 a = 1
1038 b = 2
1039 c = 3
1040 });
1041
1042 let root_id = doc.get_root_id();
1043 let root = doc.node(root_id);
1044 let map = root.as_map().unwrap();
1045 assert_eq!(map.len(), 3);
1046 }
1047
1048 #[test]
1049 fn test_eure_complex() {
1050 let doc = eure!({
1052 schema {
1053 field.%variant = @code("text")
1054 field.min_length = 3
1055 field.max_length = 20
1056 }
1057 tags = ["required"]
1058 });
1059
1060 let root_id = doc.get_root_id();
1061 let root = doc.node(root_id);
1062
1063 let schema_id = root
1065 .as_map()
1066 .unwrap()
1067 .get_node_id(&"schema".into())
1068 .unwrap();
1069 let schema = doc.node(schema_id);
1070
1071 let field_id = schema
1073 .as_map()
1074 .unwrap()
1075 .get_node_id(&"field".into())
1076 .unwrap();
1077 let field = doc.node(field_id);
1078 assert!(field.get_extension(&"variant".parse().unwrap()).is_some());
1079
1080 let tags_id = root.as_map().unwrap().get_node_id(&"tags".into()).unwrap();
1082 let tags = doc.node(tags_id);
1083 assert_eq!(tags.as_array().unwrap().len(), 1);
1084 }
1085
1086 #[test]
1087 fn test_eure_array_push() {
1088 let doc = eure!({
1090 items[] = 1
1091 items[] = 2
1092 items[] = 3
1093 });
1094
1095 let root_id = doc.get_root_id();
1096 let root = doc.node(root_id);
1097 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1098 let items = doc.node(items_id);
1099 let array = items.as_array().unwrap();
1100 assert_eq!(array.len(), 3);
1101 }
1102
1103 #[test]
1104 fn test_eure_array_push_with_child() {
1105 let doc = eure!({
1107 items[].name = "first"
1108 items[].name = "second"
1109 });
1110
1111 let root_id = doc.get_root_id();
1112 let root = doc.node(root_id);
1113 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1114 let items = doc.node(items_id);
1115 let array = items.as_array().unwrap();
1116 assert_eq!(array.len(), 2);
1117
1118 let first_id = array.get(0).unwrap();
1120 let first = doc.node(first_id);
1121 let name_id = first.as_map().unwrap().get_node_id(&"name".into()).unwrap();
1122 let name = doc.node(name_id);
1123 assert_eq!(name.as_primitive().unwrap().as_str(), Some("first"));
1124 }
1125
1126 #[test]
1127 fn test_eure_tuple_index() {
1128 let doc = eure!({
1130 point.#0 = 1.5
1131 point.#1 = 2.5
1132 });
1133
1134 let root_id = doc.get_root_id();
1135 let root = doc.node(root_id);
1136 let point_id = root.as_map().unwrap().get_node_id(&"point".into()).unwrap();
1137 let point = doc.node(point_id);
1138 let tuple = point.as_tuple().unwrap();
1139 assert_eq!(tuple.len(), 2);
1140 }
1141
1142 #[test]
1143 fn test_eure_mixed_path_extension_array() {
1144 let doc = eure!({
1146 field.%items[].name = "item1"
1147 field.%items[].name = "item2"
1148 });
1149
1150 let root_id = doc.get_root_id();
1151 let root = doc.node(root_id);
1152 let field_id = root.as_map().unwrap().get_node_id(&"field".into()).unwrap();
1153 let field = doc.node(field_id);
1154
1155 let items_id = field.get_extension(&"items".parse().unwrap()).unwrap();
1157 let items = doc.node(items_id);
1158 let array = items.as_array().unwrap();
1159 assert_eq!(array.len(), 2);
1160 }
1161
1162 #[test]
1163 fn test_eure_mixed_path_array_extension() {
1164 let doc = eure!({
1166 items[].%variant = @code("text")
1167 items[].%variant = @code("number")
1168 });
1169
1170 let root_id = doc.get_root_id();
1171 let root = doc.node(root_id);
1172 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1173 let items = doc.node(items_id);
1174 let array = items.as_array().unwrap();
1175 assert_eq!(array.len(), 2);
1176
1177 let first_id = array.get(0).unwrap();
1179 let first = doc.node(first_id);
1180 let variant_id = first.get_extension(&"variant".parse().unwrap()).unwrap();
1181 let variant = doc.node(variant_id);
1182 assert_eq!(
1183 variant.as_primitive().unwrap().as_text().unwrap().as_str(),
1184 "text"
1185 );
1186 }
1187
1188 #[test]
1189 fn test_eure_tuple_key() {
1190 use crate::value::{ObjectKey, Tuple};
1191
1192 let doc = eure!({
1194 map.(1, "key") = "value1"
1195 map.(2, "key") = "value2"
1196 });
1197
1198 let root_id = doc.get_root_id();
1199 let root = doc.node(root_id);
1200 let map_id = root.as_map().unwrap().get_node_id(&"map".into()).unwrap();
1201 let map_node = doc.node(map_id);
1202 let map = map_node.as_map().unwrap();
1203 assert_eq!(map.len(), 2);
1204
1205 let tuple_key = ObjectKey::Tuple(Tuple(alloc::vec![1.into(), "key".into()]));
1207 let value_id = map.get_node_id(&tuple_key).unwrap();
1208 let value = doc.node(value_id);
1209 assert_eq!(value.as_primitive().unwrap().as_str(), Some("value1"));
1210 }
1211
1212 #[test]
1213 fn test_eure_tuple_key_with_bool() {
1214 use crate::value::{ObjectKey, Tuple};
1215
1216 let doc = eure!({
1218 map.(true, 1) = "yes"
1219 map.(false, 1) = "no"
1220 });
1221
1222 let root_id = doc.get_root_id();
1223 let root = doc.node(root_id);
1224 let map_id = root.as_map().unwrap().get_node_id(&"map".into()).unwrap();
1225 let map_node = doc.node(map_id);
1226 let map = map_node.as_map().unwrap();
1227 assert_eq!(map.len(), 2);
1228
1229 let tuple_key = ObjectKey::Tuple(Tuple(alloc::vec![true.into(), 1.into()]));
1231 let value_id = map.get_node_id(&tuple_key).unwrap();
1232 let value = doc.node(value_id);
1233 assert_eq!(value.as_primitive().unwrap().as_str(), Some("yes"));
1234 }
1235
1236 #[test]
1237 fn test_eure_tuple_key_with_child() {
1238 use crate::value::{ObjectKey, Tuple};
1239
1240 let doc = eure!({
1242 map.(1, 2).name = "point_a"
1243 map.(1, 2).value = 42
1244 });
1245
1246 let root_id = doc.get_root_id();
1247 let root = doc.node(root_id);
1248 let map_id = root.as_map().unwrap().get_node_id(&"map".into()).unwrap();
1249 let map_node = doc.node(map_id);
1250 let map = map_node.as_map().unwrap();
1251
1252 let tuple_key = ObjectKey::Tuple(Tuple(alloc::vec![1.into(), 2.into()]));
1254 let entry_id = map.get_node_id(&tuple_key).unwrap();
1255 let entry = doc.node(entry_id);
1256 let entry_map = entry.as_map().unwrap();
1257
1258 let name_id = entry_map.get_node_id(&"name".into()).unwrap();
1259 let name = doc.node(name_id);
1260 assert_eq!(name.as_primitive().unwrap().as_str(), Some("point_a"));
1261 }
1262
1263 #[test]
1264 fn test_eure_string_key() {
1265 let doc = eure!({
1267 field."min-length" = 3
1268 field."max-length" = 20
1269 });
1270
1271 let root_id = doc.get_root_id();
1272 let root = doc.node(root_id);
1273 let field_id = root.as_map().unwrap().get_node_id(&"field".into()).unwrap();
1274 let field = doc.node(field_id);
1275 let field_map = field.as_map().unwrap();
1276
1277 let min_id = field_map.get_node_id(&"min-length".into()).unwrap();
1279 let min_node = doc.node(min_id);
1280 assert!(matches!(
1281 min_node.as_primitive(),
1282 Some(crate::value::PrimitiveValue::Integer(_))
1283 ));
1284 }
1285
1286 #[test]
1287 fn test_eure_object_literal() {
1288 let doc = eure!({
1290 variants.click = { "x" => 1.0, "y" => 2.0 }
1291 });
1292
1293 let root_id = doc.get_root_id();
1294 let root = doc.node(root_id);
1295 let variants_id = root
1296 .as_map()
1297 .unwrap()
1298 .get_node_id(&"variants".into())
1299 .unwrap();
1300 let variants = doc.node(variants_id);
1301 let click_id = variants
1302 .as_map()
1303 .unwrap()
1304 .get_node_id(&"click".into())
1305 .unwrap();
1306 let click = doc.node(click_id);
1307 let click_map = click.as_map().unwrap();
1308
1309 assert_eq!(click_map.len(), 2);
1310 assert!(click_map.get(&"x".into()).is_some());
1311 assert!(click_map.get(&"y".into()).is_some());
1312 }
1313
1314 #[test]
1315 fn test_eure_object_literal_with_string() {
1316 let doc = eure!({
1318 schema.variants.success = { "data" => "any" }
1319 });
1320
1321 let root_id = doc.get_root_id();
1322 let root = doc.node(root_id);
1323 let schema_id = root
1324 .as_map()
1325 .unwrap()
1326 .get_node_id(&"schema".into())
1327 .unwrap();
1328 let schema = doc.node(schema_id);
1329 let variants_id = schema
1330 .as_map()
1331 .unwrap()
1332 .get_node_id(&"variants".into())
1333 .unwrap();
1334 let variants = doc.node(variants_id);
1335 let success_id = variants
1336 .as_map()
1337 .unwrap()
1338 .get_node_id(&"success".into())
1339 .unwrap();
1340 let success = doc.node(success_id);
1341 let success_map = success.as_map().unwrap();
1342
1343 let data_id = success_map.get_node_id(&"data".into()).unwrap();
1344 let data = doc.node(data_id);
1345 assert_eq!(data.as_primitive().unwrap().as_str(), Some("any"));
1346 }
1347
1348 #[test]
1349 fn test_eure_value_binding() {
1350 let doc = eure!({
1352 = @code("hello")
1353 });
1354
1355 let root_id = doc.get_root_id();
1356 let root = doc.node(root_id);
1357 let text = root.as_primitive().unwrap().as_text().unwrap();
1358 assert_eq!(text.as_str(), "hello");
1359 }
1360
1361 #[test]
1362 fn test_eure_value_binding_with_extension() {
1363 let doc = eure!({
1365 = @code("any")
1366 %variant = "literal"
1367 });
1368
1369 let root_id = doc.get_root_id();
1370 let root = doc.node(root_id);
1371
1372 let text = root.as_primitive().unwrap().as_text().unwrap();
1374 assert_eq!(text.as_str(), "any");
1375
1376 let variant_id = root.get_extension(&"variant".parse().unwrap()).unwrap();
1378 let variant = doc.node(variant_id);
1379 assert_eq!(variant.as_primitive().unwrap().as_str(), Some("literal"));
1380 }
1381
1382 #[test]
1383 fn test_eure_empty_block() {
1384 let doc = eure!({ config {} });
1386
1387 let root_id = doc.get_root_id();
1388 let root = doc.node(root_id);
1389 let config_id = root
1390 .as_map()
1391 .unwrap()
1392 .get_node_id(&"config".into())
1393 .unwrap();
1394 let config = doc.node(config_id);
1395
1396 let map = config
1398 .as_map()
1399 .expect("Empty block should create an empty map");
1400 assert!(map.is_empty());
1401 }
1402
1403 #[test]
1408 fn test_eure_null_literal() {
1409 let doc = eure!({ optional = null });
1411
1412 let root_id = doc.get_root_id();
1413 let root = doc.node(root_id);
1414 let opt_id = root
1415 .as_map()
1416 .unwrap()
1417 .get_node_id(&"optional".into())
1418 .unwrap();
1419 let opt = doc.node(opt_id);
1420 assert!(matches!(
1421 opt.as_primitive(),
1422 Some(crate::value::PrimitiveValue::Null)
1423 ));
1424 }
1425
1426 #[test]
1427 fn test_eure_null_root() {
1428 let doc = eure!({
1430 = null
1431 });
1432
1433 let root_id = doc.get_root_id();
1434 let root = doc.node(root_id);
1435 assert!(matches!(
1436 root.as_primitive(),
1437 Some(crate::value::PrimitiveValue::Null)
1438 ));
1439 }
1440
1441 #[test]
1442 fn test_eure_hole_literal() {
1443 use crate::document::node::NodeValue;
1444
1445 let doc = eure!({
1447 placeholder = !
1448 });
1449
1450 let root_id = doc.get_root_id();
1451 let root = doc.node(root_id);
1452 let placeholder_id = root
1453 .as_map()
1454 .unwrap()
1455 .get_node_id(&"placeholder".into())
1456 .unwrap();
1457 let placeholder = doc.node(placeholder_id);
1458 assert_eq!(placeholder.content, NodeValue::Hole(None));
1459 }
1460
1461 #[test]
1462 fn test_eure_hole_root() {
1463 use crate::document::node::NodeValue;
1464
1465 let doc = eure!({
1468 = !
1469 });
1470
1471 let root_id = doc.get_root_id();
1472 let root = doc.node(root_id);
1473 assert!(matches!(root.content, NodeValue::Map(_)));
1475 }
1476
1477 #[test]
1478 fn test_eure_code_inline_implicit() {
1479 let doc = eure!({
1481 snippet = @code("let x = 1")
1482 });
1483
1484 let root_id = doc.get_root_id();
1485 let root = doc.node(root_id);
1486 let snippet_id = root
1487 .as_map()
1488 .unwrap()
1489 .get_node_id(&"snippet".into())
1490 .unwrap();
1491 let snippet = doc.node(snippet_id);
1492 let text = snippet.as_primitive().unwrap().as_text().unwrap();
1493 assert_eq!(text.as_str(), "let x = 1");
1494 assert!(text.language.is_implicit());
1495 }
1496
1497 #[test]
1498 fn test_eure_code_inline_with_language() {
1499 let doc = eure!({
1501 query = @code("sql", "SELECT * FROM users")
1502 });
1503
1504 let root_id = doc.get_root_id();
1505 let root = doc.node(root_id);
1506 let query_id = root.as_map().unwrap().get_node_id(&"query".into()).unwrap();
1507 let query = doc.node(query_id);
1508 let text = query.as_primitive().unwrap().as_text().unwrap();
1509 assert_eq!(text.as_str(), "SELECT * FROM users");
1510 assert_eq!(text.language.as_str(), Some("sql"));
1511 }
1512
1513 #[test]
1514 fn test_eure_block_implicit() {
1515 let doc = eure!({
1517 script = @block("fn main() {}")
1518 });
1519
1520 let root_id = doc.get_root_id();
1521 let root = doc.node(root_id);
1522 let script_id = root
1523 .as_map()
1524 .unwrap()
1525 .get_node_id(&"script".into())
1526 .unwrap();
1527 let script = doc.node(script_id);
1528 let text = script.as_primitive().unwrap().as_text().unwrap();
1529 assert_eq!(text.as_str(), "fn main() {}\n");
1531 assert!(text.language.is_implicit());
1532 }
1533
1534 #[test]
1535 fn test_eure_block_with_language() {
1536 let doc = eure!({
1538 code = @block("rust", "fn main() {\n println!(\"Hello\");\n}")
1539 });
1540
1541 let root_id = doc.get_root_id();
1542 let root = doc.node(root_id);
1543 let code_id = root.as_map().unwrap().get_node_id(&"code".into()).unwrap();
1544 let code = doc.node(code_id);
1545 let text = code.as_primitive().unwrap().as_text().unwrap();
1546 assert_eq!(text.language.as_str(), Some("rust"));
1547 assert!(text.as_str().contains("println!"));
1548 }
1549
1550 #[test]
1551 fn test_eure_code_at_root() {
1552 let doc = eure!({
1554 = @code("hello")
1555 });
1556
1557 let root_id = doc.get_root_id();
1558 let root = doc.node(root_id);
1559 let text = root.as_primitive().unwrap().as_text().unwrap();
1560 assert_eq!(text.as_str(), "hello");
1561 }
1562
1563 #[test]
1564 fn test_eure_code_with_language_at_root() {
1565 let doc = eure!({
1567 = @code("sql", "SELECT 1")
1568 });
1569
1570 let root_id = doc.get_root_id();
1571 let root = doc.node(root_id);
1572 let text = root.as_primitive().unwrap().as_text().unwrap();
1573 assert_eq!(text.as_str(), "SELECT 1");
1574 assert_eq!(text.language.as_str(), Some("sql"));
1575 }
1576
1577 #[test]
1578 fn test_eure_block_at_root() {
1579 let doc = eure!({
1581 = @block("fn main() {}")
1582 });
1583
1584 let root_id = doc.get_root_id();
1585 let root = doc.node(root_id);
1586 let text = root.as_primitive().unwrap().as_text().unwrap();
1587 assert_eq!(text.as_str(), "fn main() {}\n");
1588 assert!(text.language.is_implicit());
1589 }
1590
1591 #[test]
1592 fn test_eure_block_with_language_at_root() {
1593 let doc = eure!({
1595 = @block("rust", "fn main() {}")
1596 });
1597
1598 let root_id = doc.get_root_id();
1599 let root = doc.node(root_id);
1600 let text = root.as_primitive().unwrap().as_text().unwrap();
1601 assert_eq!(text.as_str(), "fn main() {}\n");
1602 assert_eq!(text.language.as_str(), Some("rust"));
1603 }
1604
1605 #[test]
1610 fn test_eure_array_specific_index() {
1611 let doc = eure!({
1613 items[0] = "first"
1614 items[1] = "second"
1615 });
1616
1617 let root_id = doc.get_root_id();
1618 let root = doc.node(root_id);
1619 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1620 let items = doc.node(items_id);
1621 let array = items.as_array().unwrap();
1622 assert_eq!(array.len(), 2);
1623
1624 let first_id = array.get(0).unwrap();
1626 let first = doc.node(first_id);
1627 assert_eq!(first.as_primitive().unwrap().as_str(), Some("first"));
1628
1629 let second_id = array.get(1).unwrap();
1630 let second = doc.node(second_id);
1631 assert_eq!(second.as_primitive().unwrap().as_str(), Some("second"));
1632 }
1633
1634 #[test]
1635 fn test_eure_array_index_with_child() {
1636 let doc = eure!({
1638 items[0].name = "first"
1639 items[0].value = 1
1640 items[1].name = "second"
1641 });
1642
1643 let root_id = doc.get_root_id();
1644 let root = doc.node(root_id);
1645 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1646 let items = doc.node(items_id);
1647 let array = items.as_array().unwrap();
1648 assert_eq!(array.len(), 2);
1649
1650 let first_id = array.get(0).unwrap();
1652 let first = doc.node(first_id);
1653 let name_id = first.as_map().unwrap().get_node_id(&"name".into()).unwrap();
1654 let name = doc.node(name_id);
1655 assert_eq!(name.as_primitive().unwrap().as_str(), Some("first"));
1656 }
1657
1658 #[test]
1659 fn test_eure_nested_empty_blocks() {
1660 let doc = eure!({
1662 a {
1663 b {
1664 c {}
1665 }
1666 }
1667 });
1668
1669 let root_id = doc.get_root_id();
1670 let root = doc.node(root_id);
1671
1672 let a_id = root.as_map().unwrap().get_node_id(&"a".into()).unwrap();
1673 let a = doc.node(a_id);
1674
1675 let b_id = a.as_map().unwrap().get_node_id(&"b".into()).unwrap();
1676 let b = doc.node(b_id);
1677
1678 let c_id = b.as_map().unwrap().get_node_id(&"c".into()).unwrap();
1679 let c = doc.node(c_id);
1680
1681 let map = c.as_map().expect("c should be an empty map");
1683 assert!(map.is_empty());
1684 }
1685
1686 #[test]
1687 fn test_eure_multiple_extensions() {
1688 let doc = eure!({
1690 field.%variant = @code("text")
1691 field.%"variant-repr" = "internal"
1692 field.%schema = "custom"
1693 });
1694
1695 let root_id = doc.get_root_id();
1696 let root = doc.node(root_id);
1697 let field_id = root.as_map().unwrap().get_node_id(&"field".into()).unwrap();
1698 let field = doc.node(field_id);
1699
1700 assert!(field.get_extension(&"variant".parse().unwrap()).is_some());
1702 assert!(
1703 field
1704 .get_extension(&"variant-repr".parse().unwrap())
1705 .is_some()
1706 );
1707 assert!(field.get_extension(&"schema".parse().unwrap()).is_some());
1708 }
1709
1710 #[test]
1711 fn test_eure_extension_on_array_element() {
1712 let doc = eure!({
1715 items[0].%variant = @code("text")
1716 items[0].value = "first"
1717 items[1].%variant = @code("number")
1718 items[1].value = 42
1719 });
1720
1721 let root_id = doc.get_root_id();
1722 let root = doc.node(root_id);
1723 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1724 let items = doc.node(items_id);
1725 let array = items.as_array().unwrap();
1726 assert_eq!(array.len(), 2);
1727
1728 let first_id = array.get(0).unwrap();
1730 let first = doc.node(first_id);
1731 let variant_id = first.get_extension(&"variant".parse().unwrap()).unwrap();
1732 let variant = doc.node(variant_id);
1733 assert_eq!(
1734 variant.as_primitive().unwrap().as_text().unwrap().as_str(),
1735 "text"
1736 );
1737 let value_id = first
1738 .as_map()
1739 .unwrap()
1740 .get_node_id(&"value".into())
1741 .unwrap();
1742 let value = doc.node(value_id);
1743 assert_eq!(value.as_primitive().unwrap().as_str(), Some("first"));
1744
1745 let second_id = array.get(1).unwrap();
1747 let second = doc.node(second_id);
1748 let variant_id = second.get_extension(&"variant".parse().unwrap()).unwrap();
1749 let variant = doc.node(variant_id);
1750 assert_eq!(
1751 variant.as_primitive().unwrap().as_text().unwrap().as_str(),
1752 "number"
1753 );
1754 }
1755
1756 #[test]
1757 fn test_eure_deep_nesting() {
1758 let doc = eure!({ a.b.c.d.e.f = "deep" });
1760
1761 let root_id = doc.get_root_id();
1762 let root = doc.node(root_id);
1763
1764 let a_id = root.as_map().unwrap().get_node_id(&"a".into()).unwrap();
1765 let a = doc.node(a_id);
1766 let b_id = a.as_map().unwrap().get_node_id(&"b".into()).unwrap();
1767 let b = doc.node(b_id);
1768 let c_id = b.as_map().unwrap().get_node_id(&"c".into()).unwrap();
1769 let c = doc.node(c_id);
1770 let d_id = c.as_map().unwrap().get_node_id(&"d".into()).unwrap();
1771 let d = doc.node(d_id);
1772 let e_id = d.as_map().unwrap().get_node_id(&"e".into()).unwrap();
1773 let e = doc.node(e_id);
1774 let f_id = e.as_map().unwrap().get_node_id(&"f".into()).unwrap();
1775 let f = doc.node(f_id);
1776
1777 assert_eq!(f.as_primitive().unwrap().as_str(), Some("deep"));
1778 }
1779
1780 #[test]
1781 fn test_eure_empty_array_literal() {
1782 let doc = eure!({ items = [] });
1784
1785 let root_id = doc.get_root_id();
1786 let root = doc.node(root_id);
1787 let items_id = root.as_map().unwrap().get_node_id(&"items".into()).unwrap();
1788 let items = doc.node(items_id);
1789 let array = items.as_array().unwrap();
1790 assert!(array.is_empty());
1791 }
1792
1793 #[test]
1794 fn test_eure_empty_tuple_literal() {
1795 let doc = eure!({ point = () });
1797
1798 let root_id = doc.get_root_id();
1799 let root = doc.node(root_id);
1800 let point_id = root.as_map().unwrap().get_node_id(&"point".into()).unwrap();
1801 let point = doc.node(point_id);
1802 let tuple = point.as_tuple().unwrap();
1803 assert!(tuple.is_empty());
1804 }
1805
1806 #[test]
1807 fn test_eure_empty_map_literal() {
1808 let doc = eure!({ data {} });
1811
1812 let root_id = doc.get_root_id();
1813 let root = doc.node(root_id);
1814 let data_id = root.as_map().unwrap().get_node_id(&"data".into()).unwrap();
1815 let data = doc.node(data_id);
1816 let map = data.as_map().unwrap();
1817 assert!(map.is_empty());
1818 }
1819
1820 #[test]
1821 fn test_eure_mixed_null_and_values() {
1822 let doc = eure!({
1824 name = "Alice"
1825 age = null
1826 active = true
1827 score = null
1828 });
1829
1830 let root_id = doc.get_root_id();
1831 let root = doc.node(root_id);
1832 let map = root.as_map().unwrap();
1833 assert_eq!(map.len(), 4);
1834
1835 let age_id = map.get_node_id(&"age".into()).unwrap();
1836 let age = doc.node(age_id);
1837 assert!(matches!(
1838 age.as_primitive(),
1839 Some(crate::value::PrimitiveValue::Null)
1840 ));
1841 }
1842
1843 #[test]
1848 fn test_eure_section_basic() {
1849 let doc = eure!({
1851 @user
1852 name = "Alice"
1853 age = 30
1854 });
1855
1856 let root_id = doc.get_root_id();
1857 let root = doc.node(root_id);
1858 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
1859 let user = doc.node(user_id);
1860 let name_id = user.as_map().unwrap().get_node_id(&"name".into()).unwrap();
1861 let name = doc.node(name_id);
1862 assert_eq!(name.as_primitive().unwrap().as_str(), Some("Alice"));
1863 }
1864
1865 #[test]
1866 fn test_eure_section_multiple() {
1867 let doc = eure!({
1869 @user
1870 name = "Alice"
1871
1872 @settings
1873 theme = "dark"
1874 });
1875
1876 let root_id = doc.get_root_id();
1877 let root = doc.node(root_id);
1878
1879 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
1880 let user = doc.node(user_id);
1881 assert!(user.as_map().unwrap().get_node_id(&"name".into()).is_some());
1882
1883 let settings_id = root
1884 .as_map()
1885 .unwrap()
1886 .get_node_id(&"settings".into())
1887 .unwrap();
1888 let settings = doc.node(settings_id);
1889 assert!(
1890 settings
1891 .as_map()
1892 .unwrap()
1893 .get_node_id(&"theme".into())
1894 .is_some()
1895 );
1896 }
1897
1898 #[test]
1899 fn test_eure_section_dotted_path() {
1900 let doc = eure!({
1902 @user.profile
1903 name = "Alice"
1904 });
1905
1906 let root_id = doc.get_root_id();
1907 let root = doc.node(root_id);
1908 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
1909 let user = doc.node(user_id);
1910 let profile_id = user
1911 .as_map()
1912 .unwrap()
1913 .get_node_id(&"profile".into())
1914 .unwrap();
1915 let profile = doc.node(profile_id);
1916 assert!(
1917 profile
1918 .as_map()
1919 .unwrap()
1920 .get_node_id(&"name".into())
1921 .is_some()
1922 );
1923 }
1924
1925 #[test]
1926 fn test_eure_section_with_block() {
1927 let doc = eure!({
1929 @user {
1930 name = "Alice"
1931 age = 30
1932 }
1933 });
1934
1935 let root_id = doc.get_root_id();
1936 let root = doc.node(root_id);
1937 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
1938 let user = doc.node(user_id);
1939 assert!(user.as_map().unwrap().get_node_id(&"name".into()).is_some());
1940 assert!(user.as_map().unwrap().get_node_id(&"age".into()).is_some());
1941 }
1942
1943 #[test]
1944 fn test_eure_section_block_with_nested() {
1945 let doc = eure!({
1947 @config {
1948 server {
1949 host = "localhost"
1950 port = 8080
1951 }
1952 debug = true
1953 }
1954 });
1955
1956 let root_id = doc.get_root_id();
1957 let root = doc.node(root_id);
1958 let config_id = root
1959 .as_map()
1960 .unwrap()
1961 .get_node_id(&"config".into())
1962 .unwrap();
1963 let config = doc.node(config_id);
1964 assert!(
1965 config
1966 .as_map()
1967 .unwrap()
1968 .get_node_id(&"server".into())
1969 .is_some()
1970 );
1971 assert!(
1972 config
1973 .as_map()
1974 .unwrap()
1975 .get_node_id(&"debug".into())
1976 .is_some()
1977 );
1978
1979 let server_id = config
1980 .as_map()
1981 .unwrap()
1982 .get_node_id(&"server".into())
1983 .unwrap();
1984 let server = doc.node(server_id);
1985 assert!(
1986 server
1987 .as_map()
1988 .unwrap()
1989 .get_node_id(&"host".into())
1990 .is_some()
1991 );
1992 assert!(
1993 server
1994 .as_map()
1995 .unwrap()
1996 .get_node_id(&"port".into())
1997 .is_some()
1998 );
1999 }
2000
2001 #[test]
2002 fn test_eure_section_block_multiple() {
2003 let doc = eure!({
2005 @user {
2006 name = "Alice"
2007 }
2008 @settings {
2009 theme = "dark"
2010 }
2011 });
2012
2013 let root_id = doc.get_root_id();
2014 let root = doc.node(root_id);
2015 assert!(root.as_map().unwrap().get_node_id(&"user".into()).is_some());
2016 assert!(
2017 root.as_map()
2018 .unwrap()
2019 .get_node_id(&"settings".into())
2020 .is_some()
2021 );
2022 }
2023
2024 #[test]
2025 fn test_eure_section_block_dotted_path() {
2026 let doc = eure!({
2028 @server.config {
2029 host = "localhost"
2030 port = 8080
2031 }
2032 });
2033
2034 let root_id = doc.get_root_id();
2035 let root = doc.node(root_id);
2036 let server_id = root
2037 .as_map()
2038 .unwrap()
2039 .get_node_id(&"server".into())
2040 .unwrap();
2041 let server = doc.node(server_id);
2042 let config_id = server
2043 .as_map()
2044 .unwrap()
2045 .get_node_id(&"config".into())
2046 .unwrap();
2047 let config = doc.node(config_id);
2048 assert!(
2049 config
2050 .as_map()
2051 .unwrap()
2052 .get_node_id(&"host".into())
2053 .is_some()
2054 );
2055 assert!(
2056 config
2057 .as_map()
2058 .unwrap()
2059 .get_node_id(&"port".into())
2060 .is_some()
2061 );
2062 }
2063
2064 #[test]
2065 fn test_eure_section_block_empty() {
2066 let doc = eure!({
2068 @empty {}
2069 });
2070
2071 let root_id = doc.get_root_id();
2072 let root = doc.node(root_id);
2073 let empty_id = root.as_map().unwrap().get_node_id(&"empty".into()).unwrap();
2074 let empty = doc.node(empty_id);
2075 assert!(empty.as_map().unwrap().is_empty());
2077 }
2078
2079 #[test]
2080 fn test_eure_section_mixed_styles() {
2081 let doc = eure!({
2083 @user {
2084 name = "Alice"
2085 }
2086
2087 @settings
2088 theme = "dark"
2089 debug = true
2090
2091 @logging {
2092 level = "info"
2093 }
2094 });
2095
2096 let root_id = doc.get_root_id();
2097 let root = doc.node(root_id);
2098
2099 let user_id = root.as_map().unwrap().get_node_id(&"user".into()).unwrap();
2101 let user = doc.node(user_id);
2102 assert!(user.as_map().unwrap().get_node_id(&"name".into()).is_some());
2103
2104 let settings_id = root
2106 .as_map()
2107 .unwrap()
2108 .get_node_id(&"settings".into())
2109 .unwrap();
2110 let settings = doc.node(settings_id);
2111 assert!(
2112 settings
2113 .as_map()
2114 .unwrap()
2115 .get_node_id(&"theme".into())
2116 .is_some()
2117 );
2118 assert!(
2119 settings
2120 .as_map()
2121 .unwrap()
2122 .get_node_id(&"debug".into())
2123 .is_some()
2124 );
2125
2126 let logging_id = root
2128 .as_map()
2129 .unwrap()
2130 .get_node_id(&"logging".into())
2131 .unwrap();
2132 let logging = doc.node(logging_id);
2133 assert!(
2134 logging
2135 .as_map()
2136 .unwrap()
2137 .get_node_id(&"level".into())
2138 .is_some()
2139 );
2140 }
2141
2142 #[test]
2143 fn test_eure_section_in_section_block() {
2144 let doc = eure!({
2146 @ settings {
2147 theme = "dark"
2148 @ logging
2149 level = "info"
2150 }
2151 });
2152
2153 let settings = doc
2154 .parse_context(doc.get_root_id())
2155 .parse_record()
2156 .expect("Failed to parse record")
2157 .field_record("settings")
2158 .expect("Failed to parse settings");
2159 let theme = settings
2160 .parse_field::<&str>("theme")
2161 .expect("Failed to parse theme");
2162 let logging = settings
2163 .field_record("logging")
2164 .expect("Failed to parse logging")
2165 .parse_field::<&str>("level")
2166 .expect("Failed to parse level");
2167 settings
2168 .deny_unknown_fields()
2169 .expect("Failed to deny unknown fields");
2170 assert_eq!(theme, "dark");
2171 assert_eq!(logging, "info");
2172 }
2173
2174 #[test]
2175 fn test_eure_variable_text() {
2176 use crate::text::Text;
2178 let code = Text::inline_implicit("fn main() {}");
2179 let doc = eure!({ snippet = code });
2180
2181 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2182 let snippet_ctx = root.field("snippet").unwrap();
2183 let snippet_node = doc.node(snippet_ctx.node_id());
2184 let text = snippet_node.as_primitive().unwrap().as_text().unwrap();
2185 assert_eq!(text.as_str(), "fn main() {}");
2186 }
2187
2188 #[test]
2189 fn test_eure_variable_in_array() {
2190 use alloc::vec::Vec;
2192 let first = "one";
2193 let second = "two";
2194 let third = "three";
2195 let doc = eure!({ items = [first, second, third] });
2196
2197 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2198 let items = root.parse_field::<Vec<&str>>("items").unwrap();
2199 assert_eq!(items, vec!["one", "two", "three"]);
2200 }
2201
2202 #[test]
2203 fn test_eure_variable_in_tuple() {
2204 let x = 1.5;
2206 let y = 2.5;
2207 let doc = eure!({ point = (x, y) });
2208
2209 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2210 let point = root.parse_field::<(f64, f64)>("point").unwrap();
2211 assert_eq!(point, (1.5, 2.5));
2212 }
2213
2214 #[test]
2215 fn test_eure_variable_in_object_literal() {
2216 let x_val = 10.0;
2218 let y_val = 20.0;
2219 let doc = eure!({
2220 coords = {
2221 "x" => x_val
2222 "y" => y_val
2223 }
2224 });
2225
2226 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2227 let coords = root.field_record("coords").unwrap();
2228 let x = coords.parse_field::<f64>("x").unwrap();
2229 let y = coords.parse_field::<f64>("y").unwrap();
2230 assert_eq!(x, 10.0);
2231 assert_eq!(y, 20.0);
2232 }
2233
2234 #[test]
2235 #[allow(clippy::bool_assert_comparison)] fn test_eure_variable_mixed_with_literals() {
2237 let username = "bob";
2239 let is_active = true;
2240 let doc = eure!({
2241 user.name = username
2242 user.active = is_active
2243 user.role = "admin"
2244 user.level = 5
2245 });
2246
2247 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2248 let user = root.field_record("user").unwrap();
2249 assert_eq!(user.parse_field::<&str>("name").unwrap(), "bob");
2250 assert_eq!(user.parse_field::<bool>("active").unwrap(), true);
2251 assert_eq!(user.parse_field::<&str>("role").unwrap(), "admin");
2252 assert_eq!(user.parse_field::<i32>("level").unwrap(), 5);
2253 }
2254
2255 #[test]
2256 fn test_eure_variable_in_nested_array() {
2257 use alloc::vec::Vec;
2259 let tag1 = "rust";
2260 let tag2 = "macro";
2261 let doc = eure!({
2262 tags[] = tag1
2263 tags[] = tag2
2264 });
2265
2266 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2267 let tags = root.parse_field::<Vec<&str>>("tags").unwrap();
2268 assert_eq!(tags, vec!["rust", "macro"]);
2269 }
2270
2271 #[test]
2272 fn test_eure_variable_at_root() {
2273 let value = 42;
2275 let doc = eure!({
2276 = value
2277 });
2278
2279 let ctx = doc.parse_context(doc.get_root_id());
2280 let root_value = ctx.parse::<i32>().unwrap();
2281 assert_eq!(root_value, 42);
2282 }
2283
2284 #[test]
2285 fn test_eure_variable_in_section() {
2286 let theme_value = "dark";
2288 let lang_value = "en";
2289 let doc = eure!({
2290 @settings
2291 theme = theme_value
2292 language = lang_value
2293 });
2294
2295 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2296 let settings = root.field_record("settings").unwrap();
2297 assert_eq!(settings.parse_field::<&str>("theme").unwrap(), "dark");
2298 assert_eq!(settings.parse_field::<&str>("language").unwrap(), "en");
2299 }
2300
2301 #[test]
2302 fn test_eure_variable_null_and_primitive() {
2303 use crate::value::PrimitiveValue;
2305 let null_value = PrimitiveValue::Null;
2306 let doc = eure!({ optional = null_value });
2307
2308 let root = doc.parse_context(doc.get_root_id()).parse_record().unwrap();
2309 let optional_ctx = root.field("optional").unwrap();
2310 let optional_node = doc.node(optional_ctx.node_id());
2311 assert!(matches!(
2312 optional_node.as_primitive().unwrap(),
2313 PrimitiveValue::Null
2314 ));
2315 }
2316}