1use std::{collections::BTreeMap, sync::Arc};
2
3use crate::{
4 ContentId,
5 capability::{CapabilityName, CapabilitySet, read_construct_capability},
6 control::{ControlPolicy, ControlPolicyRef, NoopControlPolicy},
7 datum_store::BTreeDatumStore,
8 effect_ledger::EffectLedger,
9 error::{Diagnostic, Error, Result},
10 eval::{EvalPolicy, EvalPolicyRef, MacroExpanderRef, Phase},
11 expr::{Expr, SourceRegistry},
12 fact_store::{BTreeFactStore, FactStore},
13 factory::Factory,
14 handle_store::BTreeHandleStore,
15 id::{LibId, Symbol},
16 library::{LoadCx, Registry},
17 list::ListRegistry,
18 number_domain::PromotionSearchLimits,
19 object::Args,
20 table::TableRegistry,
21 value::Value,
22};
23
24use super::{Diagnostics, Env};
25
26pub type Capabilities = CapabilitySet;
28
29pub struct Cx {
38 env: Env,
39 diagnostics: Diagnostics,
40 capabilities: Capabilities,
41 eval_policy: EvalPolicyRef,
42 macro_expander: Option<MacroExpanderRef>,
43 factory: Arc<dyn Factory>,
44 pub(crate) registry: Registry,
45 list_registry: ListRegistry,
46 table_registry: TableRegistry,
47 promotion_search_limits: PromotionSearchLimits,
48 sources: SourceRegistry,
49 datum_store: BTreeDatumStore,
50 handles: BTreeHandleStore,
51 facts: BTreeFactStore,
52 load_claims: BTreeMap<LibId, Vec<ContentId>>,
53 effect_ledger: EffectLedger,
54 control_policy: ControlPolicyRef,
55}
56
57impl Cx {
58 pub fn new(eval_policy: EvalPolicyRef, factory: Arc<dyn Factory>) -> Self {
72 let mut datum_store = BTreeDatumStore::default();
73 let mut facts = BTreeFactStore::default();
74 facts.insert_boot_claims(&mut datum_store);
75
76 Self {
77 env: Env::default(),
78 diagnostics: Diagnostics::default(),
79 capabilities: Capabilities::default(),
80 eval_policy,
81 macro_expander: None,
82 factory,
83 registry: Registry::default(),
84 list_registry: ListRegistry::default(),
85 table_registry: TableRegistry::default(),
86 promotion_search_limits: PromotionSearchLimits::default(),
87 sources: SourceRegistry::default(),
88 datum_store,
89 handles: BTreeHandleStore::default(),
90 facts,
91 load_claims: BTreeMap::new(),
92 effect_ledger: EffectLedger::default(),
93 control_policy: Arc::new(NoopControlPolicy),
94 }
95 }
96
97 pub fn env(&self) -> &Env {
99 &self.env
100 }
101
102 pub fn env_mut(&mut self) -> &mut Env {
104 &mut self.env
105 }
106
107 pub fn with_env<T>(&mut self, env: Env, f: impl FnOnce(&mut Self) -> Result<T>) -> Result<T> {
109 let saved = std::mem::replace(&mut self.env, env);
110 let result = f(self);
111 self.env = saved;
112 result
113 }
114
115 pub fn factory(&self) -> &dyn Factory {
117 self.factory.as_ref()
118 }
119
120 pub fn factory_ref(&self) -> Arc<dyn Factory> {
122 self.factory.clone()
123 }
124
125 pub fn with_factory<T>(
127 &mut self,
128 factory: Arc<dyn Factory>,
129 f: impl FnOnce(&mut Self) -> Result<T>,
130 ) -> Result<T> {
131 let saved = std::mem::replace(&mut self.factory, factory);
132 let result = f(self);
133 self.factory = saved;
134 result
135 }
136
137 pub fn registry(&self) -> &Registry {
139 &self.registry
140 }
141
142 pub fn registry_mut(&mut self) -> &mut Registry {
144 &mut self.registry
145 }
146
147 pub fn list_registry(&self) -> &ListRegistry {
149 &self.list_registry
150 }
151
152 pub fn list_registry_mut(&mut self) -> &mut ListRegistry {
154 &mut self.list_registry
155 }
156
157 pub fn table_registry(&self) -> &TableRegistry {
159 &self.table_registry
160 }
161
162 pub fn table_registry_mut(&mut self) -> &mut TableRegistry {
164 &mut self.table_registry
165 }
166
167 pub fn with_registry<T>(
169 &mut self,
170 registry: Registry,
171 f: impl FnOnce(&mut Self) -> Result<T>,
172 ) -> Result<T> {
173 let saved = std::mem::replace(&mut self.registry, registry);
174 let result = f(self);
175 self.registry = saved;
176 result
177 }
178
179 pub fn new_list(&mut self, items: Vec<Value>) -> Result<Value> {
181 let registry = std::mem::take(&mut self.list_registry);
182 let result = registry.new_list(self, items);
183 self.list_registry = registry;
184 result
185 }
186
187 pub fn new_cons(&mut self, car: Value, cdr: Value) -> Result<Value> {
189 let registry = std::mem::take(&mut self.list_registry);
190 let result = registry.new_cons(self, car, cdr);
191 self.list_registry = registry;
192 result
193 }
194
195 pub fn new_table(&mut self, entries: Vec<(Symbol, Value)>) -> Result<Value> {
197 let registry = std::mem::take(&mut self.table_registry);
198 let result = registry.new_table(self, entries);
199 self.table_registry = registry;
200 result
201 }
202
203 pub fn sources(&self) -> &SourceRegistry {
205 &self.sources
206 }
207
208 pub fn sources_mut(&mut self) -> &mut SourceRegistry {
210 &mut self.sources
211 }
212
213 pub fn datum_store(&self) -> &BTreeDatumStore {
215 &self.datum_store
216 }
217
218 pub fn datum_store_mut(&mut self) -> &mut BTreeDatumStore {
220 &mut self.datum_store
221 }
222
223 pub fn handles(&self) -> &BTreeHandleStore {
225 &self.handles
226 }
227
228 pub fn handles_mut(&mut self) -> &mut BTreeHandleStore {
230 &mut self.handles
231 }
232
233 pub fn facts(&self) -> &BTreeFactStore {
235 &self.facts
236 }
237
238 pub fn facts_mut(&mut self) -> &mut BTreeFactStore {
240 &mut self.facts
241 }
242
243 pub fn effect_ledger(&self) -> &EffectLedger {
245 &self.effect_ledger
246 }
247
248 pub fn effect_ledger_mut(&mut self) -> &mut EffectLedger {
250 &mut self.effect_ledger
251 }
252
253 pub fn control_policy(&self) -> &dyn ControlPolicy {
255 self.control_policy.as_ref()
256 }
257
258 pub fn control_policy_ref(&self) -> ControlPolicyRef {
260 self.control_policy.clone()
261 }
262
263 pub fn control_policy_name(&self) -> &'static str {
265 self.control_policy.name()
266 }
267
268 pub fn set_control_policy(&mut self, control_policy: ControlPolicyRef) {
270 self.control_policy = control_policy;
271 }
272
273 pub(crate) fn with_effect_ledger<T>(
274 &mut self,
275 f: impl FnOnce(&mut Self, &mut EffectLedger) -> Result<T>,
276 ) -> Result<T> {
277 let mut ledger = std::mem::take(&mut self.effect_ledger);
278 let result = f(self, &mut ledger);
279 self.effect_ledger = ledger;
280 result
281 }
282
283 pub fn insert_fact(&mut self, claim: crate::Claim) -> Result<crate::Ref> {
285 self.facts
286 .insert_authorized(&self.capabilities, &mut self.datum_store, claim)
287 }
288
289 pub fn insert_fact_for_lib(
295 &mut self,
296 lib_id: LibId,
297 claim: crate::Claim,
298 ) -> Result<crate::Ref> {
299 let (reference, inserted) = self.insert_recorded_fact(claim)?;
300 if let Some(inserted) = inserted {
301 self.record_load_claims(lib_id, vec![inserted]);
302 }
303 Ok(reference)
304 }
305
306 pub(crate) fn insert_recorded_fact(
307 &mut self,
308 claim: crate::Claim,
309 ) -> Result<(crate::Ref, Option<ContentId>)> {
310 let id = claim.content_id(&mut self.datum_store)?;
311 let existed = self.facts.get(&id).is_some();
312 let inserted = self.insert_fact(claim)?;
313 let crate::Ref::Content(inserted_id) = inserted else {
314 return Err(Error::Lib(
315 "fact insertion returned a non-content reference".to_owned(),
316 ));
317 };
318 debug_assert_eq!(inserted_id, id);
319 Ok((
320 crate::Ref::Content(inserted_id.clone()),
321 (!existed).then_some(inserted_id),
322 ))
323 }
324
325 pub fn query_facts(&self, pattern: crate::ClaimPattern) -> Result<Vec<crate::Claim>> {
327 self.facts.query_authorized(self, pattern)
328 }
329
330 pub(crate) fn record_load_claims(&mut self, lib_id: LibId, claim_ids: Vec<ContentId>) {
331 if claim_ids.is_empty() {
332 return;
333 }
334 self.load_claims
335 .entry(lib_id)
336 .or_default()
337 .extend(claim_ids);
338 }
339
340 pub(crate) fn remove_load_claims(&mut self, lib_ids: &[LibId]) {
341 for lib_id in lib_ids {
342 if let Some(claim_ids) = self.load_claims.remove(lib_id) {
343 for claim_id in claim_ids {
344 self.facts.remove(&claim_id);
345 }
346 }
347 }
348 }
349
350 pub fn promotion_search_limits(&self) -> PromotionSearchLimits {
352 self.promotion_search_limits
353 }
354
355 pub fn set_promotion_search_limits(&mut self, limits: PromotionSearchLimits) {
357 self.promotion_search_limits = limits;
358 }
359
360 pub(crate) fn load_cx(&self) -> LoadCx {
361 LoadCx::new(
362 self.capabilities.clone(),
363 self.factory.clone(),
364 self.registry.clone(),
365 )
366 }
367
368 pub fn eval_policy(&self) -> &dyn EvalPolicy {
370 self.eval_policy.as_ref()
371 }
372
373 pub fn eval_policy_ref(&self) -> EvalPolicyRef {
375 self.eval_policy.clone()
376 }
377
378 pub fn eval_policy_name(&self) -> &'static str {
380 self.eval_policy.name()
381 }
382
383 pub fn set_eval_policy(&mut self, eval_policy: EvalPolicyRef) {
385 self.eval_policy = eval_policy;
386 }
387
388 pub fn set_macro_expander(&mut self, macro_expander: MacroExpanderRef) {
390 self.macro_expander = Some(macro_expander);
391 }
392
393 pub fn clear_macro_expander(&mut self) {
395 self.macro_expander = None;
396 }
397
398 pub fn macro_expander_ref(&self) -> Option<MacroExpanderRef> {
400 self.macro_expander.clone()
401 }
402
403 pub fn expand_macros(&mut self, phase: Phase, expr: Expr) -> Result<Expr> {
405 match self.macro_expander.clone() {
406 Some(expander) => expander.expand_expr(self, phase, expr),
407 None => Ok(expr),
408 }
409 }
410
411 pub fn diagnostics(&self) -> &Diagnostics {
413 &self.diagnostics
414 }
415
416 pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
418 self.diagnostics.take()
419 }
420
421 pub fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
423 self.diagnostics.push_diagnostic(diagnostic);
424 }
425
426 pub fn push_info(&mut self, message: impl Into<String>) {
428 self.diagnostics.push_info(message);
429 }
430
431 pub fn grant(&mut self, capability: CapabilityName) {
433 self.capabilities.insert(capability);
434 }
435
436 pub fn grant_named(&mut self, capability: &'static str) {
438 self.capabilities.insert(CapabilityName::new(capability));
439 }
440
441 pub fn capabilities(&self) -> &Capabilities {
443 &self.capabilities
444 }
445
446 pub fn with_capabilities<T>(
448 &mut self,
449 capabilities: Capabilities,
450 f: impl FnOnce(&mut Self) -> Result<T>,
451 ) -> Result<T> {
452 let saved = std::mem::replace(&mut self.capabilities, capabilities);
453 let result = f(self);
454 self.capabilities = saved;
455 result
456 }
457
458 pub fn resolve_class(&self, symbol: &Symbol) -> Result<Value> {
460 self.registry()
461 .class_by_symbol(symbol)
462 .cloned()
463 .ok_or_else(|| Error::UnknownClass {
464 class: symbol.clone(),
465 })
466 }
467
468 pub fn resolve_function(&self, symbol: &Symbol) -> Result<Value> {
470 self.registry()
471 .function_by_symbol(symbol)
472 .cloned()
473 .ok_or_else(|| Error::UnknownFunction {
474 function: symbol.clone(),
475 })
476 }
477
478 pub fn resolve_macro(&self, symbol: &Symbol) -> Result<Value> {
480 self.registry()
481 .macro_by_symbol(symbol)
482 .cloned()
483 .ok_or_else(|| Error::UnknownSymbol {
484 symbol: symbol.clone(),
485 })
486 }
487
488 pub fn resolve_shape(&self, symbol: &Symbol) -> Result<Value> {
490 self.registry()
491 .shape_by_symbol(symbol)
492 .cloned()
493 .ok_or_else(|| Error::UnknownSymbol {
494 symbol: symbol.clone(),
495 })
496 }
497
498 pub fn resolve_codec(&self, symbol: &Symbol) -> Result<Value> {
500 self.registry()
501 .codec_by_symbol(symbol)
502 .cloned()
503 .ok_or_else(|| Error::UnknownSymbol {
504 symbol: symbol.clone(),
505 })
506 }
507
508 pub fn resolve_number_domain(&self, symbol: &Symbol) -> Result<Value> {
510 self.registry()
511 .number_domain_by_symbol(symbol)
512 .cloned()
513 .ok_or_else(|| Error::UnknownSymbol {
514 symbol: symbol.clone(),
515 })
516 }
517
518 pub fn resolve_value(&self, symbol: &Symbol) -> Result<Value> {
520 self.registry()
521 .value_by_symbol(symbol)
522 .cloned()
523 .ok_or_else(|| Error::UnknownSymbol {
524 symbol: symbol.clone(),
525 })
526 }
527
528 pub fn call_value(&mut self, value: Value, args: Args) -> Result<Value> {
530 let Some(callable) = value.object().as_callable() else {
531 return Err(Error::TypeMismatch {
532 expected: "callable",
533 found: "non-callable",
534 });
535 };
536 callable.call(self, args)
537 }
538
539 pub fn call_exprs(&mut self, value: Value, args: Vec<crate::expr::Expr>) -> Result<Value> {
541 let Some(callable) = value.object().as_callable() else {
542 return Err(Error::TypeMismatch {
543 expected: "callable",
544 found: "non-callable",
545 });
546 };
547 callable.call_exprs(self, crate::object::RawArgs::new(args))
548 }
549
550 pub fn call_function(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
552 let function = self.resolve_function(symbol)?;
553 self.call_value(function, args)
554 }
555
556 pub fn call_class(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
558 let class = self.resolve_class(symbol)?;
559 self.call_value(class, args)
560 }
561
562 pub fn read_construct(&mut self, class: &Symbol, args: Vec<Value>) -> Result<Value> {
566 self.require(&read_construct_capability())?;
567
568 let class_value = self.resolve_class(class)?;
569 let Some(class_impl) = class_value.object().as_class() else {
570 return Err(Error::TypeMismatch {
571 expected: "class",
572 found: "non-class",
573 });
574 };
575 let Some(read_constructor) = class_impl.read_constructor(self)? else {
576 return Err(Error::Eval(format!(
577 "class {} has no read constructor",
578 class
579 )));
580 };
581 let Some(read_impl) = read_constructor.object().as_read_constructor() else {
582 return Err(Error::TypeMismatch {
583 expected: "read-constructor",
584 found: "non-read-constructor",
585 });
586 };
587 read_impl.construct_read(self, args)
588 }
589
590 pub fn force(&mut self, value: Value, demand: crate::eval::Demand) -> Result<Value> {
592 let eval_policy = self.eval_policy.clone();
593 eval_policy.force(self, value, demand)
594 }
595
596 pub fn eval_expr(&mut self, expr: crate::expr::Expr) -> Result<Value> {
598 let eval_policy = self.eval_policy.clone();
599 eval_policy.eval_expr(self, expr)
600 }
601
602 pub fn symbol_is_bound(&mut self, name: &Symbol) -> bool {
604 self.env().get(name).is_some()
605 || self.resolve_function(name).is_ok()
606 || self.resolve_class(name).is_ok()
607 || self.resolve_shape(name).is_ok()
608 || self.resolve_value(name).is_ok()
609 }
610
611 pub fn resolve_unbound_symbol(&mut self, symbol: Symbol) -> Result<Value> {
613 let eval_policy = self.eval_policy_ref();
614 eval_policy.resolve_unbound_symbol(self, symbol)
615 }
616
617 pub fn resolve_unbound_call(
619 &mut self,
620 operator: Symbol,
621 args: Vec<crate::expr::Expr>,
622 ) -> Result<Value> {
623 let eval_policy = self.eval_policy_ref();
624 eval_policy.resolve_unbound_call(self, operator, args)
625 }
626
627 pub fn require(&self, capability: &CapabilityName) -> Result<()> {
629 if self.capabilities.contains(capability) {
630 Ok(())
631 } else {
632 Err(Error::CapabilityDenied {
633 capability: capability.clone(),
634 })
635 }
636 }
637
638 pub fn require_all(&self, capabilities: &[CapabilityName]) -> Result<()> {
640 for capability in capabilities {
641 self.require(capability)?;
642 }
643 Ok(())
644 }
645}