1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
use std::cell::RefCell; use std::rc::Rc; #[derive(Debug, Clone, Eq, PartialEq)] pub(crate) enum ContextItem { Class, Module, Sclass, Def, Defs, Block, Lambda, } #[derive(Debug, Clone, Default)] pub(crate) struct Context { pub(crate) stack: Rc<RefCell<Vec<ContextItem>>>, } impl Context { pub(crate) fn new() -> Self { Self { stack: Rc::new(RefCell::new(vec![])), } } pub(crate) fn is_empty(&self) -> bool { self.stack.borrow().is_empty() } fn push(&self, item: ContextItem) { self.stack.borrow_mut().push(item); } pub(crate) fn push_class(&self) { self.push(ContextItem::Class) } pub(crate) fn push_module(&self) { self.push(ContextItem::Module) } pub(crate) fn push_sclass(&self) { self.push(ContextItem::Sclass) } pub(crate) fn push_def(&self) { self.push(ContextItem::Def) } pub(crate) fn push_defs(&self) { self.push(ContextItem::Defs) } pub(crate) fn push_block(&self) { self.push(ContextItem::Block) } pub(crate) fn push_lambda(&self) { self.push(ContextItem::Lambda) } pub(crate) fn pop(&self) { self.stack.borrow_mut().pop(); } fn is_in(&self, item: ContextItem) -> bool { self.stack.borrow().last() == Some(&item) } pub(crate) fn is_in_class(&self) -> bool { self.is_in(ContextItem::Class) } #[allow(dead_code)] pub(crate) fn is_in_module(&self) -> bool { self.is_in(ContextItem::Module) } #[allow(dead_code)] pub(crate) fn is_in_sclass(&self) -> bool { self.is_in(ContextItem::Sclass) } pub(crate) fn is_in_def(&self) -> bool { self.is_in(ContextItem::Def) } #[allow(dead_code)] pub(crate) fn is_in_defs(&self) -> bool { self.is_in(ContextItem::Defs) } #[allow(dead_code)] pub(crate) fn is_in_block(&self) -> bool { self.is_in(ContextItem::Block) } #[allow(dead_code)] pub(crate) fn is_in_lambda(&self) -> bool { self.is_in(ContextItem::Lambda) } #[allow(dead_code)] pub(crate) fn reset(&self) { self.stack.borrow_mut().clear() } #[allow(dead_code)] pub(crate) fn is_indirectly_in_def(&self) -> bool { let stack = self.stack.borrow(); stack.contains(&ContextItem::Def) || stack.contains(&ContextItem::Defs) } pub(crate) fn is_class_definition_allowed(&self) -> bool { let stack = self.stack.borrow(); let def_index: Option<usize> = stack .iter() .rev() .position(|i| *i == ContextItem::Def || *i == ContextItem::Defs); let sclass_index: Option<usize> = stack.iter().rev().position(|i| *i == ContextItem::Sclass); match (def_index, sclass_index) { (None, _) => true, (Some(_), None) => false, (Some(def_index), Some(sclass_index)) => sclass_index < def_index, } } pub(crate) fn is_module_definition_allowed(&self) -> bool { self.is_class_definition_allowed() } pub(crate) fn is_dynamic_const_definition_allowed(&self) -> bool { self.is_class_definition_allowed() } pub(crate) fn is_in_dynamic_block(&self) -> bool { self.is_in(ContextItem::Block) || self.is_in(ContextItem::Lambda) } pub(crate) fn inner_clone(&self) -> Vec<ContextItem> { self.stack.borrow().clone() } }