1use std::{
2 collections::BTreeMap,
3 sync::{
4 Arc,
5 atomic::{AtomicU64, Ordering},
6 },
7};
8
9use crate::{
10 ContentId,
11 capability::{CapabilityName, CapabilitySet, GrantSeat, read_construct_capability},
12 control::{ControlPolicy, ControlPolicyRef, NoopControlPolicy},
13 datum_store::BTreeDatumStore,
14 effect_ledger::EffectLedger,
15 error::{Diagnostic, Error, Result},
16 eval::{EvalPolicy, EvalPolicyRef, MacroExpanderRef, Phase},
17 expr::{Expr, SourceRegistry},
18 fact_store::{BTreeFactStore, FactStore},
19 factory::Factory,
20 handle_store::BTreeHandleStore,
21 id::{LibId, Symbol},
22 library::{LoadCx, Registry},
23 list::ListRegistry,
24 number_domain::PromotionSearchLimits,
25 object::Args,
26 table::TableRegistry,
27 value::Value,
28};
29
30use super::{Diagnostics, Env};
31
32static NEXT_GRANT_ID: AtomicU64 = AtomicU64::new(1);
36
37pub type Capabilities = CapabilitySet;
39
40pub struct Cx {
49 grant_id: u64,
54 env: Env,
55 diagnostics: Diagnostics,
56 capabilities: Capabilities,
57 eval_policy: EvalPolicyRef,
58 macro_expander: Option<MacroExpanderRef>,
59 factory: Arc<dyn Factory>,
60 pub(crate) registry: Registry,
61 list_registry: ListRegistry,
62 table_registry: TableRegistry,
63 promotion_search_limits: PromotionSearchLimits,
64 sources: SourceRegistry,
65 datum_store: BTreeDatumStore,
66 handles: BTreeHandleStore,
67 facts: BTreeFactStore,
68 load_claims: BTreeMap<LibId, Vec<ContentId>>,
69 effect_ledger: EffectLedger,
70 control_policy: ControlPolicyRef,
71}
72
73impl Cx {
74 pub fn new(eval_policy: EvalPolicyRef, factory: Arc<dyn Factory>) -> Self {
88 let mut datum_store = BTreeDatumStore::default();
89 let mut facts = BTreeFactStore::default();
90 facts.insert_boot_claims(&mut datum_store);
91
92 Self {
93 grant_id: NEXT_GRANT_ID.fetch_add(1, Ordering::Relaxed),
94 env: Env::default(),
95 diagnostics: Diagnostics::default(),
96 capabilities: Capabilities::default(),
97 eval_policy,
98 macro_expander: None,
99 factory,
100 registry: Registry::default(),
101 list_registry: ListRegistry::default(),
102 table_registry: TableRegistry::default(),
103 promotion_search_limits: PromotionSearchLimits::default(),
104 sources: SourceRegistry::default(),
105 datum_store,
106 handles: BTreeHandleStore::default(),
107 facts,
108 load_claims: BTreeMap::new(),
109 effect_ledger: EffectLedger::default(),
110 control_policy: Arc::new(NoopControlPolicy),
111 }
112 }
113
114 pub fn env(&self) -> &Env {
116 &self.env
117 }
118
119 pub fn env_mut(&mut self) -> &mut Env {
121 &mut self.env
122 }
123
124 pub fn with_env<T>(&mut self, env: Env, f: impl FnOnce(&mut Self) -> Result<T>) -> Result<T> {
126 let saved = std::mem::replace(&mut self.env, env);
127 let result = f(self);
128 self.env = saved;
129 result
130 }
131
132 pub fn factory(&self) -> &dyn Factory {
134 self.factory.as_ref()
135 }
136
137 pub fn factory_ref(&self) -> Arc<dyn Factory> {
139 self.factory.clone()
140 }
141
142 pub fn with_factory<T>(
144 &mut self,
145 factory: Arc<dyn Factory>,
146 f: impl FnOnce(&mut Self) -> Result<T>,
147 ) -> Result<T> {
148 let saved = std::mem::replace(&mut self.factory, factory);
149 let result = f(self);
150 self.factory = saved;
151 result
152 }
153
154 pub fn registry(&self) -> &Registry {
156 &self.registry
157 }
158
159 pub fn registry_mut(&mut self) -> &mut Registry {
161 &mut self.registry
162 }
163
164 pub fn list_registry(&self) -> &ListRegistry {
166 &self.list_registry
167 }
168
169 pub fn list_registry_mut(&mut self) -> &mut ListRegistry {
171 &mut self.list_registry
172 }
173
174 pub fn table_registry(&self) -> &TableRegistry {
176 &self.table_registry
177 }
178
179 pub fn table_registry_mut(&mut self) -> &mut TableRegistry {
181 &mut self.table_registry
182 }
183
184 pub fn with_registry<T>(
186 &mut self,
187 registry: Registry,
188 f: impl FnOnce(&mut Self) -> Result<T>,
189 ) -> Result<T> {
190 let saved = std::mem::replace(&mut self.registry, registry);
191 let result = f(self);
192 self.registry = saved;
193 result
194 }
195
196 pub fn new_list(&mut self, items: Vec<Value>) -> Result<Value> {
198 let registry = std::mem::take(&mut self.list_registry);
199 let result = registry.new_list(self, items);
200 self.list_registry = registry;
201 result
202 }
203
204 pub fn new_cons(&mut self, car: Value, cdr: Value) -> Result<Value> {
206 let registry = std::mem::take(&mut self.list_registry);
207 let result = registry.new_cons(self, car, cdr);
208 self.list_registry = registry;
209 result
210 }
211
212 pub fn new_table(&mut self, entries: Vec<(Symbol, Value)>) -> Result<Value> {
214 let registry = std::mem::take(&mut self.table_registry);
215 let result = registry.new_table(self, entries);
216 self.table_registry = registry;
217 result
218 }
219
220 pub fn sources(&self) -> &SourceRegistry {
222 &self.sources
223 }
224
225 pub fn sources_mut(&mut self) -> &mut SourceRegistry {
227 &mut self.sources
228 }
229
230 pub fn datum_store(&self) -> &BTreeDatumStore {
232 &self.datum_store
233 }
234
235 pub fn datum_store_mut(&mut self) -> &mut BTreeDatumStore {
237 &mut self.datum_store
238 }
239
240 pub fn handles(&self) -> &BTreeHandleStore {
242 &self.handles
243 }
244
245 pub fn handles_mut(&mut self) -> &mut BTreeHandleStore {
247 &mut self.handles
248 }
249
250 pub fn facts(&self) -> &BTreeFactStore {
252 &self.facts
253 }
254
255 pub fn facts_mut(&mut self) -> &mut BTreeFactStore {
257 &mut self.facts
258 }
259
260 pub fn effect_ledger(&self) -> &EffectLedger {
262 &self.effect_ledger
263 }
264
265 pub fn effect_ledger_mut(&mut self) -> &mut EffectLedger {
267 &mut self.effect_ledger
268 }
269
270 pub fn control_policy(&self) -> &dyn ControlPolicy {
272 self.control_policy.as_ref()
273 }
274
275 pub fn control_policy_ref(&self) -> ControlPolicyRef {
277 self.control_policy.clone()
278 }
279
280 pub fn control_policy_name(&self) -> &'static str {
282 self.control_policy.name()
283 }
284
285 pub fn set_control_policy(&mut self, control_policy: ControlPolicyRef) {
287 self.control_policy = control_policy;
288 }
289
290 pub(crate) fn with_effect_ledger<T>(
291 &mut self,
292 f: impl FnOnce(&mut Self, &mut EffectLedger) -> Result<T>,
293 ) -> Result<T> {
294 let mut ledger = std::mem::take(&mut self.effect_ledger);
295 let result = f(self, &mut ledger);
296 self.effect_ledger = ledger;
297 result
298 }
299
300 pub fn insert_fact(&mut self, claim: crate::Claim) -> Result<crate::Ref> {
302 self.facts
303 .insert_authorized(&self.capabilities, &mut self.datum_store, claim)
304 }
305
306 pub fn insert_fact_for_lib(
312 &mut self,
313 lib_id: LibId,
314 claim: crate::Claim,
315 ) -> Result<crate::Ref> {
316 let (reference, inserted) = self.insert_recorded_fact(claim)?;
317 if let Some(inserted) = inserted {
318 self.record_load_claims(lib_id, vec![inserted]);
319 }
320 Ok(reference)
321 }
322
323 pub(crate) fn insert_recorded_fact(
324 &mut self,
325 claim: crate::Claim,
326 ) -> Result<(crate::Ref, Option<ContentId>)> {
327 let id = claim.content_id(&mut self.datum_store)?;
328 let existed = self.facts.get(&id).is_some();
329 let inserted = self.insert_fact(claim)?;
330 let crate::Ref::Content(inserted_id) = inserted else {
331 return Err(Error::Lib(
332 "fact insertion returned a non-content reference".to_owned(),
333 ));
334 };
335 debug_assert_eq!(inserted_id, id);
336 Ok((
337 crate::Ref::Content(inserted_id.clone()),
338 (!existed).then_some(inserted_id),
339 ))
340 }
341
342 pub fn query_facts(&self, pattern: crate::ClaimPattern) -> Result<Vec<crate::Claim>> {
344 self.facts.query_authorized(self, pattern)
345 }
346
347 pub(crate) fn record_load_claims(&mut self, lib_id: LibId, claim_ids: Vec<ContentId>) {
348 if claim_ids.is_empty() {
349 return;
350 }
351 self.load_claims
352 .entry(lib_id)
353 .or_default()
354 .extend(claim_ids);
355 }
356
357 pub(crate) fn remove_load_claims(&mut self, lib_ids: &[LibId]) {
358 for lib_id in lib_ids {
359 if let Some(claim_ids) = self.load_claims.remove(lib_id) {
360 for claim_id in claim_ids {
361 self.facts.remove(&claim_id);
362 }
363 }
364 }
365 }
366
367 pub fn promotion_search_limits(&self) -> PromotionSearchLimits {
369 self.promotion_search_limits
370 }
371
372 pub fn set_promotion_search_limits(&mut self, limits: PromotionSearchLimits) {
374 self.promotion_search_limits = limits;
375 }
376
377 pub(crate) fn load_cx(&self) -> LoadCx {
378 LoadCx::new(
379 self.capabilities.clone(),
380 self.factory.clone(),
381 self.registry.clone(),
382 )
383 }
384
385 pub fn eval_policy(&self) -> &dyn EvalPolicy {
387 self.eval_policy.as_ref()
388 }
389
390 pub fn eval_policy_ref(&self) -> EvalPolicyRef {
392 self.eval_policy.clone()
393 }
394
395 pub fn eval_policy_name(&self) -> &'static str {
397 self.eval_policy.name()
398 }
399
400 pub fn set_eval_policy(&mut self, eval_policy: EvalPolicyRef) {
402 self.eval_policy = eval_policy;
403 }
404
405 pub fn set_macro_expander(&mut self, macro_expander: MacroExpanderRef) {
407 self.macro_expander = Some(macro_expander);
408 }
409
410 pub fn clear_macro_expander(&mut self) {
412 self.macro_expander = None;
413 }
414
415 pub fn macro_expander_ref(&self) -> Option<MacroExpanderRef> {
417 self.macro_expander.clone()
418 }
419
420 pub fn expand_macros(&mut self, phase: Phase, expr: Expr) -> Result<Expr> {
422 match self.macro_expander.clone() {
423 Some(expander) => expander.expand_expr(self, phase, expr),
424 None => Ok(expr),
425 }
426 }
427
428 pub fn diagnostics(&self) -> &Diagnostics {
430 &self.diagnostics
431 }
432
433 pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
435 self.diagnostics.take()
436 }
437
438 pub fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
440 self.diagnostics.push_diagnostic(diagnostic);
441 }
442
443 pub fn push_info(&mut self, message: impl Into<String>) {
445 self.diagnostics.push_info(message);
446 }
447
448 pub fn new_seated(eval_policy: EvalPolicyRef, factory: Arc<dyn Factory>) -> (Self, GrantSeat) {
455 let cx = Self::new(eval_policy, factory);
456 let seat = GrantSeat::for_cx(cx.grant_id);
457 (cx, seat)
458 }
459
460 pub(crate) fn grant_id(&self) -> u64 {
462 self.grant_id
463 }
464
465 pub(crate) fn grant_from_host(&mut self, capability: CapabilityName) {
472 self.capabilities.insert(capability);
473 }
474
475 #[cfg(feature = "test-support")]
479 pub fn grant(&mut self, capability: CapabilityName) {
480 self.grant_from_host(capability);
481 }
482
483 #[cfg(feature = "test-support")]
486 pub fn grant_named(&mut self, capability: &'static str) {
487 self.grant_from_host(CapabilityName::new(capability));
488 }
489
490 pub fn capabilities(&self) -> &Capabilities {
492 &self.capabilities
493 }
494
495 pub fn with_capabilities<T>(
497 &mut self,
498 capabilities: Capabilities,
499 f: impl FnOnce(&mut Self) -> Result<T>,
500 ) -> Result<T> {
501 let saved = std::mem::replace(&mut self.capabilities, capabilities);
502 let result = f(self);
503 self.capabilities = saved;
504 result
505 }
506
507 pub fn resolve_class(&self, symbol: &Symbol) -> Result<Value> {
509 self.registry()
510 .class_by_symbol(symbol)
511 .cloned()
512 .ok_or_else(|| Error::UnknownClass {
513 class: symbol.clone(),
514 })
515 }
516
517 pub fn resolve_function(&self, symbol: &Symbol) -> Result<Value> {
519 self.registry()
520 .function_by_symbol(symbol)
521 .cloned()
522 .ok_or_else(|| Error::UnknownFunction {
523 function: symbol.clone(),
524 })
525 }
526
527 pub fn resolve_macro(&self, symbol: &Symbol) -> Result<Value> {
529 self.registry()
530 .macro_by_symbol(symbol)
531 .cloned()
532 .ok_or_else(|| Error::UnknownSymbol {
533 symbol: symbol.clone(),
534 })
535 }
536
537 pub fn resolve_shape(&self, symbol: &Symbol) -> Result<Value> {
539 self.registry()
540 .shape_by_symbol(symbol)
541 .cloned()
542 .ok_or_else(|| Error::UnknownSymbol {
543 symbol: symbol.clone(),
544 })
545 }
546
547 pub fn resolve_codec(&self, symbol: &Symbol) -> Result<Value> {
549 self.registry()
550 .codec_by_symbol(symbol)
551 .cloned()
552 .ok_or_else(|| Error::UnknownSymbol {
553 symbol: symbol.clone(),
554 })
555 }
556
557 pub fn resolve_number_domain(&self, symbol: &Symbol) -> Result<Value> {
559 self.registry()
560 .number_domain_by_symbol(symbol)
561 .cloned()
562 .ok_or_else(|| Error::UnknownSymbol {
563 symbol: symbol.clone(),
564 })
565 }
566
567 pub fn resolve_value(&self, symbol: &Symbol) -> Result<Value> {
569 self.registry()
570 .value_by_symbol(symbol)
571 .cloned()
572 .ok_or_else(|| Error::UnknownSymbol {
573 symbol: symbol.clone(),
574 })
575 }
576
577 pub fn call_value(&mut self, value: Value, args: Args) -> Result<Value> {
579 let Some(callable) = value.object().as_callable() else {
580 return Err(Error::TypeMismatch {
581 expected: "callable",
582 found: "non-callable",
583 });
584 };
585 callable.call(self, args)
586 }
587
588 pub fn call_exprs(&mut self, value: Value, args: Vec<crate::expr::Expr>) -> Result<Value> {
590 let Some(callable) = value.object().as_callable() else {
591 return Err(Error::TypeMismatch {
592 expected: "callable",
593 found: "non-callable",
594 });
595 };
596 callable.call_exprs(self, crate::object::RawArgs::new(args))
597 }
598
599 pub fn call_function(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
601 let function = self.resolve_function(symbol)?;
602 self.call_value(function, args)
603 }
604
605 pub fn call_class(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
607 let class = self.resolve_class(symbol)?;
608 self.call_value(class, args)
609 }
610
611 pub fn read_construct(&mut self, class: &Symbol, args: Vec<Value>) -> Result<Value> {
615 self.require(&read_construct_capability())?;
616
617 let class_value = self.resolve_class(class)?;
618 let Some(class_impl) = class_value.object().as_class() else {
619 return Err(Error::TypeMismatch {
620 expected: "class",
621 found: "non-class",
622 });
623 };
624 let Some(read_constructor) = class_impl.read_constructor(self)? else {
625 return Err(Error::Eval(format!(
626 "class {} has no read constructor",
627 class
628 )));
629 };
630 let Some(read_impl) = read_constructor.object().as_read_constructor() else {
631 return Err(Error::TypeMismatch {
632 expected: "read-constructor",
633 found: "non-read-constructor",
634 });
635 };
636 read_impl.construct_read(self, args)
637 }
638
639 pub fn force(&mut self, value: Value, demand: crate::eval::Demand) -> Result<Value> {
641 let eval_policy = self.eval_policy.clone();
642 eval_policy.force(self, value, demand)
643 }
644
645 pub fn eval_expr(&mut self, expr: crate::expr::Expr) -> Result<Value> {
647 let eval_policy = self.eval_policy.clone();
648 eval_policy.eval_expr(self, expr)
649 }
650
651 pub fn symbol_is_bound(&mut self, name: &Symbol) -> bool {
653 self.env().get(name).is_some()
654 || self.resolve_function(name).is_ok()
655 || self.resolve_class(name).is_ok()
656 || self.resolve_shape(name).is_ok()
657 || self.resolve_value(name).is_ok()
658 }
659
660 pub fn resolve_unbound_symbol(&mut self, symbol: Symbol) -> Result<Value> {
662 let eval_policy = self.eval_policy_ref();
663 eval_policy.resolve_unbound_symbol(self, symbol)
664 }
665
666 pub fn resolve_unbound_call(
668 &mut self,
669 operator: Symbol,
670 args: Vec<crate::expr::Expr>,
671 ) -> Result<Value> {
672 let eval_policy = self.eval_policy_ref();
673 eval_policy.resolve_unbound_call(self, operator, args)
674 }
675
676 pub fn require(&self, capability: &CapabilityName) -> Result<()> {
678 if self.capabilities.contains(capability) {
679 Ok(())
680 } else {
681 Err(Error::CapabilityDenied {
682 capability: capability.clone(),
683 })
684 }
685 }
686
687 pub fn require_all(&self, capabilities: &[CapabilityName]) -> Result<()> {
689 for capability in capabilities {
690 self.require(capability)?;
691 }
692 Ok(())
693 }
694}