rune 0.9.0

An embeddable dynamic programming language for Rust.
Documentation
use crate::compiling::v1::assemble::prelude::*;

impl AssembleFn for ast::ItemFn {
    fn assemble_fn(&self, c: &mut Compiler<'_>, instance_fn: bool) -> CompileResult<()> {
        let span = self.span();
        log::trace!("ItemFn => {:?}", c.source.source(span));

        let mut patterns = Vec::new();
        let mut first = true;

        for (arg, _) in &self.args {
            let span = arg.span();

            match arg {
                ast::FnArg::SelfValue(s) => {
                    if !instance_fn || !first {
                        return Err(CompileError::new(span, CompileErrorKind::UnsupportedSelf));
                    }

                    let span = s.span();
                    c.scopes.new_var("self", span)?;
                }
                ast::FnArg::Pat(pat) => {
                    let offset = c.scopes.decl_anon(pat.span())?;
                    patterns.push((pat, offset));
                }
            }

            first = false;
        }

        for (pat, offset) in patterns {
            c.compile_pat_offset(pat, offset)?;
        }

        if self.body.statements.is_empty() {
            let total_var_count = c.scopes.total_var_count(span)?;
            c.locals_pop(total_var_count, span);
            c.asm.push(Inst::ReturnUnit, span);
            return Ok(());
        }

        if !self.body.produces_nothing() {
            self.body.assemble(c, Needs::Value)?.apply(c)?;

            let total_var_count = c.scopes.total_var_count(span)?;
            c.locals_clean(total_var_count, span);
            c.asm.push(Inst::Return, span);
        } else {
            self.body.assemble(c, Needs::None)?.apply(c)?;

            let total_var_count = c.scopes.total_var_count(span)?;
            c.locals_pop(total_var_count, span);
            c.asm.push(Inst::ReturnUnit, span);
        }

        c.scopes.pop_last(span)?;
        Ok(())
    }
}