1use crate::ast::module::Module;
2use crate::ast::r#type::Type;
3use crate::ast::type_alias::TypeAlias;
4use crate::context::key::ContextKey;
5use crate::context::scope::Scope;
6use crate::context::value::ContextValue;
7use crate::llvm::builder::ir::IRBuilder;
8use crate::llvm::context::LLVMContext;
9use crate::llvm::module::LLVMModule;
10use crate::llvm::types::LLVMType;
11use crate::llvm::value::fucntion::FunctionValue;
12use crate::llvm::value::LLVMValue;
13use llvm_sys::prelude::LLVMBasicBlockRef;
14use slotmap::DefaultKey;
15use std::collections::HashMap;
16use std::rc::Rc;
17use std::sync::{Arc, Mutex, RwLock};
18
19pub mod key;
20pub mod scope;
21pub mod value;
22
23#[derive(Clone, Debug)]
24pub struct Context {
25 parent: Option<Box<Context>>,
26 key: ContextKey,
27 value: ContextValue,
28}
29
30impl Context {
31 pub fn background() -> Self {
32 Self {
33 parent: None,
34 key: ContextKey::Background,
35 value: ContextValue::Background,
36 }
37 }
38 pub fn with_builder(parent: &Context, builder: IRBuilder) -> Self {
39 Self {
40 parent: Some(Box::new(parent.clone())),
41 key: ContextKey::Builder,
42 value: ContextValue::Builder(Arc::new(builder)),
43 }
44 }
45 pub fn with_module_slot_map(parent: &Context, t: slotmap::SlotMap<DefaultKey, Module>) -> Self {
46 Self::with_value(
47 parent,
48 ContextKey::ModuleSlotMap,
49 ContextValue::ModuleSlotMap(Arc::new(RwLock::new(t))),
50 )
51 }
52 pub fn apply_mut_module(&self, key: DefaultKey, apply: impl Fn(&mut Module)) {
53 let slot_map = self.get(ContextKey::ModuleSlotMap).unwrap();
54 match slot_map {
55 ContextValue::ModuleSlotMap(slot_map) => {
56 let mut slot_map = slot_map.write().unwrap();
57 let module = slot_map.get_mut(key).unwrap();
58 apply(module)
59 }
60 _ => panic!("not a module slot map"),
61 }
62 }
63 pub fn get_module_slot_map(&self) -> Arc<RwLock<slotmap::SlotMap<DefaultKey, Module>>> {
64 match self.get(ContextKey::ModuleSlotMap) {
65 Some(ContextValue::ModuleSlotMap(slot_map)) => slot_map.clone(),
66 _ => Arc::new(RwLock::new(slotmap::SlotMap::new())),
67 }
68 }
69
70 pub fn apply_module(&self, key: DefaultKey, mut apply: impl FnMut(&Module)) {
71 let slot_map = self.get(ContextKey::ModuleSlotMap).unwrap();
72 match slot_map {
73 ContextValue::ModuleSlotMap(slot_map) => {
74 let slot_map = slot_map.read().unwrap();
75 let module = slot_map.get(key).unwrap();
76 apply(module)
77 }
78 _ => panic!("not a module slot map"),
79 }
80 }
81 pub fn register_module(&self, module: Module) -> DefaultKey {
82 let slot_map = self.get(ContextKey::ModuleSlotMap).unwrap();
83 match slot_map {
84 ContextValue::ModuleSlotMap(slot_map) => {
85 let mut slot_map = slot_map.write().unwrap();
86 slot_map.insert(module)
87 }
88 _ => panic!("not a module slot map"),
89 }
90 }
91 pub fn with_type(parent: &Context, name: String, ty: Type) -> Self {
92 Self::with_value(parent, ContextKey::Type(name), ContextValue::Type(ty))
93 }
94 pub fn get_builder(&self) -> Arc<IRBuilder> {
95 match self.get(ContextKey::Builder) {
96 Some(ContextValue::Builder(b)) => b.clone(),
97 _ => panic!("not a builder"),
98 }
99 }
100 pub fn get_current_function(&self) -> FunctionValue {
101 match self.get(ContextKey::Function) {
102 Some(ContextValue::Function(b)) => b.clone(),
103 _ => panic!("not a function"),
104 }
105 }
106 pub fn get_current_function_type(&self) -> &Type {
107 match self.get(ContextKey::Type("current_function".into())) {
108 Some(ContextValue::Type(ty)) => ty,
109 _ => panic!("not a function"),
110 }
111 }
112 pub fn with_scope(parent: &Context) -> Self {
113 Self::with_value(parent, ContextKey::Scope, ContextValue::Scope(Scope::new()))
114 }
115 pub fn with_type_table(parent: &Context, t: HashMap<Type, LLVMType>) -> Self {
116 Self::with_value(
117 parent,
118 ContextKey::TypeTable,
119 ContextValue::TypeTable(Rc::new(RwLock::new(t))),
120 )
121 }
122 pub fn create_llvm_context() -> Self {
123 let llvm_ctx = LLVMContext::new();
124 let module = llvm_ctx.create_module("main");
125 let ctx = Context {
126 parent: None,
127 key: ContextKey::LLVMContext,
128 value: ContextValue::LLVMContext(Rc::new(Mutex::new(LLVMContext::new()))),
129 };
130 Self {
131 parent: Some(Box::new(ctx)),
132 key: ContextKey::LLVMModule,
133 value: ContextValue::LLVMModule(Rc::new(RwLock::new(module))),
134 }
135 }
136 pub fn with_function(parent: &Context, f: FunctionValue) -> Self {
137 Self::with_value(parent, ContextKey::Function, ContextValue::Function(f))
138 }
139 pub fn with_flag(parent: &Context, key: impl Into<String>, flag: bool) -> Self {
140 Self::with_value(
141 parent,
142 ContextKey::Flag(key.into()),
143 ContextValue::Flag(Arc::new(RwLock::new(flag))),
144 )
145 }
146 pub fn get_llvm_module(&self) -> Rc<RwLock<LLVMModule>> {
147 match self.get(ContextKey::LLVMModule) {
148 Some(ContextValue::LLVMModule(m)) => m.clone(),
149 _ => panic!("not a llvm module"),
150 }
151 }
152 pub fn with_llvm_module(parent: &Context, m: LLVMModule) -> Self {
153 Self::with_value(
154 parent,
155 ContextKey::LLVMModule,
156 ContextValue::LLVMModule(Rc::new(RwLock::new(m))),
157 )
158 }
159 pub fn get_llvm_context(&self) -> Rc<Mutex<LLVMContext>> {
160 match self.get(ContextKey::LLVMContext) {
161 Some(ContextValue::LLVMContext(c)) => c.clone(),
162 _ => panic!("not a llvm context"),
163 }
164 }
165
166 pub fn with_local(parent: &Context, local: Vec<String>) -> Self {
167 Self::with_value(
168 parent,
169 ContextKey::LocalVariable,
170 ContextValue::LocalVariable(Arc::new(RwLock::new(local))),
171 )
172 }
173 pub fn get_type_binding_functions(&self, name: &str) -> Vec<crate::ast::function::Function> {
174 let slot_map = self.get_module_slot_map();
175 let slot_map = slot_map.read().unwrap();
176 let mut result = Vec::new();
177
178 for module in slot_map.values() {
179 for (_, function) in module.get_functions() {
180 if function.has_binding() && function.get_binding() == name {
181 result.push(function);
182 }
183 }
184 }
185
186 result
187 }
188
189 pub fn with_capture(parent: &Context) -> Self {
190 Self::with_value(
191 parent,
192 ContextKey::CaptureVariable,
193 ContextValue::CaptureVariable(Arc::new(RwLock::new(vec![]))),
194 )
195 }
196 pub fn set_flag(&self, key: impl Into<String>, flag: bool) {
197 match self.get(ContextKey::Flag(key.into())) {
198 Some(ContextValue::Flag(f)) => {
199 let mut f = f.write().unwrap();
200 *f = flag;
201 }
202 _ => panic!("not a flag"),
203 }
204 }
205 pub fn get_flag(&self, key: impl Into<String>) -> Option<bool> {
206 match self.get(ContextKey::Flag(key.into())) {
207 Some(ContextValue::Flag(f)) => {
208 let f = f.read().unwrap();
209 Some(*f)
210 }
211 _ => None,
212 }
213 }
214 pub fn with_value(parent: &Context, key: ContextKey, value: ContextValue) -> Self {
215 Self {
216 parent: Some(Box::new(parent.clone())),
217 key,
218 value,
219 }
220 }
221
222 pub fn get(&self, key: ContextKey) -> Option<&ContextValue> {
223 if self.key == key {
224 return Some(&self.value);
225 }
226 match &self.parent {
227 None => None,
228 Some(parent) => parent.get(key),
229 }
230 }
231 pub fn get_scope(&self) -> Scope {
232 match self.get(ContextKey::Scope) {
233 Some(ContextValue::Scope(s)) => s.clone(),
234 _ => panic!("not a scope"),
235 }
236 }
237 pub fn set_symbol(&self, name: String, v: LLVMValue) {
238 let scope = self.get(ContextKey::Scope).unwrap().as_scope();
239 scope.set(name, v);
240 }
241 pub fn get_symbol(&self, name: impl AsRef<str>) -> Option<LLVMValue> {
242 let scope = self.get(ContextKey::Scope).unwrap().as_scope();
243 match scope.has(name.as_ref()) {
244 true => scope.get(name),
245 false => match &self.parent {
246 None => None,
247 Some(parent) => parent.get_symbol(name),
248 },
249 }
250 }
251 pub fn get_type(&self, t: &Type) -> Option<LLVMType> {
252 match self.get(ContextKey::TypeTable) {
253 Some(ContextValue::TypeTable(tt0)) => {
254 let tt = tt0.read().unwrap();
255 let r = tt.get(t);
256 r.cloned()
257 }
258 _ => panic!("not a type table"),
259 }
260 }
261 pub fn register_type(&self, ty: &Type, llvm_ty: &LLVMType) {
262 match self.get(ContextKey::TypeTable) {
263 Some(ContextValue::TypeTable(tt0)) => {
264 let mut tt = tt0.write().unwrap();
265 tt.insert(ty.clone(), llvm_ty.clone());
266 }
267 _ => panic!("not a type table"),
268 }
269 }
270 pub fn get_alias_type(&self, name: impl AsRef<str>) -> Option<Type> {
271 match self.get(ContextKey::AliasType) {
272 Some(ContextValue::AliasType(t)) => {
273 let t = t.read().unwrap();
274 t.get(name.as_ref()).cloned()
275 }
276 _ => panic!("not a symbol type"),
277 }
278 }
279 pub fn set_alias_type(&self, name: String, t0: Type) {
280 match self.get(ContextKey::AliasType) {
281 Some(ContextValue::AliasType(t)) => {
282 let mut t = t.write().unwrap();
283 t.insert(name, t0);
284 }
285 _ => panic!("not a symbol type"),
286 }
287 }
288 pub fn get_symbol_type(&self, name: impl AsRef<str>) -> Option<Type> {
289 match self.get(ContextKey::SymbolType) {
290 Some(ContextValue::SymbolType(t)) => {
291 let t = t.read().unwrap();
292 let r = t.get(name.as_ref());
293 match r {
294 None => self.parent.clone()?.parent?.get_symbol_type(name),
295 Some(s) => Some(s.clone()),
296 }
297 }
298 _ => None,
299 }
300 }
301 pub fn try_add_local(&self, name: String) {
302 if let Some(ContextValue::LocalVariable(local)) = self.get(ContextKey::LocalVariable) {
303 let mut local = local.write().unwrap();
304 local.push(name);
305 }
306 }
307 pub fn add_capture(&self, name: String, ty: Type) {
308 match self.get(ContextKey::CaptureVariable) {
309 Some(ContextValue::CaptureVariable(local)) => {
310 let mut local = local.write().unwrap();
311 local.push((name, ty));
312 }
313 _ => panic!("not a local variable"),
314 }
315 }
316 pub fn is_local_variable(&self, name: impl AsRef<str>) -> bool {
317 match self.get(ContextKey::LocalVariable) {
318 Some(ContextValue::LocalVariable(local)) => {
319 let local = local.read().unwrap();
320 local.contains(&name.as_ref().to_string())
321 }
322 _ => panic!("not a local variable"),
323 }
324 }
325 pub fn get_captures(&self) -> Option<Vec<(String, Type)>> {
326 match self.get(ContextKey::CaptureVariable) {
327 Some(ContextValue::CaptureVariable(local)) => {
328 let local = local.read().unwrap();
329 Some(local.clone())
330 }
331 _ => panic!("not a local variable"),
332 }
333 }
334 pub fn get_function(&self, name: impl AsRef<str>) -> Option<crate::ast::function::Function> {
335 let slot_map = self.get_module_slot_map();
336 let slot_map = slot_map.read().unwrap();
337 for module in slot_map.values() {
338 if let Some(fun) = module.get_function(name.as_ref()) {
339 return Some(fun.clone());
340 }
341 }
342 None
343 }
344 pub fn set_symbol_type(&self, name: String, t0: Type) {
345 match self.get(ContextKey::SymbolType) {
346 Some(ContextValue::SymbolType(t)) => {
347 let mut t = t.write().unwrap();
348 t.insert(name, t0);
349 }
350 _ => panic!("not a symbol type"),
351 }
352 }
353 pub fn get_type_alias(&self, name: impl AsRef<str>) -> Option<TypeAlias> {
354 let slot_map = self.get_module_slot_map();
355 let slot_map = slot_map.read().unwrap();
356
357 for module in slot_map.values() {
358 if let Some(ty) = module.get_type_alias(name.as_ref()) {
359 return Some(ty.clone());
360 }
361 }
362
363 None
364 }
365 pub fn with_loop_block(parent: &Context, name: String, block: LLVMBasicBlockRef) -> Self {
366 Self::with_value(
367 parent,
368 ContextKey::LoopBlock(name),
369 ContextValue::LoopBlock(block),
370 )
371 }
372
373 pub fn get_loop_block(&self, name: &str) -> Option<LLVMBasicBlockRef> {
374 match self.get(ContextKey::LoopBlock(name.to_string())) {
375 Some(ContextValue::LoopBlock(block)) => Some(*block),
376 _ => None,
377 }
378 }
379
380 pub fn with_default_expr(parent: &Context) -> Self {
381 Self::with_value(
382 parent,
383 ContextKey::DefaultExpr,
384 ContextValue::DefaultExpr(Arc::new(RwLock::new(HashMap::new()))),
385 )
386 }
387 pub fn set_default_expr(&self, name: String, expr: Box<crate::ast::expr::ExprNode>) {
388 match self.get(ContextKey::DefaultExpr) {
389 Some(ContextValue::DefaultExpr(map)) => {
390 let mut map = map.write().unwrap();
391 map.insert(name, expr);
392 }
393 _ => panic!("not a default expr"),
394 }
395 }
396
397 pub fn get_default_expr(&self, name: &str) -> Option<Box<crate::ast::expr::ExprNode>> {
398 if let Some(ContextValue::DefaultExpr(map)) = self.get(ContextKey::DefaultExpr) {
399 map.read().unwrap().get(name).cloned()
400 } else {
401 None
402 }
403 }
404}