1#![allow(clippy::result_unit_err)]
5#![allow(clippy::assigning_clones)]
6pub mod compare;
7pub mod eval;
8pub mod generalize;
9pub mod hint;
10pub mod initialize;
11pub mod inquire;
12pub mod instantiate;
13pub mod instantiate_spec;
14pub mod register;
15pub mod test;
16pub mod unify;
17
18use std::fmt;
19use std::mem;
20use std::ops::{Deref, DerefMut};
21use std::option::Option; use std::path::Path;
23
24use erg_common::config::ErgConfig;
25use erg_common::consts::DEBUG_MODE;
26use erg_common::consts::ERG_MODE;
27use erg_common::consts::PYTHON_MODE;
28use erg_common::dict::Dict;
29use erg_common::error::Location;
30use erg_common::impl_display_from_debug;
31use erg_common::pathutil::NormalizedPathBuf;
32use erg_common::traits::{Locational, Stream};
33use erg_common::Str;
34use erg_common::{fmt_option, fn_name, get_hash, log};
35
36use ast::{DefId, DefKind, VarName};
37use erg_parser::ast;
38use erg_parser::ast::Def;
39use erg_parser::ast::Signature;
40use erg_parser::token::Token;
41
42use crate::context::instantiate::TyVarCache;
43use crate::context::instantiate_spec::ConstTemplate;
44use crate::error::{TyCheckError, TyCheckErrors};
45use crate::hir::Identifier;
46use crate::module::SharedModuleGraph;
47use crate::module::{
48 SharedCompilerResource, SharedModuleCache, SharedModuleIndex, SharedPromises, SharedTraitImpls,
49};
50use crate::ty::value::ValueObj;
51use crate::ty::GuardType;
52use crate::ty::ParamTy;
53use crate::ty::{Predicate, Type, Visibility, VisibilityModifier};
54use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
55use Type::*;
56
57pub trait ContextProvider {
59 fn dir(&self) -> Dict<&VarName, &VarInfo>;
60 fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context>;
61 fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)>;
62 fn has(&self, name: &str) -> bool {
63 self.get_var_info(name).is_some()
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68pub enum ControlKind {
69 If,
70 While,
71 For,
72 Match,
73 Try,
74 With,
75 Discard,
76 Assert,
77}
78
79impl fmt::Display for ControlKind {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match self {
82 Self::If => write!(f, "if"),
83 Self::While => write!(f, "while"),
84 Self::For => write!(f, "for"),
85 Self::Match => write!(f, "match"),
86 Self::Try => write!(f, "try"),
87 Self::With => write!(f, "with"),
88 Self::Discard => write!(f, "discard"),
89 Self::Assert => write!(f, "assert"),
90 }
91 }
92}
93
94impl TryFrom<&str> for ControlKind {
95 type Error = ();
96 fn try_from(s: &str) -> Result<Self, Self::Error> {
97 match s {
98 "if" | "if!" => Ok(ControlKind::If),
99 "while!" => Ok(ControlKind::While),
100 "while" if PYTHON_MODE => Ok(ControlKind::While),
101 "for" | "for!" => Ok(ControlKind::For),
102 "match" | "match!" => Ok(ControlKind::Match),
103 "try" | "try!" => Ok(ControlKind::Try),
104 "with" | "with!" => Ok(ControlKind::With),
105 "discard" => Ok(ControlKind::Discard),
106 "assert" => Ok(ControlKind::Assert),
107 _ => Err(()),
108 }
109 }
110}
111
112impl ControlKind {
113 pub const fn is_if(&self) -> bool {
114 matches!(self, Self::If)
115 }
116 pub const fn is_conditional(&self) -> bool {
118 matches!(self, Self::If | Self::While)
119 }
120 pub const fn makes_scope(&self) -> bool {
121 !matches!(self, Self::Assert)
122 }
123}
124
125#[derive(Debug, Clone)]
126pub struct TraitImpl {
127 pub sub_type: Type,
128 pub sup_trait: Type,
129 pub declared_in: Option<NormalizedPathBuf>,
130}
131
132impl PartialEq for TraitImpl {
133 fn eq(&self, other: &Self) -> bool {
134 self.sub_type == other.sub_type && self.sup_trait == other.sup_trait
135 }
136}
137
138impl Eq for TraitImpl {}
139
140impl std::hash::Hash for TraitImpl {
141 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
142 self.sub_type.hash(state);
143 self.sup_trait.hash(state);
144 }
145}
146
147impl std::fmt::Display for TraitImpl {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(f, "TraitImpl{{{} <: {}}}", self.sub_type, self.sup_trait)
150 }
151}
152
153impl TraitImpl {
154 pub const fn new(
155 sub_type: Type,
156 sup_trait: Type,
157 declared_in: Option<NormalizedPathBuf>,
158 ) -> Self {
159 Self {
160 sub_type,
161 sup_trait,
162 declared_in,
163 }
164 }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
168pub enum ClassDefType {
169 Simple(Type),
170 ImplTrait { class: Type, impl_trait: Type },
171}
172
173impl std::fmt::Display for ClassDefType {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 match self {
176 ClassDefType::Simple(ty) => write!(f, "{ty}"),
177 ClassDefType::ImplTrait { class, impl_trait } => {
178 write!(f, "{class}|<: {impl_trait}|")
179 }
180 }
181 }
182}
183
184impl ClassDefType {
185 pub const fn impl_trait(class: Type, impl_trait: Type) -> Self {
186 ClassDefType::ImplTrait { class, impl_trait }
187 }
188
189 pub fn get_class(&self) -> &Type {
190 match self {
191 ClassDefType::Simple(class) => class,
192 ClassDefType::ImplTrait { class, .. } => class,
193 }
194 }
195
196 pub fn get_impl_trait(&self) -> Option<&Type> {
197 match self {
198 ClassDefType::Simple(_) => None,
199 ClassDefType::ImplTrait { impl_trait, .. } => Some(impl_trait),
200 }
201 }
202
203 pub fn is_class_of(&self, t: &Type) -> bool {
204 match self {
205 ClassDefType::Simple(class) => class == t,
206 ClassDefType::ImplTrait { class, .. } => class == t,
207 }
208 }
209
210 pub fn is_impl_of(&self, trait_: &Type) -> bool {
211 match self {
212 ClassDefType::ImplTrait { impl_trait, .. } => impl_trait == trait_,
213 _ => false,
214 }
215 }
216}
217
218#[derive(Debug, Clone)]
219pub struct MethodContext {
220 pub id: DefId,
221 pub typ: ClassDefType,
222 pub ctx: Context,
223}
224
225impl Deref for MethodContext {
226 type Target = Context;
227
228 fn deref(&self) -> &Self::Target {
229 &self.ctx
230 }
231}
232
233impl DerefMut for MethodContext {
234 fn deref_mut(&mut self) -> &mut Self::Target {
235 &mut self.ctx
236 }
237}
238
239impl MethodContext {
240 pub const fn new(id: DefId, typ: ClassDefType, ctx: Context) -> Self {
241 Self { id, typ, ctx }
242 }
243}
244
245#[derive(Debug, Clone, Default)]
246pub struct TypeContext {
247 pub typ: Type,
248 pub ctx: Context,
249}
250
251impl Deref for TypeContext {
252 type Target = Context;
253
254 fn deref(&self) -> &Self::Target {
255 &self.ctx
256 }
257}
258
259impl DerefMut for TypeContext {
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 &mut self.ctx
262 }
263}
264
265impl TypeContext {
266 pub const fn new(typ: Type, ctx: Context) -> Self {
267 Self { typ, ctx }
268 }
269
270 pub(crate) fn get_class_member<'c>(
273 &'c self,
274 name: &VarName,
275 ctx: &'c Context,
276 ) -> Option<&'c VarInfo> {
277 self.get_current_scope_attr(name).or_else(|| {
278 let sups = ctx.get_nominal_super_type_ctxs(&self.typ)?;
279 for sup in sups {
280 if let Some(vi) = sup.get_current_scope_attr(name) {
281 return Some(vi);
282 }
283 }
284 None
285 })
286 }
287
288 pub(crate) fn get_trait_impl_types(&self, trait_: &Type) -> Option<(&Type, &Type)> {
289 self.ctx.methods_list.iter().find_map(|mc| match &mc.typ {
290 ClassDefType::ImplTrait { class, impl_trait }
291 if impl_trait.qual_name() == trait_.qual_name() =>
292 {
293 Some((class, impl_trait))
294 }
295 _ => None,
296 })
297 }
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
301pub enum DefaultInfo {
302 NonDefault, WithDefault,
304}
305
306impl_display_from_debug!(DefaultInfo);
307
308impl DefaultInfo {
309 pub const fn has_default(&self) -> bool {
310 matches!(self, DefaultInfo::WithDefault)
311 }
312}
313
314#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
315pub enum Variance {
316 Covariant,
318 Contravariant,
320 #[default]
322 Invariant,
323}
324
325impl_display_from_debug!(Variance);
326
327impl std::ops::Mul for Variance {
328 type Output = Self;
329
330 fn mul(self, rhs: Self) -> Self::Output {
331 match (self, rhs) {
332 (Variance::Covariant, Variance::Covariant)
333 | (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
334 (Variance::Covariant, Variance::Contravariant)
335 | (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
336 _ => Variance::Invariant,
337 }
338 }
339}
340
341impl Variance {
342 pub const fn is_invariant(&self) -> bool {
343 matches!(self, Variance::Invariant)
344 }
345}
346
347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
348pub struct ParamSpec {
349 pub(crate) name: Option<Str>,
350 pub(crate) t: Type,
352 pub is_var_params: bool,
353 pub default_info: DefaultInfo,
354 loc: AbsLocation,
355}
356
357impl ParamSpec {
358 pub fn new<S: Into<Str>>(
359 name: Option<S>,
360 t: Type,
361 is_var_params: bool,
362 default: DefaultInfo,
363 loc: AbsLocation,
364 ) -> Self {
365 Self {
366 name: name.map(|s| s.into()),
367 t,
368 is_var_params,
369 default_info: default,
370 loc,
371 }
372 }
373
374 pub fn named<S: Into<Str>>(
375 name: S,
376 t: Type,
377 is_var_params: bool,
378 default: DefaultInfo,
379 ) -> Self {
380 Self::new(
381 Some(name),
382 t,
383 is_var_params,
384 default,
385 AbsLocation::unknown(),
386 )
387 }
388
389 pub fn named_nd<S: Into<Str>>(name: S, t: Type) -> Self {
390 Self::new(
391 Some(name),
392 t,
393 false,
394 DefaultInfo::NonDefault,
395 AbsLocation::unknown(),
396 )
397 }
398
399 pub fn default<S: Into<Str>>(name: S, t: Type) -> Self {
400 Self::new(
401 Some(name),
402 t,
403 false,
404 DefaultInfo::WithDefault,
405 AbsLocation::unknown(),
406 )
407 }
408
409 pub fn t<S: Into<Str>>(name: S, is_var_params: bool, default: DefaultInfo) -> Self {
410 Self::new(
411 Some(name),
412 Type,
413 is_var_params,
414 default,
415 AbsLocation::unknown(),
416 )
417 }
418
419 pub fn t_nd<S: Into<Str>>(name: S) -> Self {
420 Self::new(
421 Some(name),
422 Type,
423 false,
424 DefaultInfo::NonDefault,
425 AbsLocation::unknown(),
426 )
427 }
428
429 pub fn has_default(&self) -> bool {
430 self.default_info.has_default()
431 }
432}
433
434impl From<&ParamSpec> for ParamTy {
435 fn from(param: &ParamSpec) -> Self {
436 if let Some(name) = ¶m.name {
437 ParamTy::kw(name.clone(), param.t.clone())
438 } else {
439 ParamTy::Pos(param.t.clone())
440 }
441 }
442}
443
444#[derive(Debug, Clone, PartialEq, Eq, Hash)]
445pub enum ContextKind {
446 LambdaFunc(Option<ControlKind>),
447 LambdaProc(Option<ControlKind>),
448 Func,
449 Proc,
450 Class,
451 MethodDefs(Option<Type>), PatchMethodDefs(Type),
453 Trait,
454 StructuralTrait,
455 Patch(Type),
456 StructuralPatch(Type),
457 GluePatch(Box<TraitImpl>), Module,
460 Instant,
461 Record,
462 Dummy,
463}
464
465impl From<&Def> for ContextKind {
466 fn from(def: &Def) -> Self {
467 match def.def_kind() {
468 DefKind::Class | DefKind::Inherit => Self::Class,
469 DefKind::Trait | DefKind::Subsume => Self::Trait,
470 DefKind::StructuralTrait => Self::StructuralTrait,
471 DefKind::ErgImport | DefKind::PyImport | DefKind::RsImport | DefKind::InlineModule => {
472 Self::Module
473 }
474 DefKind::Other => {
475 if let Signature::Subr(subr) = &def.sig {
476 if subr.ident.is_procedural() {
477 Self::Proc
478 } else {
479 Self::Func
480 }
481 } else {
482 Self::Instant
483 }
484 }
485 DefKind::Patch => Self::Instant,
487 }
488 }
489}
490
491impl fmt::Display for ContextKind {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 match self {
494 Self::LambdaFunc(kind) => write!(f, "LambdaFunc({})", fmt_option!(kind)),
495 Self::LambdaProc(kind) => write!(f, "LambdaProc({})", fmt_option!(kind)),
496 Self::Func => write!(f, "Func"),
497 Self::Proc => write!(f, "Proc"),
498 Self::Class => write!(f, "Class"),
499 Self::MethodDefs(trait_) => write!(f, "MethodDefs({})", fmt_option!(trait_)),
500 Self::PatchMethodDefs(type_) => write!(f, "PatchMethodDefs({type_})"),
501 Self::Trait => write!(f, "Trait"),
502 Self::StructuralTrait => write!(f, "StructuralTrait"),
503 Self::Patch(type_) => write!(f, "Patch({type_})"),
504 Self::StructuralPatch(type_) => write!(f, "StructuralPatch({type_})"),
505 Self::GluePatch(type_) => write!(f, "GluePatch({type_})"),
506 Self::Module => write!(f, "Module"),
507 Self::Instant => write!(f, "Instant"),
508 Self::Record => write!(f, "Record"),
509 Self::Dummy => write!(f, "Dummy"),
510 }
511 }
512}
513
514impl ContextKind {
515 pub const fn is_method_def(&self) -> bool {
516 matches!(self, Self::MethodDefs(_))
517 }
518
519 pub const fn is_trait_impl(&self) -> bool {
520 matches!(self, Self::MethodDefs(Some(_)))
521 }
522
523 pub const fn is_type(&self) -> bool {
524 matches!(self, Self::Class | Self::Trait | Self::StructuralTrait)
525 }
526
527 pub const fn is_subr(&self) -> bool {
528 matches!(
529 self,
530 Self::Func | Self::Proc | Self::LambdaFunc(_) | Self::LambdaProc(_)
531 )
532 }
533
534 pub const fn is_class(&self) -> bool {
535 matches!(self, Self::Class)
536 }
537
538 pub const fn is_trait(&self) -> bool {
539 matches!(self, Self::Trait | Self::StructuralTrait)
540 }
541
542 pub const fn is_patch(&self) -> bool {
543 matches!(self, Self::Patch(_) | Self::GluePatch(_))
544 }
545
546 pub const fn is_module(&self) -> bool {
547 matches!(self, Self::Module)
548 }
549
550 pub const fn is_instant(&self) -> bool {
551 matches!(self, Self::Instant)
552 }
553
554 pub const fn control_kind(&self) -> Option<ControlKind> {
555 match self {
556 Self::LambdaFunc(kind) | Self::LambdaProc(kind) => *kind,
557 _ => None,
558 }
559 }
560}
561
562#[derive(Debug, Clone, Copy, PartialEq, Eq)]
569pub enum RegistrationMode {
570 PreRegister,
571 Normal,
572}
573
574impl RegistrationMode {
575 pub const fn is_preregister(&self) -> bool {
576 matches!(self, Self::PreRegister)
577 }
578 pub const fn is_normal(&self) -> bool {
579 matches!(self, Self::Normal)
580 }
581}
582
583#[derive(Debug, Clone, PartialEq, Eq, Hash)]
584pub struct MethodPair {
585 pub definition_type: Type,
586 pub method_info: VarInfo,
587}
588
589impl fmt::Display for MethodPair {
590 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
591 write!(
592 f,
593 "{{ def: {} info: {} }}",
594 self.definition_type, self.method_info
595 )
596 }
597}
598
599impl MethodPair {
600 pub const fn new(definition_type: Type, method_info: VarInfo) -> Self {
601 Self {
602 definition_type,
603 method_info,
604 }
605 }
606}
607
608#[derive(Debug, Clone)]
612pub struct Context {
613 pub name: Str,
614 pub kind: ContextKind,
615 pub(crate) cfg: ErgConfig,
616 pub(crate) preds: Vec<Predicate>,
617 pub(crate) outer: Option<Box<Context>>,
619 pub(crate) const_param_defaults: Dict<Str, Vec<ConstTemplate>>,
621 pub(crate) super_classes: Vec<Type>, pub(crate) super_traits: Vec<Type>, pub(crate) methods_list: Vec<MethodContext>,
628 pub(crate) method_to_traits: Dict<Str, Vec<MethodPair>>,
631 pub(crate) method_to_classes: Dict<Str, Vec<MethodPair>>,
632 pub(crate) method_impl_patches: Dict<VarName, Vec<VarName>>,
637 pub(crate) decls: Dict<VarName, VarInfo>,
639 pub(crate) future_defined_locals: Dict<VarName, VarInfo>,
641 pub(crate) deleted_locals: Dict<VarName, VarInfo>,
642 pub(crate) params: Vec<(Option<VarName>, VarInfo)>,
651 pub(crate) params_spec: Vec<ParamSpec>,
652 pub(crate) locals: Dict<VarName, VarInfo>,
653 pub(crate) consts: Dict<VarName, ValueObj>,
654 pub(crate) mono_types: Dict<VarName, TypeContext>,
656 pub(crate) poly_types: Dict<VarName, TypeContext>,
660 pub(crate) patches: Dict<VarName, Context>,
663 pub(crate) shared: Option<SharedCompilerResource>,
664 pub(crate) tv_cache: Option<TyVarCache>,
665 pub(crate) higher_order_caller: Vec<Str>,
666 pub(crate) guards: Vec<GuardType>,
667 pub(crate) erg_to_py_names: Dict<Str, Str>,
668 pub(crate) captured_names: Vec<Identifier>,
669 pub(crate) level: usize,
670}
671
672impl Default for Context {
673 #[inline]
674 fn default() -> Self {
675 Self::default_with_name("<dummy>")
676 }
677}
678
679impl fmt::Display for Context {
680 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681 f.debug_struct("Context")
682 .field("name", &self.name)
683 .field("preds", &self.preds)
684 .field("params", &self.params)
685 .field("decls", &self.decls)
686 .field("locals", &self.params)
687 .field("consts", &self.consts)
688 .field("mono_types", &self.mono_types)
689 .field("poly_types", &self.poly_types)
690 .field("patches", &self.patches)
691 .finish()
693 }
694}
695
696impl ContextProvider for Context {
697 fn dir(&self) -> Dict<&VarName, &VarInfo> {
698 let mut vars = self.type_dir(self);
699 if let Some(outer) = self.get_outer_scope() {
700 vars.guaranteed_extend(outer.dir());
701 } else if let Some(builtins) = self.get_builtins_not_self() {
702 vars.guaranteed_extend(builtins.locals.iter());
703 }
704 vars
705 }
706
707 fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
708 self.get_mod(receiver_name)
709 .or_else(|| self.rec_local_get_type(receiver_name).map(|ctx| &ctx.ctx))
710 .or_else(|| {
711 let (_, vi) = self.get_var_info(receiver_name)?;
712 self.get_nominal_type_ctx(&vi.t).map(|ctx| &ctx.ctx)
713 })
714 }
715
716 fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
718 self.get_var_kv(name).or_else(|| {
719 self.get_builtins_not_self()
720 .and_then(|builtin| builtin.get_var_kv(name))
721 })
722 }
723}
724
725impl Context {
726 pub fn dir(&self) -> Dict<&VarName, &VarInfo> {
727 ContextProvider::dir(self)
728 }
729
730 pub fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
731 ContextProvider::get_receiver_ctx(self, receiver_name)
732 }
733
734 pub fn get_receiver_ctxs(&self, receiver_name: &str) -> Vec<&Context> {
735 let mut ctxs = vec![];
736 if let Some(receiver_ctx) = self.get_receiver_ctx(receiver_name) {
737 ctxs.push(receiver_ctx);
738 ctxs.extend(
739 receiver_ctx
740 .super_classes
741 .iter()
742 .flat_map(|t| self.get_nominal_type_ctx(t).map(|ctx| &ctx.ctx)),
743 );
744 }
745 ctxs
746 }
747
748 pub fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
749 ContextProvider::get_var_info(self, name)
750 }
751
752 pub fn has(&self, name: &str) -> bool {
753 ContextProvider::has(self, name)
754 }
755
756 pub fn get_type_info(&self, typ: &Type) -> Option<(&VarName, &VarInfo)> {
758 let namespace = typ.namespace();
759 let ctx = self.get_namespace(&namespace)?;
760 ctx.get_var_info(&typ.local_name())
761 }
762
763 pub fn unregister(&mut self, name: &str) -> Option<VarInfo> {
764 self.mono_types.remove(name);
765 self.poly_types.remove(name);
766 self.patches.remove(name);
767 self.erg_to_py_names.remove(name);
768 self.locals
769 .remove(name)
770 .or_else(|| self.locals.remove(name))
771 }
772}
773
774impl Context {
775 #[allow(clippy::too_many_arguments)]
776 #[inline]
777 pub fn new(
778 name: Str,
779 cfg: ErgConfig,
780 kind: ContextKind,
781 params: Vec<ParamSpec>,
782 outer: Option<Context>,
783 shared: Option<SharedCompilerResource>,
784 level: usize,
785 ) -> Self {
786 Self::with_capacity(name, cfg, kind, params, outer, shared, 0, level)
787 }
788
789 pub fn default_with_name(name: &'static str) -> Self {
790 Self::new(
791 name.into(),
792 ErgConfig::default(),
793 ContextKind::Dummy,
794 vec![],
795 None,
796 None,
797 Self::TOP_LEVEL,
798 )
799 }
800
801 #[allow(clippy::too_many_arguments)]
802 pub fn with_capacity(
803 name: Str,
804 cfg: ErgConfig,
805 kind: ContextKind,
806 params: Vec<ParamSpec>,
807 outer: Option<Context>,
808 shared: Option<SharedCompilerResource>,
809 capacity: usize,
810 level: usize,
811 ) -> Self {
812 let mut params_ = Vec::new();
813 for param in params.clone().into_iter() {
814 let id = DefId(get_hash(&(&name, ¶m)));
815 if let Some(name) = param.name {
816 let var_kind = VarKind::parameter(id, param.is_var_params, param.default_info);
817 let muty = Mutability::from(&name[..]);
818 let vi = VarInfo::new(
819 param.t,
820 muty,
821 Visibility::private(&name),
822 var_kind,
823 None,
824 kind.clone(),
825 None,
826 param.loc,
827 );
828 params_.push((Some(VarName::new(Token::symbol(&name))), vi));
829 } else {
830 let var_kind = VarKind::parameter(id, param.is_var_params, param.default_info);
831 let muty = Mutability::Immutable;
832 let vi = VarInfo::new(
833 param.t,
834 muty,
835 Visibility::private(name.clone()),
836 var_kind,
837 None,
838 kind.clone(),
839 None,
840 param.loc,
841 );
842 params_.push((None, vi));
843 }
844 }
845 Self {
846 name,
847 cfg,
848 kind,
849 preds: vec![],
850 outer: outer.map(Box::new),
851 super_classes: vec![],
852 super_traits: vec![],
853 methods_list: vec![],
854 const_param_defaults: Dict::default(),
855 method_to_traits: Dict::default(),
856 method_to_classes: Dict::default(),
857 method_impl_patches: Dict::default(),
858 params: params_,
859 params_spec: params,
860 decls: Dict::default(),
861 future_defined_locals: Dict::default(),
862 deleted_locals: Dict::default(),
863 locals: Dict::with_capacity(capacity),
864 consts: Dict::default(),
865 mono_types: Dict::default(),
866 poly_types: Dict::default(),
867 shared,
868 tv_cache: None,
869 patches: Dict::default(),
870 higher_order_caller: vec![],
871 guards: vec![],
872 erg_to_py_names: Dict::default(),
873 captured_names: vec![],
874 level,
875 }
876 }
877
878 #[inline]
879 pub fn mono(
880 name: Str,
881 cfg: ErgConfig,
882 kind: ContextKind,
883 outer: Option<Context>,
884 shared: Option<SharedCompilerResource>,
885 level: usize,
886 ) -> Self {
887 Self::new(name, cfg, kind, vec![], outer, shared, level)
888 }
889
890 #[allow(clippy::too_many_arguments)]
891 #[inline]
892 pub fn poly(
893 name: Str,
894 cfg: ErgConfig,
895 kind: ContextKind,
896 params: Vec<ParamSpec>,
897 outer: Option<Context>,
898 shared: Option<SharedCompilerResource>,
899 capacity: usize,
900 level: usize,
901 ) -> Self {
902 Self::with_capacity(name, cfg, kind, params, outer, shared, capacity, level)
903 }
904
905 pub fn poly_trait<S: Into<Str>>(
906 name: S,
907 params: Vec<ParamSpec>,
908 cfg: ErgConfig,
909 shared: Option<SharedCompilerResource>,
910 capacity: usize,
911 level: usize,
912 ) -> Self {
913 let name = name.into();
914 Self::poly(
915 name,
916 cfg,
917 ContextKind::Trait,
918 params,
919 None,
920 shared,
921 capacity,
922 level,
923 )
924 }
925
926 #[inline]
927 pub fn builtin_poly_trait<S: Into<Str>>(
928 name: S,
929 params: Vec<ParamSpec>,
930 capacity: usize,
931 ) -> Self {
932 Self::poly_trait(
933 name,
934 params,
935 ErgConfig::default(),
936 None,
937 capacity,
938 Self::TOP_LEVEL,
939 )
940 }
941
942 pub fn poly_class<S: Into<Str>>(
943 name: S,
944 params: Vec<ParamSpec>,
945 cfg: ErgConfig,
946 shared: Option<SharedCompilerResource>,
947 capacity: usize,
948 level: usize,
949 ) -> Self {
950 let name = name.into();
951 Self::poly(
952 name,
953 cfg,
954 ContextKind::Class,
955 params,
956 None,
957 shared,
958 capacity,
959 level,
960 )
961 }
962
963 #[inline]
964 pub fn builtin_poly_class<S: Into<Str>>(
965 name: S,
966 params: Vec<ParamSpec>,
967 capacity: usize,
968 ) -> Self {
969 Self::poly_class(
970 name,
971 params,
972 ErgConfig::default(),
973 None,
974 capacity,
975 Self::TOP_LEVEL,
976 )
977 }
978
979 #[allow(clippy::too_many_arguments)]
980 pub fn poly_patch<S: Into<Str>>(
981 name: S,
982 base: Type,
983 params: Vec<ParamSpec>,
984 cfg: ErgConfig,
985 shared: Option<SharedCompilerResource>,
986 capacity: usize,
987 level: usize,
988 ) -> Self {
989 let name = name.into();
990 Self::poly(
991 name,
992 cfg,
993 ContextKind::Patch(base),
994 params,
995 None,
996 shared,
997 capacity,
998 level,
999 )
1000 }
1001
1002 #[inline]
1003 pub fn mono_trait<S: Into<Str>>(
1004 name: S,
1005 cfg: ErgConfig,
1006 shared: Option<SharedCompilerResource>,
1007 capacity: usize,
1008 level: usize,
1009 ) -> Self {
1010 Self::poly_trait(name, vec![], cfg, shared, capacity, level)
1011 }
1012
1013 #[inline]
1014 pub fn builtin_mono_trait<S: Into<Str>>(name: S, capacity: usize) -> Self {
1015 Self::mono_trait(name, ErgConfig::default(), None, capacity, Self::TOP_LEVEL)
1016 }
1017
1018 #[inline]
1019 pub fn mono_class<S: Into<Str>>(
1020 name: S,
1021 cfg: ErgConfig,
1022 shared: Option<SharedCompilerResource>,
1023 capacity: usize,
1024 level: usize,
1025 ) -> Self {
1026 Self::poly_class(name, vec![], cfg, shared, capacity, level)
1027 }
1028
1029 #[inline]
1030 pub fn builtin_mono_class<S: Into<Str>>(name: S, capacity: usize) -> Self {
1031 Self::mono_class(name, ErgConfig::default(), None, capacity, Self::TOP_LEVEL)
1032 }
1033
1034 #[inline]
1035 pub fn mono_patch<S: Into<Str>>(
1036 name: S,
1037 base: Type,
1038 cfg: ErgConfig,
1039 shared: Option<SharedCompilerResource>,
1040 capacity: usize,
1041 level: usize,
1042 ) -> Self {
1043 Self::poly_patch(name, base, vec![], cfg, shared, capacity, level)
1044 }
1045
1046 #[inline]
1047 pub fn methods(
1048 impl_trait: Option<Type>,
1049 cfg: ErgConfig,
1050 shared: Option<SharedCompilerResource>,
1051 capacity: usize,
1052 level: usize,
1053 ) -> Self {
1054 let name = if let Some(tr) = &impl_trait {
1055 tr.local_name()
1056 } else {
1057 Str::ever("Methods")
1058 };
1059 Self::with_capacity(
1060 name,
1061 cfg,
1062 ContextKind::MethodDefs(impl_trait),
1063 vec![],
1064 None,
1065 shared,
1066 capacity,
1067 level,
1068 )
1069 }
1070
1071 #[inline]
1072 pub fn builtin_methods(impl_trait: Option<Type>, capacity: usize) -> Self {
1073 Self::methods(
1074 impl_trait,
1075 ErgConfig::default(),
1076 None,
1077 capacity,
1078 Self::TOP_LEVEL,
1079 )
1080 }
1081
1082 #[allow(clippy::too_many_arguments)]
1083 #[inline]
1084 pub fn poly_glue_patch<S: Into<Str>>(
1085 name: S,
1086 base: Type,
1087 impls: Type,
1088 params: Vec<ParamSpec>,
1089 cfg: ErgConfig,
1090 shared: Option<SharedCompilerResource>,
1091 capacity: usize,
1092 level: usize,
1093 ) -> Self {
1094 Self::poly(
1095 name.into(),
1096 cfg,
1097 ContextKind::GluePatch(Box::new(TraitImpl::new(base, impls, None))),
1098 params,
1099 None,
1100 shared,
1101 capacity,
1102 level,
1103 )
1104 }
1105
1106 #[inline]
1107 pub fn builtin_poly_glue_patch<S: Into<Str>>(
1108 name: S,
1109 base: Type,
1110 impls: Type,
1111 params: Vec<ParamSpec>,
1112 capacity: usize,
1113 ) -> Self {
1114 Self::poly_glue_patch(
1115 name,
1116 base,
1117 impls,
1118 params,
1119 ErgConfig::default(),
1120 None,
1121 capacity,
1122 Self::TOP_LEVEL,
1123 )
1124 }
1125
1126 #[inline]
1127 pub fn builtin_patch<S: Into<Str>>(
1128 name: S,
1129 impls: Type,
1130 params: Vec<ParamSpec>,
1131 capacity: usize,
1132 ) -> Self {
1133 Self::poly(
1134 name.into(),
1135 ErgConfig::default(),
1136 ContextKind::Patch(impls),
1137 params,
1138 None,
1139 None,
1140 capacity,
1141 Self::TOP_LEVEL,
1142 )
1143 }
1144
1145 #[inline]
1146 pub fn module(
1147 name: Str,
1148 cfg: ErgConfig,
1149 shared: Option<SharedCompilerResource>,
1150 capacity: usize,
1151 ) -> Self {
1152 Self::with_capacity(
1153 name,
1154 cfg,
1155 ContextKind::Module,
1156 vec![],
1157 None,
1158 shared,
1159 capacity,
1160 Self::TOP_LEVEL,
1161 )
1162 }
1163
1164 #[inline]
1165 pub fn builtin_module<S: Into<Str>>(
1166 name: S,
1167 cfg: ErgConfig,
1168 shared: SharedCompilerResource,
1169 capacity: usize,
1170 ) -> Self {
1171 Self::module(name.into(), cfg, Some(shared), capacity)
1172 }
1173
1174 #[inline]
1175 pub fn instant(
1176 name: Str,
1177 cfg: ErgConfig,
1178 capacity: usize,
1179 shared: Option<SharedCompilerResource>,
1180 outer: Context,
1181 ) -> Self {
1182 Self::with_capacity(
1183 name,
1184 cfg,
1185 ContextKind::Instant,
1186 vec![],
1187 Some(outer),
1188 shared,
1189 capacity,
1190 Self::TOP_LEVEL,
1191 )
1192 }
1193
1194 pub(crate) fn module_path(&self) -> &Path {
1195 self.cfg.input.path()
1196 }
1197
1198 pub(crate) fn absolutize(&self, loc: Location) -> AbsLocation {
1199 AbsLocation::new(Some(NormalizedPathBuf::from(self.module_path())), loc)
1200 }
1201
1202 #[inline]
1203 pub fn caused_by(&self) -> String {
1204 String::from(&self.name[..])
1205 }
1206
1207 pub(crate) fn get_outer(&self) -> Option<&Context> {
1209 self.outer.as_ref().map(|x| x.as_ref())
1210 }
1211
1212 pub(crate) fn get_outer_scope(&self) -> Option<&Context> {
1214 let outer = self.get_outer()?;
1215 if outer.name != "<builtins>" && outer.kind.is_module() && self.kind.is_module() {
1216 None
1217 } else {
1218 Some(outer)
1219 }
1220 }
1221
1222 pub(crate) fn get_outer_scope_or_builtins(&self) -> Option<&Context> {
1223 self.get_outer_scope()
1224 .or_else(|| self.get_builtins_not_self())
1225 }
1226
1227 pub(crate) fn get_mut_outer(&mut self) -> Option<&mut Context> {
1228 self.outer.as_mut().map(|x| x.as_mut())
1229 }
1230
1231 pub(crate) fn impl_of(&self) -> Option<Type> {
1232 if let ContextKind::MethodDefs(Some(tr)) = &self.kind {
1233 Some(tr.clone())
1234 } else {
1235 None
1236 }
1237 }
1238
1239 pub fn is_empty(&self) -> bool {
1240 let default_locals = if ERG_MODE { 4 } else { 3 };
1241 self.super_classes.is_empty()
1242 && self.super_traits.is_empty()
1243 && self.methods_list.is_empty()
1244 && self.const_param_defaults.is_empty()
1245 && self.method_to_traits.is_empty()
1246 && self.method_to_classes.is_empty()
1247 && self.method_impl_patches.is_empty()
1248 && self.params.is_empty()
1249 && self.params_spec.is_empty()
1250 && self.decls.is_empty()
1251 && self.future_defined_locals.is_empty()
1252 && self.deleted_locals.is_empty()
1253 && self.consts.is_empty()
1254 && self.mono_types.is_empty()
1255 && self.poly_types.is_empty()
1256 && self.patches.is_empty()
1257 && self.locals.len() <= default_locals
1258 }
1259
1260 pub(crate) fn path(&self) -> Str {
1261 if self.kind == ContextKind::Module {
1263 self.name.replace(".__init__", "").into()
1264 } else if let Some(outer) = self.get_outer() {
1265 outer.path()
1266 } else {
1267 self.name.replace(".__init__", "").into()
1268 }
1269 }
1270
1271 pub(crate) fn get_builtins_not_self(&self) -> Option<&Context> {
1274 if &self.path()[..] != "<builtins>" {
1275 self.get_builtins()
1276 } else {
1277 None
1278 }
1279 }
1280
1281 pub(crate) fn get_builtins(&self) -> Option<&Context> {
1283 self.shared
1285 .as_ref()
1286 .map(|shared| shared.mod_cache.raw_ref_builtins_ctx().unwrap())
1287 .map(|mod_ctx| &mod_ctx.context)
1288 }
1289
1290 pub(crate) fn get_module(&self) -> Option<&Context> {
1291 self.get_outer()
1292 .and_then(|outer| {
1293 if outer.kind == ContextKind::Module {
1294 Some(outer)
1295 } else {
1296 outer.get_module()
1297 }
1298 })
1299 .or_else(|| {
1300 if self.kind == ContextKind::Module {
1301 Some(self)
1302 } else {
1303 None
1304 }
1305 })
1306 }
1307
1308 pub(crate) fn get_module_from_stack(&self, path: &NormalizedPathBuf) -> Option<&Context> {
1309 if self.kind == ContextKind::Module && &NormalizedPathBuf::from(self.module_path()) == path
1310 {
1311 return Some(self);
1312 }
1313 self.get_outer()
1314 .and_then(|outer| outer.get_module_from_stack(path))
1315 }
1316
1317 pub fn initialize(&mut self) {
1320 let mut shared = mem::take(&mut self.shared);
1321 if let Some(mod_cache) = shared.as_mut().map(|s| &mut s.mod_cache) {
1322 mod_cache.initialize();
1323 }
1324 if let Some(py_mod_cache) = shared.as_mut().map(|s| &mut s.py_mod_cache) {
1325 py_mod_cache.initialize();
1326 }
1327 *self = Self::new(
1328 self.name.clone(),
1329 self.cfg.clone(),
1330 self.kind.clone(),
1331 vec![],
1332 None,
1333 shared,
1334 self.level,
1335 );
1336 }
1337
1338 pub(crate) fn grow(
1339 &mut self,
1340 name: &str,
1341 kind: ContextKind,
1342 vis: VisibilityModifier,
1343 tv_cache: Option<TyVarCache>,
1344 ) {
1345 let name = if kind.is_module() {
1346 name.into()
1347 } else if vis.is_public() {
1348 format!("{parent}.{name}", parent = self.name)
1349 } else {
1350 format!("{parent}::{name}", parent = self.name)
1351 };
1352 log!(info "{}: current namespace: {name}", fn_name!());
1353 self.outer = Some(Box::new(mem::take(self)));
1354 self.cfg = self.get_outer().unwrap().cfg.clone();
1356 self.shared = self.get_outer().unwrap().shared.clone();
1357 self.higher_order_caller = self.get_outer().unwrap().higher_order_caller.clone();
1358 self.tv_cache = tv_cache;
1359 self.name = name.into();
1360 self.kind = kind;
1361 }
1362
1363 pub(crate) fn replace(&mut self, new: Self) {
1364 let old = mem::take(self);
1365 *self = new;
1366 self.outer = Some(Box::new(old));
1367 self.cfg = self.get_outer().unwrap().cfg.clone();
1368 self.shared = self.get_outer().unwrap().shared.clone();
1369 self.higher_order_caller = self.get_outer().unwrap().higher_order_caller.clone();
1370 }
1371
1372 pub(crate) fn clear_invalid_vars(&mut self) {
1373 self.locals.retain(|_, v| v.t != Failure);
1374 self.decls.retain(|_, v| v.t != Failure);
1375 self.params.retain(|(_, v)| v.t != Failure);
1376 }
1377
1378 pub fn pop(&mut self) -> Context {
1380 self.check_types();
1381 if let Some(parent) = self.outer.take() {
1382 let ctx = mem::take(self);
1383 *self = *parent;
1384 log!(info "{}: current namespace: {}", fn_name!(), self.name);
1385 ctx
1386 } else {
1387 panic!("cannot pop the top-level context (or use `pop_mod`)");
1388 }
1389 }
1390
1391 pub fn pop_mod(&mut self) -> Option<Context> {
1393 self.check_types();
1394 if self.outer.is_some() {
1395 log!(err "not in the top-level context");
1396 if self.kind.is_module() {
1397 Some(self.pop())
1398 } else {
1399 None
1400 }
1401 } else {
1402 log!(info "{}: current namespace: <builtins>", fn_name!());
1403 Some(mem::take(self))
1405 }
1406 }
1407
1408 pub(crate) fn check_decls_and_pop(&mut self) -> (Context, TyCheckErrors) {
1409 match self.check_decls() {
1410 Ok(_) => (self.pop(), TyCheckErrors::empty()),
1411 Err(errs) => (self.pop(), errs),
1412 }
1413 }
1414
1415 pub(crate) fn check_decls(&mut self) -> Result<(), TyCheckErrors> {
1416 let mut uninited_errs = TyCheckErrors::empty();
1417 for (name, vi) in self.decls.iter() {
1418 uninited_errs.push(TyCheckError::uninitialized_error(
1419 self.cfg.input.clone(),
1420 line!() as usize,
1421 name.loc(),
1422 self.caused_by(),
1423 name.inspect(),
1424 &vi.t,
1425 ));
1426 }
1427 if !uninited_errs.is_empty() {
1428 Err(uninited_errs)
1429 } else {
1430 Ok(())
1431 }
1432 }
1433
1434 pub(crate) fn type_dir<'t>(&'t self, namespace: &'t Context) -> Dict<&'t VarName, &'t VarInfo> {
1436 let mut attrs = self.locals.iter().collect::<Dict<_, _>>();
1437 attrs.guaranteed_extend(
1438 self.params
1439 .iter()
1440 .filter_map(|(k, v)| k.as_ref().map(|k| (k, v))),
1441 );
1442 attrs.guaranteed_extend(self.decls.iter());
1443 attrs.guaranteed_extend(
1444 self.methods_list
1445 .iter()
1446 .flat_map(|ctx| ctx.type_dir(namespace)),
1447 );
1448 if let Some(tv_cache) = &self.tv_cache {
1449 attrs.guaranteed_extend(tv_cache.var_infos.iter());
1450 }
1451 for sup in self.super_classes.iter() {
1452 if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1453 if sup_ctx.name == self.name {
1454 continue;
1455 }
1456 attrs.guaranteed_extend(sup_ctx.type_dir(namespace));
1457 }
1458 }
1459 for sup in self.super_traits.iter() {
1460 if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1461 if sup_ctx.name == self.name {
1462 continue;
1463 }
1464 attrs.guaranteed_extend(sup_ctx.type_impl_dir(namespace));
1465 }
1466 }
1467 attrs
1468 }
1469
1470 fn type_impl_dir<'t>(&'t self, namespace: &'t Context) -> Dict<&'t VarName, &'t VarInfo> {
1471 let mut attrs = self.locals.iter().collect::<Dict<_, _>>();
1472 attrs.guaranteed_extend(
1473 self.methods_list
1474 .iter()
1475 .flat_map(|ctx| ctx.type_impl_dir(namespace)),
1476 );
1477 for sup in self.super_classes.iter().chain(self.super_traits.iter()) {
1478 if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1479 if sup_ctx.name == self.name {
1480 continue;
1481 }
1482 attrs.guaranteed_extend(sup_ctx.type_impl_dir(namespace));
1483 }
1484 }
1485 attrs
1486 }
1487
1488 pub fn local_dir(&self) -> Dict<&VarName, &VarInfo> {
1489 self.type_dir(self)
1490 }
1491
1492 pub(crate) fn opt_mod_cache(&self) -> Option<&SharedModuleCache> {
1493 self.shared.as_ref().map(|s| &s.mod_cache)
1494 }
1495
1496 pub(crate) fn mod_cache(&self) -> &SharedModuleCache {
1497 &self.shared().mod_cache
1498 }
1499
1500 pub(crate) fn opt_py_mod_cache(&self) -> Option<&SharedModuleCache> {
1501 self.shared.as_ref().map(|s| &s.py_mod_cache)
1502 }
1503
1504 pub(crate) fn py_mod_cache(&self) -> &SharedModuleCache {
1505 &self.shared().py_mod_cache
1506 }
1507
1508 pub(crate) fn opt_index(&self) -> Option<&SharedModuleIndex> {
1509 self.shared.as_ref().map(|s| &s.index)
1510 }
1511
1512 pub fn index(&self) -> &SharedModuleIndex {
1513 &self.shared().index
1514 }
1515
1516 pub fn graph(&self) -> &SharedModuleGraph {
1517 &self.shared().graph
1518 }
1519
1520 pub fn trait_impls(&self) -> &SharedTraitImpls {
1521 &self.shared().trait_impls
1522 }
1523
1524 pub fn shared(&self) -> &SharedCompilerResource {
1525 self.shared.as_ref().unwrap()
1526 }
1527
1528 pub fn promises(&self) -> &SharedPromises {
1529 &self.shared().promises
1530 }
1531
1532 pub fn current_control_flow(&self) -> Option<ControlKind> {
1533 self.higher_order_caller
1534 .last()
1535 .and_then(|name| ControlKind::try_from(&name[..]).ok())
1536 }
1537
1538 pub fn control_kind(&self) -> Option<ControlKind> {
1539 for caller in self.higher_order_caller.iter().rev() {
1540 if let Ok(control) = ControlKind::try_from(&caller[..]) {
1541 return Some(control);
1542 }
1543 }
1544 None
1545 }
1546
1547 pub fn current_true_function_ctx(&self) -> Option<&Context> {
1550 if self.kind.is_subr() && self.current_control_flow().is_none() {
1551 Some(self)
1552 } else if let Some(outer) = self.get_outer_scope() {
1553 outer.current_true_function_ctx()
1554 } else {
1555 None
1556 }
1557 }
1558
1559 pub(crate) fn check_types(&self) {
1560 if DEBUG_MODE {
1561 for (_, ctx) in self.poly_types.iter() {
1562 if ctx.typ.has_undoable_linked_var() {
1563 panic!("{} has undoable linked vars", ctx.typ);
1564 }
1565 ctx.check_types();
1566 }
1567 for methods in self.methods_list.iter() {
1568 if methods.typ.get_class().has_undoable_linked_var() {
1569 panic!("{} has undoable linked vars", methods.typ);
1570 }
1571 if methods
1572 .typ
1573 .get_impl_trait()
1574 .is_some_and(|t| t.has_undoable_linked_var())
1575 {
1576 panic!("{} has undoable linked vars", methods.typ);
1577 }
1578 methods.check_types();
1579 }
1580 if let Some(outer) = self.get_outer() {
1581 outer.check_types();
1582 }
1583 }
1584 }
1585
1586 pub(crate) fn get_tv_ctx(&self, ident: &ast::Identifier, args: &ast::Args) -> TyVarCache {
1587 let mut tv_ctx = TyVarCache::new(self.level, self);
1588 if let Some(ctx) = self.get_type_ctx(ident.inspect()) {
1589 let arg_ts = ctx.params.iter().map(|(_, vi)| &vi.t);
1590 for ((tp, arg), arg_t) in ctx.typ.typarams().iter().zip(args.pos_args()).zip(arg_ts) {
1591 let tp = self.detach_tp(tp.clone(), &mut tv_ctx);
1592 if let Some(ident) = &arg.expr.as_ident() {
1593 if self.subtype_of(arg_t, &Type::Type) {
1594 if let Ok(tv) = self.convert_tp_into_type(tp.clone()) {
1595 let _ = tv_ctx.push_or_init_tyvar(&ident.name, &tv, self);
1596 continue;
1597 }
1598 }
1599 let _ = tv_ctx.push_or_init_typaram(&ident.name, &tp, self);
1600 }
1601 }
1602 }
1603 tv_ctx
1604 }
1605}
1606
1607#[derive(Debug, Clone, Default)]
1608pub struct ModuleContext {
1609 pub context: Context,
1610 pub scope: Dict<Str, Context>,
1611}
1612
1613impl ModuleContext {
1614 pub const fn new(toplevel: Context, scope: Dict<Str, Context>) -> Self {
1615 Self {
1616 context: toplevel,
1617 scope,
1618 }
1619 }
1620
1621 pub fn get_top_cfg(&self) -> ErgConfig {
1622 self.context.cfg.clone()
1623 }
1624
1625 pub fn is_empty(&self) -> bool {
1626 self.context.is_empty()
1627 }
1628}