knave 0.9.4

A small Lisp for humans and agents that infers types and ownership and compiles to readable Rust
Documentation
use std::path::PathBuf;

use rustc_hash::{FxHashMap, FxHashSet};

use super::{DefinitionGraph, InferredCopies, LiteralDefaults, TypeChecker, TypedProgram};
use crate::core::{BindingId, ModulePath};
use crate::expand::{Expander, PreludeState, Program};
use crate::language::Language;
use crate::modules::ModuleSources;
use crate::source::SourceMap;

pub struct TypedSource {
    program: Program,
}

impl TypedSource {
    const MODULE: &str = "fixture";

    pub fn expand(text: &str) -> Self {
        let mut sources = SourceMap::default();
        let entry = sources.add(Self::file_name(), text);
        let module_sources = ModuleSources::new(PathBuf::from("."), PathBuf::from("."));
        let program = Expander::new(&mut sources, module_sources)
            .expand(ModulePath::new(Self::MODULE), entry)
            .expect("the source expands");
        Self { program }
    }

    pub fn expand_on_a_loaded_prelude(text: &str) -> Self {
        let state = PreludeState::load(PreludeState::build().save().leak())
            .expect("the saved prelude loads");
        let mut sources = SourceMap::default();
        let entry = sources.add(Self::file_name(), text);
        let module_sources = ModuleSources::new(PathBuf::from("."), PathBuf::from("."));
        let program = Expander::with_prelude(&mut sources, module_sources, state)
            .expand(ModulePath::new(Self::MODULE), entry)
            .expect("the source expands");
        Self { program }
    }

    pub fn enter_at(&mut self, name: &str) {
        let program = &self.program;
        let entry = program
            .entry_module()
            .definitions()
            .map(|(binding, _)| binding)
            .find(|binding| program.bindings.get(*binding).name() == name);
        self.program.entry_function = entry;
    }

    pub fn move_entry_to(&mut self, path: ModulePath) {
        let entry = self.program.entry;
        let module = self
            .program
            .modules
            .iter_mut()
            .find(|module| module.id == entry);
        module.expect("the entry module is expanded").path = path;
    }

    pub fn detach_entry(&mut self) {
        self.program.entry = self.program.modules[0].id;
    }

    pub fn check_also(&mut self, binding: BindingId) {
        self.program.check_also(binding);
    }

    pub fn program(&self) -> &Program {
        &self.program
    }

    pub fn typed(&self) -> TypedProgram {
        self.check(&DefinitionGraph::of(&self.program))
    }

    pub fn check(&self, graph: &DefinitionGraph) -> TypedProgram {
        TypeChecker::check(
            &self.program,
            graph,
            &FxHashSet::default(),
            &InferredCopies::default(),
            &FxHashMap::default(),
            LiteralDefaults::default(),
            false,
        )
        .expect("the source checks")
    }

    fn file_name() -> String {
        format!("{}.{}", Self::MODULE, Language::EXTENSION)
    }
}