lib_ruby_parser/
context.rs1use std::cell::RefCell;
2use std::rc::Rc;
3
4#[derive(Debug, Clone, Eq, PartialEq, Default)]
5pub(crate) struct SharedContext {
6 value: Rc<RefCell<Context>>,
7}
8
9#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
10pub(crate) struct Context {
11 value: usize,
12}
13
14macro_rules! context_flag {
15 ($upper:ident, $getter:ident, $setter: ident, $value:expr) => {
16 impl Context {
17 const $upper: usize = $value;
18
19 pub(crate) fn $getter(&self) -> bool {
20 (self.value & Self::$upper) != 0
21 }
22
23 pub(crate) fn $setter(&mut self, value: bool) {
24 if cfg!(feature = "debug-parser") {
25 println!("{}({})", stringify!($setter), value);
26 }
27 if value {
28 self.value |= Self::$upper;
29 } else {
30 self.value &= !Self::$upper;
31 }
32 }
33 }
34
35 impl SharedContext {
36 #[allow(dead_code)]
37 pub(crate) fn $getter(&self) -> bool {
38 self.value.borrow().$getter()
39 }
40
41 pub(crate) fn $setter(&mut self, value: bool) {
42 self.value.borrow_mut().$setter(value)
43 }
44 }
45 };
46}
47
48context_flag!(IN_DEFINED, in_defined, set_in_defined, 1 << 0);
49context_flag!(IN_KWARG, in_kwarg, set_in_kwarg, 1 << 1);
50context_flag!(IN_ARGDEF, in_argdef, set_in_argdef, 1 << 2);
51context_flag!(IN_DEF, in_def, set_in_def, 1 << 3);
52context_flag!(IN_CLASS, in_class, set_in_class, 1 << 4);
53context_flag!(IN_LAMBDA, in_lambda, set_in_lambda, 1 << 5);
54context_flag!(IN_BLOCK, in_block, set_in_block, 1 << 6);
55
56impl SharedContext {
57 pub(crate) fn new() -> Self {
58 Self::default()
59 }
60
61 pub(crate) fn dump(&self) -> Context {
62 *self.value.borrow()
63 }
64
65 pub(crate) fn is_in_dynamic_block(&self) -> bool {
66 self.in_block() || self.in_lambda()
67 }
68
69 pub(crate) fn is_empty(&self) -> bool {
70 self.value.borrow().is_empty()
71 }
72}
73
74impl Context {
75 fn is_empty(&self) -> bool {
76 if cfg!(debug_assertions) && self.value != 0 {
77 println!(
78 "Context is not empty;
79 value = {};
80 IN_DEFINED = {}
81 IN_KWARG = {}
82 IN_ARGDEF = {}
83 IN_DEF = {}
84 IN_CLASS = {}
85 IN_LAMBDA = {}
86 IN_BLOCK = {}",
87 self.value,
88 self.in_defined(),
89 self.in_kwarg(),
90 self.in_argdef(),
91 self.in_def(),
92 self.in_class(),
93 self.in_lambda(),
94 self.in_block(),
95 );
96 }
97 self.value == 0
98 }
99}
100
101#[test]
102fn test_context() {
103 let mut context = Context::default();
104
105 context.set_in_def(true);
106 context.set_in_class(true);
107 assert!(context.in_def());
108 assert!(context.in_class());
109
110 context.set_in_def(false);
111 assert!(!context.in_def());
112 assert!(context.in_class());
113
114 context.set_in_class(false);
115 assert!(!context.in_def());
116 assert!(!context.in_class());
117
118 assert!(context.is_empty());
119}