nilang 0.4.1

A scripting language interpreter for Advent of Code
Documentation
use super::func::{Func, LoadedLocal};
use super::string::VMString;
use sandpit::*;
use hashbrown::HashMap;
use crate::codegen::{Func as ByteCodeFunc, Local};

pub fn load_program<'gc>(program: Vec<ByteCodeFunc>, path: Option<&str>, mu: &'gc Mutator) -> Vec<Gc<'gc, Func<'gc>>> {
    let mut loaded_funcs = HashMap::<u32, Gc<'gc, Func<'gc>>>::new();
    let mut result = vec![];

    let stored_path = path.map(|p|Gc::new(mu, VMString::alloc(p.chars(), mu)));

    for i in 0..program.len() {
        let func = &program[i];
        let is_top_level = i + 1 == program.len();
        let locals: Gc<'gc, [LoadedLocal<'gc>]> =
            mu.alloc_array_from_fn(0, |_| LoadedLocal::Int(0));
        let code = mu.alloc_array_from_slice(func.get_instrs().as_slice());
        let spans = func.spans().into_gc(mu);
        let loaded_func = Func::new(
            func.id(),
            func.auto_binds(),
            func.arg_count(),
            func.max_clique(),
            locals,
            code,
            GcOpt::new_none(),
            GcOpt::new_none(),
            Some(spans),
            stored_path.clone(),
            is_top_level,
        );
        let loaded_func_ptr = Gc::new(mu, loaded_func);

        loaded_funcs.insert(func.id(), loaded_func_ptr.clone());
        result.push(loaded_func_ptr);
    }

    for func in program.iter() {
        let locals = func.get_locals();

        let new_locals = mu.alloc_array_from_fn(locals.len(), |idx| {
            let local = &locals[idx];

            match local {
                Local::Sym(s) => LoadedLocal::SymId(*s),
                Local::Int(i) => LoadedLocal::Int(*i),
                Local::Float(f) => LoadedLocal::Float(*f),
                Local::FuncId(fn_id) => {
                    let fn_ptr = loaded_funcs.get(fn_id).unwrap().clone();

                    LoadedLocal::Func(fn_ptr)
                }
                Local::String(s) => {
                    let mut chars = s.chars();
                    let len = chars.clone().count();
                    let gc_text = mu.alloc_array_from_fn(len, |_| chars.next().unwrap());

                    LoadedLocal::Text(gc_text)
                }
            }
        });

        let fn_ptr = loaded_funcs.get(&func.id()).unwrap().clone();

        Func::update_locals(fn_ptr, new_locals, mu)
    }

    result
}