1use std::sync::{
2 Arc,
3 atomic::{AtomicU64, Ordering},
4};
5
6use crate::{
7 ContentId,
8 capability::{
9 CapabilityName, CapabilitySet, GrantSeat, macro_expansion_capability_for_phase,
10 read_construct_capability,
11 },
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, load_ledger::LibLoadLedger};
31
32static NEXT_GRANT_ID: AtomicU64 = AtomicU64::new(1);
36
37fn unknown_symbol(symbol: &Symbol) -> Error {
38 Error::UnknownSymbol {
39 symbol: symbol.clone(),
40 }
41}
42
43fn class_protocol(value: &Value) -> Result<&dyn crate::Class> {
44 value.object().as_class().ok_or(Error::TypeMismatch {
45 expected: "class",
46 found: "non-class",
47 })
48}
49
50fn read_constructor_protocol(value: &Value) -> Result<&dyn crate::ReadConstructor> {
51 value
52 .object()
53 .as_read_constructor()
54 .ok_or(Error::TypeMismatch {
55 expected: "read-constructor",
56 found: "non-read-constructor",
57 })
58}
59
60pub type Capabilities = CapabilitySet;
62
63pub struct Cx {
72 grant_id: u64,
77 env: Env,
78 diagnostics: Diagnostics,
79 capabilities: Capabilities,
80 eval_policy: EvalPolicyRef,
81 macro_expander: Option<MacroExpanderRef>,
82 factory: Arc<dyn Factory>,
83 pub(crate) registry: Registry,
84 list_registry: ListRegistry,
85 table_registry: TableRegistry,
86 promotion_search_limits: PromotionSearchLimits,
87 sources: SourceRegistry,
88 pub(super) datum_store: BTreeDatumStore,
89 handles: BTreeHandleStore,
90 pub(super) facts: BTreeFactStore,
91 pub(super) lib_load_ledger: LibLoadLedger,
92 effect_ledger: EffectLedger,
93 control_policy: ControlPolicyRef,
94}
95
96impl Cx {
97 pub fn new(
103 eval_policy: EvalPolicyRef,
104 factory: Arc<dyn Factory>,
105 handle_seed: crate::HandleSeed,
106 ) -> Self {
107 let mut datum_store = BTreeDatumStore::default();
108 let mut facts = BTreeFactStore::default();
109 facts.insert_boot_claims(&mut datum_store);
110
111 Self {
112 grant_id: NEXT_GRANT_ID.fetch_add(1, Ordering::Relaxed),
113 env: Env::default(),
114 diagnostics: Diagnostics::default(),
115 capabilities: Capabilities::default(),
116 eval_policy,
117 macro_expander: None,
118 factory,
119 registry: Registry::default(),
120 list_registry: ListRegistry::default(),
121 table_registry: TableRegistry::default(),
122 promotion_search_limits: PromotionSearchLimits::default(),
123 sources: SourceRegistry::default(),
124 datum_store,
125 handles: BTreeHandleStore::new(handle_seed),
126 facts,
127 lib_load_ledger: LibLoadLedger::default(),
128 effect_ledger: EffectLedger::default(),
129 control_policy: Arc::new(NoopControlPolicy),
130 }
131 }
132
133 pub fn fresh_handle(&mut self) -> crate::HandleId {
135 self.handles.fresh_handle()
136 }
137
138 pub fn env(&self) -> &Env {
140 &self.env
141 }
142
143 pub fn env_mut(&mut self) -> &mut Env {
145 &mut self.env
146 }
147
148 pub fn with_env<T>(&mut self, env: Env, f: impl FnOnce(&mut Self) -> Result<T>) -> Result<T> {
150 let saved = std::mem::replace(&mut self.env, env);
151 let result = f(self);
152 self.env = saved;
153 result
154 }
155
156 pub fn factory(&self) -> &dyn Factory {
158 self.factory.as_ref()
159 }
160
161 pub fn factory_ref(&self) -> Arc<dyn Factory> {
163 self.factory.clone()
164 }
165
166 pub fn with_factory<T>(
168 &mut self,
169 factory: Arc<dyn Factory>,
170 f: impl FnOnce(&mut Self) -> Result<T>,
171 ) -> Result<T> {
172 let saved = std::mem::replace(&mut self.factory, factory);
173 let result = f(self);
174 self.factory = saved;
175 result
176 }
177
178 pub fn registry(&self) -> &Registry {
180 &self.registry
181 }
182
183 pub fn registry_mut(&mut self) -> &mut Registry {
185 &mut self.registry
186 }
187
188 pub fn list_registry(&self) -> &ListRegistry {
190 &self.list_registry
191 }
192
193 pub fn list_registry_mut(&mut self) -> &mut ListRegistry {
195 &mut self.list_registry
196 }
197
198 pub fn table_registry(&self) -> &TableRegistry {
200 &self.table_registry
201 }
202
203 pub fn table_registry_mut(&mut self) -> &mut TableRegistry {
205 &mut self.table_registry
206 }
207
208 pub fn with_registry<T>(
210 &mut self,
211 registry: Registry,
212 f: impl FnOnce(&mut Self) -> Result<T>,
213 ) -> Result<T> {
214 let saved = std::mem::replace(&mut self.registry, registry);
215 let result = f(self);
216 self.registry = saved;
217 result
218 }
219
220 pub fn new_list(&mut self, items: Vec<Value>) -> Result<Value> {
222 let registry = std::mem::take(&mut self.list_registry);
223 let result = registry.new_list(self, items);
224 self.list_registry = registry;
225 result
226 }
227
228 pub fn new_cons(&mut self, car: Value, cdr: Value) -> Result<Value> {
230 let registry = std::mem::take(&mut self.list_registry);
231 let result = registry.new_cons(self, car, cdr);
232 self.list_registry = registry;
233 result
234 }
235
236 pub fn new_table(&mut self, entries: Vec<(Symbol, Value)>) -> Result<Value> {
238 let registry = std::mem::take(&mut self.table_registry);
239 let result = registry.new_table(self, entries);
240 self.table_registry = registry;
241 result
242 }
243
244 pub fn sources(&self) -> &SourceRegistry {
246 &self.sources
247 }
248
249 pub fn sources_mut(&mut self) -> &mut SourceRegistry {
251 &mut self.sources
252 }
253
254 pub fn datum_store(&self) -> &BTreeDatumStore {
256 &self.datum_store
257 }
258
259 pub fn datum_store_mut(&mut self) -> &mut BTreeDatumStore {
261 &mut self.datum_store
262 }
263
264 pub fn handles(&self) -> &BTreeHandleStore {
266 &self.handles
267 }
268
269 pub fn handles_mut(&mut self) -> &mut BTreeHandleStore {
271 &mut self.handles
272 }
273
274 pub fn facts(&self) -> &BTreeFactStore {
276 &self.facts
277 }
278
279 pub fn facts_mut(&mut self) -> &mut BTreeFactStore {
281 &mut self.facts
282 }
283
284 pub fn effect_ledger(&self) -> &EffectLedger {
286 &self.effect_ledger
287 }
288
289 pub fn effect_ledger_mut(&mut self) -> &mut EffectLedger {
291 &mut self.effect_ledger
292 }
293
294 pub fn control_policy(&self) -> &dyn ControlPolicy {
296 self.control_policy.as_ref()
297 }
298
299 pub fn control_policy_ref(&self) -> ControlPolicyRef {
301 self.control_policy.clone()
302 }
303
304 pub fn control_policy_name(&self) -> &'static str {
306 self.control_policy.name()
307 }
308
309 pub fn set_control_policy(&mut self, control_policy: ControlPolicyRef) {
311 self.control_policy = control_policy;
312 }
313
314 pub(crate) fn with_effect_ledger<T>(
315 &mut self,
316 f: impl FnOnce(&mut Self, &mut EffectLedger) -> Result<T>,
317 ) -> Result<T> {
318 let mut ledger = std::mem::take(&mut self.effect_ledger);
319 let result = f(self, &mut ledger);
320 self.effect_ledger = ledger;
321 result
322 }
323
324 pub fn insert_fact(&mut self, claim: crate::Claim) -> Result<crate::Ref> {
326 self.facts
327 .insert_authorized(&self.capabilities, &mut self.datum_store, claim)
328 }
329
330 pub fn insert_fact_for_lib(
336 &mut self,
337 lib_id: LibId,
338 claim: crate::Claim,
339 ) -> Result<crate::Ref> {
340 let (reference, inserted) = self.insert_recorded_fact(claim)?;
341 if let Some(inserted) = inserted {
342 self.record_load_claims(lib_id, vec![inserted]);
343 }
344 Ok(reference)
345 }
346
347 pub(crate) fn insert_recorded_fact(
348 &mut self,
349 claim: crate::Claim,
350 ) -> Result<(crate::Ref, Option<ContentId>)> {
351 let id = claim.content_id(&mut self.datum_store)?;
352 let existed = self.facts.get(&id).is_some();
353 let inserted = self.insert_fact(claim)?;
354 let crate::Ref::Content(inserted_id) = inserted else {
355 return Err(Error::Lib(
356 "fact insertion returned a non-content reference".to_owned(),
357 ));
358 };
359 debug_assert_eq!(inserted_id, id);
360 Ok((
361 crate::Ref::Content(inserted_id.clone()),
362 (!existed).then_some(inserted_id),
363 ))
364 }
365
366 pub fn query_facts(&self, pattern: crate::ClaimPattern) -> Result<Vec<crate::Claim>> {
368 self.facts.query_authorized(self, pattern)
369 }
370
371 pub(crate) fn record_load_claims(&mut self, lib_id: LibId, claim_ids: Vec<ContentId>) {
372 self.lib_load_ledger.record_claims(lib_id, claim_ids);
373 }
374
375 pub(crate) fn remove_load_claims(&mut self, lib_ids: &[LibId]) {
376 self.lib_load_ledger.remove_claims(lib_ids, &mut self.facts);
377 }
378
379 pub fn promotion_search_limits(&self) -> PromotionSearchLimits {
381 self.promotion_search_limits
382 }
383
384 pub fn set_promotion_search_limits(&mut self, limits: PromotionSearchLimits) {
386 self.promotion_search_limits = limits;
387 }
388
389 pub(crate) fn load_cx(&self) -> LoadCx {
390 LoadCx::new(
391 self.capabilities.clone(),
392 self.factory.clone(),
393 self.registry.clone(),
394 )
395 }
396
397 pub fn eval_policy(&self) -> &dyn EvalPolicy {
399 self.eval_policy.as_ref()
400 }
401
402 pub fn eval_policy_ref(&self) -> EvalPolicyRef {
404 self.eval_policy.clone()
405 }
406
407 pub fn eval_policy_name(&self) -> &'static str {
409 self.eval_policy.name()
410 }
411
412 pub fn set_eval_policy(&mut self, eval_policy: EvalPolicyRef) {
414 self.eval_policy = eval_policy;
415 }
416
417 pub fn set_macro_expander(&mut self, macro_expander: MacroExpanderRef) {
419 self.macro_expander = Some(macro_expander);
420 }
421
422 pub fn clear_macro_expander(&mut self) {
424 self.macro_expander = None;
425 }
426
427 pub fn macro_expander_ref(&self) -> Option<MacroExpanderRef> {
429 self.macro_expander.clone()
430 }
431
432 pub fn expand_macros(&mut self, phase: Phase, expr: Expr) -> Result<Expr> {
434 let Some(expander) = self.macro_expander.clone() else {
435 return Ok(expr);
436 };
437 let eval_policy = self.eval_policy_ref();
438 if !eval_policy.allow_macro_expansion(phase) {
439 return Err(Error::Eval(format!(
440 "macro expansion denied by eval policy {} for {phase:?}",
441 eval_policy.name()
442 )));
443 }
444 self.require(¯o_expansion_capability_for_phase(phase))?;
445 expander.expand_expr(self, phase, expr)
446 }
447
448 pub fn diagnostics(&self) -> &Diagnostics {
450 &self.diagnostics
451 }
452
453 pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
455 self.diagnostics.take()
456 }
457
458 pub fn push_diagnostic(&mut self, diagnostic: Diagnostic) {
460 self.diagnostics.push_diagnostic(diagnostic);
461 }
462
463 pub fn push_info(&mut self, message: impl Into<String>) {
465 self.diagnostics.push_info(message);
466 }
467
468 pub fn new_seated(
475 eval_policy: EvalPolicyRef,
476 factory: Arc<dyn Factory>,
477 handle_seed: crate::HandleSeed,
478 ) -> (Self, GrantSeat) {
479 let cx = Self::new(eval_policy, factory, handle_seed);
480 let seat = GrantSeat::for_cx(cx.grant_id);
481 (cx, seat)
482 }
483
484 pub(crate) fn grant_id(&self) -> u64 {
486 self.grant_id
487 }
488
489 pub(crate) fn grant_from_host(&mut self, capability: CapabilityName) {
496 self.capabilities.insert(capability);
497 }
498
499 #[cfg(feature = "test-support")]
503 pub fn grant(&mut self, capability: CapabilityName) {
504 self.grant_from_host(capability);
505 }
506
507 #[cfg(feature = "test-support")]
510 pub fn grant_named(&mut self, capability: &'static str) {
511 self.grant_from_host(CapabilityName::new(capability));
512 }
513
514 pub fn capabilities(&self) -> &Capabilities {
516 &self.capabilities
517 }
518
519 pub fn with_capabilities<T>(
521 &mut self,
522 capabilities: Capabilities,
523 f: impl FnOnce(&mut Self) -> Result<T>,
524 ) -> Result<T> {
525 let saved = std::mem::replace(&mut self.capabilities, capabilities);
526 let result = f(self);
527 self.capabilities = saved;
528 result
529 }
530
531 pub fn resolve_class(&self, symbol: &Symbol) -> Result<Value> {
533 self.resolve_registered_value(
534 |registry| registry.class_by_symbol(symbol),
535 Error::UnknownClass {
536 class: symbol.clone(),
537 },
538 )
539 }
540
541 pub fn resolve_function(&self, symbol: &Symbol) -> Result<Value> {
543 self.resolve_registered_value(
544 |registry| registry.function_by_symbol(symbol),
545 Error::UnknownFunction {
546 function: symbol.clone(),
547 },
548 )
549 }
550
551 pub fn resolve_macro(&self, symbol: &Symbol) -> Result<Value> {
553 self.resolve_registered_value(
554 |registry| registry.macro_by_symbol(symbol),
555 unknown_symbol(symbol),
556 )
557 }
558
559 pub fn resolve_shape(&self, symbol: &Symbol) -> Result<Value> {
561 self.resolve_registered_value(
562 |registry| registry.shape_by_symbol(symbol),
563 unknown_symbol(symbol),
564 )
565 }
566
567 pub fn resolve_codec(&self, symbol: &Symbol) -> Result<Value> {
569 self.resolve_registered_value(
570 |registry| registry.codec_by_symbol(symbol),
571 unknown_symbol(symbol),
572 )
573 }
574
575 pub fn resolve_number_domain(&self, symbol: &Symbol) -> Result<Value> {
577 self.resolve_registered_value(
578 |registry| registry.number_domain_by_symbol(symbol),
579 unknown_symbol(symbol),
580 )
581 }
582
583 pub fn resolve_value(&self, symbol: &Symbol) -> Result<Value> {
585 self.resolve_registered_value(
586 |registry| registry.value_by_symbol(symbol),
587 unknown_symbol(symbol),
588 )
589 }
590
591 fn resolve_registered_value(
592 &self,
593 lookup: impl FnOnce(&Registry) -> Option<&Value>,
594 not_found: Error,
595 ) -> Result<Value> {
596 lookup(self.registry()).cloned().ok_or(not_found)
597 }
598
599 pub fn call_value(&mut self, value: Value, args: Args) -> Result<Value> {
601 let Some(callable) = value.object().as_callable() else {
602 return Err(Error::TypeMismatch {
603 expected: "callable",
604 found: "non-callable",
605 });
606 };
607 callable.call(self, args)
608 }
609
610 pub fn call_exprs(&mut self, value: Value, args: Vec<crate::expr::Expr>) -> Result<Value> {
612 let Some(callable) = value.object().as_callable() else {
613 return Err(Error::TypeMismatch {
614 expected: "callable",
615 found: "non-callable",
616 });
617 };
618 callable.call_exprs(self, crate::object::RawArgs::new(args))
619 }
620
621 pub fn call_function(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
623 let function = self.resolve_function(symbol)?;
624 self.call_value(function, args)
625 }
626
627 pub fn call_class(&mut self, symbol: &Symbol, args: Args) -> Result<Value> {
629 let class = self.resolve_class(symbol)?;
630 self.call_value(class, args)
631 }
632
633 pub fn read_construct(&mut self, class: &Symbol, args: Vec<Value>) -> Result<Value> {
637 self.require(&read_construct_capability())?;
638 let class_value = self.resolve_class(class)?;
639 let constructor = class_protocol(&class_value)?
640 .read_constructor(self)?
641 .ok_or_else(|| Error::Eval(format!("class {class} has no read constructor")))?;
642 read_constructor_protocol(&constructor)?.construct_read(self, args)
643 }
644
645 pub fn force(&mut self, value: Value, demand: crate::eval::Demand) -> Result<Value> {
647 let eval_policy = self.eval_policy.clone();
648 eval_policy.force(self, value, demand)
649 }
650
651 pub fn eval_expr(&mut self, expr: crate::expr::Expr) -> Result<Value> {
653 let eval_policy = self.eval_policy.clone();
654 eval_policy.eval_expr(self, expr)
655 }
656
657 pub fn symbol_is_bound(&mut self, name: &Symbol) -> bool {
659 self.env().get(name).is_some()
660 || self.resolve_function(name).is_ok()
661 || self.resolve_class(name).is_ok()
662 || self.resolve_shape(name).is_ok()
663 || self.resolve_value(name).is_ok()
664 }
665
666 pub fn resolve_unbound_symbol(&mut self, symbol: Symbol) -> Result<Value> {
668 let eval_policy = self.eval_policy_ref();
669 eval_policy.resolve_unbound_symbol(self, symbol)
670 }
671
672 pub fn resolve_unbound_call(
674 &mut self,
675 operator: Symbol,
676 args: Vec<crate::expr::Expr>,
677 ) -> Result<Value> {
678 let eval_policy = self.eval_policy_ref();
679 eval_policy.resolve_unbound_call(self, operator, args)
680 }
681
682 pub fn require(&self, capability: &CapabilityName) -> Result<()> {
684 if self.capabilities.contains(capability) {
685 Ok(())
686 } else {
687 Err(Error::CapabilityDenied {
688 capability: capability.clone(),
689 })
690 }
691 }
692
693 pub fn require_all(&self, capabilities: &[CapabilityName]) -> Result<()> {
695 for capability in capabilities {
696 self.require(capability)?;
697 }
698 Ok(())
699 }
700}