Skip to main content

aver/interpreter/
core.rs

1use super::*;
2
3impl Default for Interpreter {
4    fn default() -> Self {
5        Self::new()
6    }
7}
8
9impl Interpreter {
10    pub fn new() -> Self {
11        let mut global = HashMap::new();
12
13        args::register(&mut global);
14        console::register(&mut global);
15        http::register(&mut global);
16        http_server::register(&mut global);
17        disk::register(&mut global);
18        env::register(&mut global);
19        tcp::register(&mut global);
20        time::register(&mut global);
21        int::register(&mut global);
22        float::register(&mut global);
23        string::register(&mut global);
24        list::register(&mut global);
25        map::register(&mut global);
26        char::register(&mut global);
27        byte::register(&mut global);
28
29        // Result and Option namespaces — constructors for Ok/Err/Some/None
30        {
31            let mut members = HashMap::new();
32            members.insert(
33                "Ok".to_string(),
34                Value::Builtin("__ctor:Result.Ok".to_string()),
35            );
36            members.insert(
37                "Err".to_string(),
38                Value::Builtin("__ctor:Result.Err".to_string()),
39            );
40            for (name, builtin_name) in result::extra_members() {
41                members.insert(name.to_string(), Value::Builtin(builtin_name));
42            }
43            global.insert(
44                "Result".to_string(),
45                Value::Namespace {
46                    name: "Result".to_string(),
47                    members,
48                },
49            );
50        }
51        {
52            let mut members = HashMap::new();
53            members.insert(
54                "Some".to_string(),
55                Value::Builtin("__ctor:Option.Some".to_string()),
56            );
57            members.insert("None".to_string(), Value::None);
58            for (name, builtin_name) in option::extra_members() {
59                members.insert(name.to_string(), Value::Builtin(builtin_name));
60            }
61            global.insert(
62                "Option".to_string(),
63                Value::Namespace {
64                    name: "Option".to_string(),
65                    members,
66                },
67            );
68        }
69
70        let mut record_schemas = HashMap::new();
71        record_schemas.insert(
72            "HttpResponse".to_string(),
73            vec![
74                "status".to_string(),
75                "body".to_string(),
76                "headers".to_string(),
77            ],
78        );
79        record_schemas.insert(
80            "HttpRequest".to_string(),
81            vec![
82                "method".to_string(),
83                "path".to_string(),
84                "body".to_string(),
85                "headers".to_string(),
86            ],
87        );
88        record_schemas.insert(
89            "Header".to_string(),
90            vec!["name".to_string(), "value".to_string()],
91        );
92        record_schemas.insert(
93            "Tcp.Connection".to_string(),
94            vec!["id".to_string(), "host".to_string(), "port".to_string()],
95        );
96
97        Interpreter {
98            env: vec![EnvFrame::Owned(global)],
99            module_cache: HashMap::new(),
100            record_schemas,
101            call_stack: Vec::new(),
102            active_local_slots: None,
103            memo_fns: HashSet::new(),
104            memo_cache: HashMap::new(),
105            execution_mode: ExecutionMode::Normal,
106            recorded_effects: Vec::new(),
107            replay_effects: Vec::new(),
108            replay_pos: 0,
109            validate_replay_args: false,
110            recording_sink: None,
111            verify_match_coverage: None,
112            runtime_policy: None,
113            cli_args: Vec::new(),
114        }
115    }
116
117    pub fn execution_mode(&self) -> ExecutionMode {
118        self.execution_mode
119    }
120
121    pub fn set_execution_mode_normal(&mut self) {
122        self.execution_mode = ExecutionMode::Normal;
123        self.recorded_effects.clear();
124        self.replay_effects.clear();
125        self.replay_pos = 0;
126        self.validate_replay_args = false;
127    }
128
129    pub fn start_recording(&mut self) {
130        self.execution_mode = ExecutionMode::Record;
131        self.recorded_effects.clear();
132        self.replay_effects.clear();
133        self.replay_pos = 0;
134        self.validate_replay_args = false;
135    }
136
137    pub fn start_replay(&mut self, effects: Vec<EffectRecord>, validate_args: bool) {
138        self.execution_mode = ExecutionMode::Replay;
139        self.replay_effects = effects;
140        self.replay_pos = 0;
141        self.validate_replay_args = validate_args;
142        self.recorded_effects.clear();
143    }
144
145    pub fn take_recorded_effects(&mut self) -> Vec<EffectRecord> {
146        std::mem::take(&mut self.recorded_effects)
147    }
148
149    pub fn replay_progress(&self) -> (usize, usize) {
150        (self.replay_pos, self.replay_effects.len())
151    }
152
153    pub fn ensure_replay_consumed(&self) -> Result<(), RuntimeError> {
154        if self.execution_mode == ExecutionMode::Replay
155            && self.replay_pos < self.replay_effects.len()
156        {
157            return Err(RuntimeError::ReplayUnconsumed {
158                remaining: self.replay_effects.len() - self.replay_pos,
159            });
160        }
161        Ok(())
162    }
163
164    pub fn configure_recording_sink(&mut self, cfg: RecordingConfig) {
165        self.recording_sink = Some(RecordingSink {
166            path: cfg.path,
167            request_id: cfg.request_id,
168            timestamp: cfg.timestamp,
169            program_file: cfg.program_file,
170            module_root: cfg.module_root,
171            entry_fn: cfg.entry_fn,
172            input: cfg.input,
173        });
174    }
175
176    pub fn recording_sink_path(&self) -> Option<std::path::PathBuf> {
177        self.recording_sink.as_ref().map(|s| s.path.clone())
178    }
179
180    pub fn persist_recording_snapshot(&self, output: RecordedOutcome) -> Result<(), RuntimeError> {
181        let Some(sink) = &self.recording_sink else {
182            return Ok(());
183        };
184
185        let recording = SessionRecording {
186            schema_version: 1,
187            request_id: sink.request_id.clone(),
188            timestamp: sink.timestamp.clone(),
189            program_file: sink.program_file.clone(),
190            module_root: sink.module_root.clone(),
191            entry_fn: sink.entry_fn.clone(),
192            input: sink.input.clone(),
193            effects: self.recorded_effects.clone(),
194            output,
195        };
196
197        let json = session_recording_to_string_pretty(&recording);
198        std::fs::write(&sink.path, json).map_err(|e| {
199            RuntimeError::Error(format!(
200                "Cannot write recording '{}': {}",
201                sink.path.display(),
202                e
203            ))
204        })?;
205        Ok(())
206    }
207
208    /// Mark a set of function names as eligible for auto-memoization.
209    pub fn enable_memo(&mut self, fns: HashSet<String>) {
210        self.memo_fns = fns;
211    }
212
213    /// Register a named effect set alias.
214    /// Set the runtime policy from an `aver.toml` configuration.
215    pub fn set_runtime_policy(&mut self, config: crate::config::ProjectConfig) {
216        self.runtime_policy = Some(config);
217    }
218
219    /// Set command-line arguments available via `Args.get()`.
220    pub fn set_cli_args(&mut self, args: Vec<String>) {
221        self.cli_args = args;
222    }
223
224    /// Check whether a builtin call is permitted by the runtime policy.
225    /// Skipped in Replay mode (deterministic playback).
226    pub(super) fn check_runtime_policy(
227        &self,
228        name: &str,
229        args: &[Value],
230    ) -> Result<(), RuntimeError> {
231        if self.execution_mode == ExecutionMode::Replay {
232            return Ok(());
233        }
234        let Some(policy) = &self.runtime_policy else {
235            return Ok(());
236        };
237
238        if name.starts_with("Http.") {
239            if let Some(Value::Str(url)) = args.first() {
240                policy
241                    .check_http_host(name, url)
242                    .map_err(RuntimeError::Error)?;
243            }
244        } else if name.starts_with("Disk.") {
245            if let Some(Value::Str(path)) = args.first() {
246                policy
247                    .check_disk_path(name, path)
248                    .map_err(RuntimeError::Error)?;
249            }
250        } else if name.starts_with("Env.")
251            && let Some(Value::Str(key)) = args.first()
252        {
253            policy
254                .check_env_key(name, key)
255                .map_err(RuntimeError::Error)?;
256        }
257
258        Ok(())
259    }
260
261    pub fn start_verify_match_coverage(&mut self, fn_name: &str) {
262        let Ok(fn_val) = self.lookup(fn_name) else {
263            self.verify_match_coverage = None;
264            return;
265        };
266        let Value::Fn(function) = fn_val else {
267            self.verify_match_coverage = None;
268            return;
269        };
270
271        let mut expected = std::collections::BTreeMap::new();
272        Self::collect_match_sites_from_fn_body(function.body.as_ref(), &mut expected);
273        if expected.is_empty() {
274            self.verify_match_coverage = None;
275            return;
276        }
277
278        self.verify_match_coverage = Some(VerifyMatchCoverageTracker {
279            target_fn: fn_name.to_string(),
280            expected_arms: expected,
281            visited_arms: HashMap::new(),
282        });
283    }
284
285    pub fn finish_verify_match_coverage(&mut self) -> Vec<VerifyMatchCoverageMiss> {
286        let Some(tracker) = self.verify_match_coverage.take() else {
287            return vec![];
288        };
289
290        let mut misses = Vec::new();
291        for ((line, arm_count), expected_total) in tracker.expected_arms {
292            let visited = tracker.visited_arms.get(&(line, arm_count));
293            let mut missing = Vec::new();
294            for arm_idx in 0..expected_total {
295                let covered = visited.is_some_and(|set| set.contains(&arm_idx));
296                if !covered {
297                    missing.push(arm_idx);
298                }
299            }
300            if !missing.is_empty() {
301                misses.push(VerifyMatchCoverageMiss {
302                    line,
303                    total_arms: expected_total,
304                    missing_arms: missing,
305                });
306            }
307        }
308        misses
309    }
310
311    pub(super) fn note_verify_match_arm(&mut self, line: usize, arm_count: usize, arm_idx: usize) {
312        let Some(tracker) = self.verify_match_coverage.as_mut() else {
313            return;
314        };
315        let Some(frame) = self.call_stack.last() else {
316            return;
317        };
318        if frame.name.as_str() != tracker.target_fn {
319            return;
320        }
321        let key = (line, arm_count);
322        if !tracker.expected_arms.contains_key(&key) {
323            return;
324        }
325        tracker.visited_arms.entry(key).or_default().insert(arm_idx);
326    }
327
328    fn collect_match_sites_from_fn_body(
329        body: &FnBody,
330        out: &mut std::collections::BTreeMap<MatchSiteKey, usize>,
331    ) {
332        for stmt in body.stmts() {
333            Self::collect_match_sites_from_stmt(stmt, out);
334        }
335    }
336
337    fn collect_match_sites_from_stmt(
338        stmt: &Stmt,
339        out: &mut std::collections::BTreeMap<MatchSiteKey, usize>,
340    ) {
341        match stmt {
342            Stmt::Binding(_, _, expr) | Stmt::Expr(expr) => {
343                Self::collect_match_sites_from_expr(expr, out);
344            }
345        }
346    }
347
348    fn collect_match_sites_from_expr(
349        expr: &Expr,
350        out: &mut std::collections::BTreeMap<MatchSiteKey, usize>,
351    ) {
352        match expr {
353            Expr::Match {
354                subject,
355                arms,
356                line,
357            } => {
358                out.insert((*line, arms.len()), arms.len());
359                Self::collect_match_sites_from_expr(subject, out);
360                for arm in arms {
361                    Self::collect_match_sites_from_expr(&arm.body, out);
362                }
363            }
364            Expr::FnCall(fn_expr, args) => {
365                Self::collect_match_sites_from_expr(fn_expr, out);
366                for arg in args {
367                    Self::collect_match_sites_from_expr(arg, out);
368                }
369            }
370            Expr::BinOp(_, left, right) => {
371                Self::collect_match_sites_from_expr(left, out);
372                Self::collect_match_sites_from_expr(right, out);
373            }
374            Expr::Attr(obj, _) | Expr::ErrorProp(obj) => {
375                Self::collect_match_sites_from_expr(obj, out);
376            }
377            Expr::Constructor(_, maybe_arg) => {
378                if let Some(arg) = maybe_arg {
379                    Self::collect_match_sites_from_expr(arg, out);
380                }
381            }
382            Expr::InterpolatedStr(parts) => {
383                for part in parts {
384                    if let StrPart::Parsed(expr) = part {
385                        Self::collect_match_sites_from_expr(expr, out);
386                    }
387                }
388            }
389            Expr::List(items) | Expr::Tuple(items) => {
390                for item in items {
391                    Self::collect_match_sites_from_expr(item, out);
392                }
393            }
394            Expr::MapLiteral(entries) => {
395                for (key, value) in entries {
396                    Self::collect_match_sites_from_expr(key, out);
397                    Self::collect_match_sites_from_expr(value, out);
398                }
399            }
400            Expr::RecordCreate { fields, .. } => {
401                for (_, expr) in fields {
402                    Self::collect_match_sites_from_expr(expr, out);
403                }
404            }
405            Expr::RecordUpdate { base, updates, .. } => {
406                Self::collect_match_sites_from_expr(base, out);
407                for (_, expr) in updates {
408                    Self::collect_match_sites_from_expr(expr, out);
409                }
410            }
411            Expr::TailCall(boxed) => {
412                for arg in &boxed.1 {
413                    Self::collect_match_sites_from_expr(arg, out);
414                }
415            }
416            Expr::Literal(_) | Expr::Ident(_) | Expr::Resolved(_) => {}
417        }
418    }
419
420    // -------------------------------------------------------------------------
421    // Environment management
422    // -------------------------------------------------------------------------
423    pub(super) fn push_env(&mut self, frame: EnvFrame) {
424        self.env.push(frame);
425    }
426
427    pub(super) fn pop_env(&mut self) {
428        if self.env.len() > 1 {
429            self.env.pop();
430        }
431    }
432
433    pub(super) fn last_owned_scope_mut(
434        &mut self,
435    ) -> Result<&mut HashMap<String, Value>, RuntimeError> {
436        let frame = self
437            .env
438            .last_mut()
439            .ok_or_else(|| RuntimeError::Error("No active scope".to_string()))?;
440        match frame {
441            EnvFrame::Owned(scope) => Ok(scope),
442            EnvFrame::Shared(_) | EnvFrame::Slots(_) => Err(RuntimeError::Error(
443                "Cannot define name in non-owned frame".to_string(),
444            )),
445        }
446    }
447
448    pub(super) fn lookup_ref(&self, name: &str) -> Result<&Value, RuntimeError> {
449        for frame in self.env.iter().rev() {
450            let found = match frame {
451                EnvFrame::Owned(scope) => scope.get(name),
452                EnvFrame::Shared(scope) => scope.get(name),
453                // Slots frames are indexed by slot, not by name — skip in name-based lookup
454                EnvFrame::Slots(_) => None,
455            };
456            if let Some(v) = found {
457                return Ok(v);
458            }
459        }
460        Err(RuntimeError::Error(format!(
461            "Undefined variable: '{}'",
462            name
463        )))
464    }
465
466    pub(super) fn global_scope_clone(&self) -> Result<HashMap<String, Value>, RuntimeError> {
467        let frame = self
468            .env
469            .first()
470            .ok_or_else(|| RuntimeError::Error("No global scope".to_string()))?;
471        match frame {
472            EnvFrame::Owned(scope) => Ok(scope.clone()),
473            EnvFrame::Shared(scope) => Ok((**scope).clone()),
474            EnvFrame::Slots(_) => Err(RuntimeError::Error(
475                "Invalid global scope frame: Slots".to_string(),
476            )),
477        }
478    }
479
480    pub fn lookup(&self, name: &str) -> Result<Value, RuntimeError> {
481        self.lookup_ref(name).cloned()
482    }
483
484    pub fn define(&mut self, name: String, val: Value) {
485        if let Ok(scope) = self.last_owned_scope_mut() {
486            scope.insert(name, val);
487        }
488    }
489
490    fn alias_exposed_type_namespaces(&mut self, module_val: &Value) {
491        let Value::Namespace { members, .. } = module_val else {
492            return;
493        };
494        for (name, member) in members {
495            if matches!(member, Value::Namespace { .. }) {
496                self.define(name.clone(), member.clone());
497            }
498        }
499    }
500
501    /// O(1) slot-based variable lookup for resolved function bodies.
502    pub(super) fn lookup_slot(&self, slot: u16) -> Result<Value, RuntimeError> {
503        let idx = self.env.len() - 1;
504        match &self.env[idx] {
505            EnvFrame::Slots(v) => Ok(v[slot as usize].clone()),
506            _ => {
507                // Fallback — shouldn't happen if resolver is correct
508                Err(RuntimeError::Error(
509                    "Resolved lookup on non-Slots frame".to_string(),
510                ))
511            }
512        }
513    }
514
515    /// Define a value in the current Slots frame at the given slot index.
516    pub(super) fn define_slot(&mut self, slot: u16, val: Value) {
517        let idx = self.env.len() - 1;
518        if let EnvFrame::Slots(v) = &mut self.env[idx] {
519            v[slot as usize] = val;
520        }
521    }
522
523    pub fn define_module_path(&mut self, path: &str, val: Value) -> Result<(), RuntimeError> {
524        let alias_source = val.clone();
525        let parts: Vec<&str> = path.split('.').filter(|s| !s.is_empty()).collect();
526        if parts.is_empty() {
527            return Err(RuntimeError::Error("Empty module path".to_string()));
528        }
529        if parts.len() == 1 {
530            self.define(parts[0].to_string(), val);
531            self.alias_exposed_type_namespaces(&alias_source);
532            return Ok(());
533        }
534
535        let head = parts[0];
536        let tail = &parts[1..];
537
538        let result = {
539            let scope = self.last_owned_scope_mut()?;
540            if let Some(existing) = scope.remove(head) {
541                match existing {
542                    Value::Namespace { name, mut members } => {
543                        Self::insert_namespace_path(&mut members, tail, val)?;
544                        scope.insert(head.to_string(), Value::Namespace { name, members });
545                        Ok(())
546                    }
547                    _ => Err(RuntimeError::Error(format!(
548                        "Cannot mount module '{}': '{}' is not a namespace",
549                        parts.join("."),
550                        head
551                    ))),
552                }
553            } else {
554                let mut members = HashMap::new();
555                Self::insert_namespace_path(&mut members, tail, val)?;
556                scope.insert(
557                    head.to_string(),
558                    Value::Namespace {
559                        name: head.to_string(),
560                        members,
561                    },
562                );
563                Ok(())
564            }
565        };
566
567        if result.is_ok() {
568            self.alias_exposed_type_namespaces(&alias_source);
569        }
570        result
571    }
572
573    pub(super) fn insert_namespace_path(
574        scope: &mut HashMap<String, Value>,
575        parts: &[&str],
576        val: Value,
577    ) -> Result<(), RuntimeError> {
578        if parts.len() == 1 {
579            scope.insert(parts[0].to_string(), val);
580            return Ok(());
581        }
582
583        let head = parts[0];
584        let tail = &parts[1..];
585
586        if let Some(existing) = scope.remove(head) {
587            match existing {
588                Value::Namespace { name, mut members } => {
589                    Self::insert_namespace_path(&mut members, tail, val)?;
590                    scope.insert(head.to_string(), Value::Namespace { name, members });
591                    Ok(())
592                }
593                _ => Err(RuntimeError::Error(format!(
594                    "Cannot mount module '{}': '{}' is not a namespace",
595                    parts.join("."),
596                    head
597                ))),
598            }
599        } else {
600            let mut members = HashMap::new();
601            Self::insert_namespace_path(&mut members, tail, val)?;
602            scope.insert(
603                head.to_string(),
604                Value::Namespace {
605                    name: head.to_string(),
606                    members,
607                },
608            );
609            Ok(())
610        }
611    }
612
613    pub(super) fn module_cache_key(path: &Path) -> String {
614        canonicalize_path(path).to_string_lossy().to_string()
615    }
616
617    pub(super) fn module_decl(items: &[TopLevel]) -> Option<&Module> {
618        items.iter().find_map(|item| {
619            if let TopLevel::Module(m) = item {
620                Some(m)
621            } else {
622                None
623            }
624        })
625    }
626
627    pub(super) fn exposed_set(items: &[TopLevel]) -> Option<HashSet<String>> {
628        Self::module_decl(items).and_then(|m| {
629            if m.exposes.is_empty() {
630                None
631            } else {
632                Some(m.exposes.iter().cloned().collect())
633            }
634        })
635    }
636
637    pub(super) fn cycle_display(loading: &[String], next: &str) -> String {
638        let mut chain = loading
639            .iter()
640            .map(|key| {
641                Path::new(key)
642                    .file_stem()
643                    .and_then(|s| s.to_str())
644                    .unwrap_or(key)
645                    .to_string()
646            })
647            .collect::<Vec<_>>();
648        chain.push(
649            Path::new(next)
650                .file_stem()
651                .and_then(|s| s.to_str())
652                .unwrap_or(next)
653                .to_string(),
654        );
655        chain.join(" -> ")
656    }
657
658    pub fn load_module(
659        &mut self,
660        name: &str,
661        base_dir: &str,
662        loading: &mut Vec<String>,
663        loading_set: &mut HashSet<String>,
664    ) -> Result<Value, RuntimeError> {
665        let path = find_module_file(name, base_dir).ok_or_else(|| {
666            RuntimeError::Error(format!("Module '{}' not found in '{}'", name, base_dir))
667        })?;
668        let cache_key = Self::module_cache_key(&path);
669
670        if let Some(cached) = self.module_cache.get(&cache_key) {
671            return Ok(cached.clone());
672        }
673
674        if loading_set.contains(&cache_key) {
675            return Err(RuntimeError::Error(format!(
676                "Circular import: {}",
677                Self::cycle_display(loading, &cache_key)
678            )));
679        }
680
681        loading.push(cache_key.clone());
682        loading_set.insert(cache_key.clone());
683        let result = (|| -> Result<Value, RuntimeError> {
684            let src = std::fs::read_to_string(&path).map_err(|e| {
685                RuntimeError::Error(format!("Cannot read '{}': {}", path.display(), e))
686            })?;
687            let mut items = parse_source(&src).map_err(|e| {
688                RuntimeError::Error(format!("Parse error in '{}': {}", path.display(), e))
689            })?;
690            require_module_declaration(&items, &path.to_string_lossy())
691                .map_err(RuntimeError::Error)?;
692            crate::resolver::resolve_program(&mut items);
693
694            if let Some(module) = Self::module_decl(&items) {
695                let expected = name.rsplit('.').next().unwrap_or(name);
696                if module.name != expected {
697                    return Err(RuntimeError::Error(format!(
698                        "Module name mismatch: expected '{}' (from '{}'), found '{}' in '{}'",
699                        expected,
700                        name,
701                        module.name,
702                        path.display()
703                    )));
704                }
705            }
706
707            let mut sub = Interpreter::new();
708
709            if let Some(module) = Self::module_decl(&items) {
710                for dep_name in &module.depends {
711                    let dep_ns = self.load_module(dep_name, base_dir, loading, loading_set)?;
712                    sub.define_module_path(dep_name, dep_ns)?;
713                }
714            }
715
716            for item in &items {
717                if let TopLevel::TypeDef(td) = item {
718                    sub.register_type_def(td);
719                }
720            }
721            for item in &items {
722                if let TopLevel::FnDef(fd) = item {
723                    sub.exec_fn_def(fd)?;
724                }
725            }
726            let module_globals = Rc::new(sub.global_scope_clone()?);
727
728            let exposed = Self::exposed_set(&items);
729            let mut members = HashMap::new();
730            for item in &items {
731                match item {
732                    TopLevel::FnDef(fd) => {
733                        let include = match &exposed {
734                            Some(set) => set.contains(&fd.name),
735                            None => !fd.name.starts_with('_'),
736                        };
737                        if include {
738                            let mut val = sub.lookup(&fd.name).map_err(|_| {
739                                RuntimeError::Error(format!(
740                                    "Failed to export '{}.{}'",
741                                    name, fd.name
742                                ))
743                            })?;
744                            if let Value::Fn(function) = &mut val {
745                                Rc::make_mut(function).home_globals = Some(Rc::clone(&module_globals));
746                            }
747                            members.insert(fd.name.clone(), val);
748                        }
749                    }
750                    TopLevel::TypeDef(TypeDef::Sum {
751                        name: type_name, ..
752                    }) => {
753                        let include = match &exposed {
754                            Some(set) => set.contains(type_name),
755                            None => !type_name.starts_with('_'),
756                        };
757                        if include {
758                            let val = sub.lookup(type_name).map_err(|_| {
759                                RuntimeError::Error(format!(
760                                    "Failed to export '{}.{}'",
761                                    name, type_name
762                                ))
763                            })?;
764                            members.insert(type_name.clone(), val);
765                        }
766                    }
767                    _ => {}
768                }
769            }
770
771            Ok(Value::Namespace {
772                name: name.to_string(),
773                members,
774            })
775        })();
776        loading.pop();
777        loading_set.remove(&cache_key);
778
779        match result {
780            Ok(ns) => {
781                self.module_cache.insert(cache_key, ns.clone());
782                Ok(ns)
783            }
784            Err(e) => Err(e),
785        }
786    }
787}