luaur-compiler 0.1.3

Luau source-to-bytecode compiler (Rust).
Documentation
use crate::records::compile_error::CompileError;
use crate::records::compiler::Compiler;
use crate::records::undefined_local_visitor::UndefinedLocalVisitor;
use luaur_ast::records::ast_expr::AstExpr;
use luaur_ast::records::ast_stat::AstStat;
use luaur_ast::records::ast_stat_block::AstStatBlock;
use luaur_ast::records::ast_stat_local::AstStatLocal;
use luaur_ast::records::ast_stat_local_function::AstStatLocalFunction;
use luaur_ast::rtti;

impl Compiler {
    pub fn validate_continue_until(
        &mut self,
        cont: *mut AstStat,
        condition: *mut AstExpr,
        body: *mut AstStatBlock,
        start: usize,
    ) {
        let mut visitor = UndefinedLocalVisitor {
            self_: self as *mut Compiler,
            undef: core::ptr::null_mut(),
            locals: luaur_common::records::dense_hash_set::DenseHashSet::new(core::ptr::null_mut()),
        };

        unsafe {
            let body_ref = &*body;
            for i in start..body_ref.body.size {
                let stat = *body_ref.body.data.add(i);
                let local_stat = rtti::ast_node_as::<AstStatLocal>(stat as *mut _);
                if !local_stat.is_null() {
                    for &var in (*local_stat).vars.iter() {
                        visitor.locals.insert(var);
                    }
                } else {
                    let func_stat = rtti::ast_node_as::<AstStatLocalFunction>(stat as *mut _);
                    if !func_stat.is_null() {
                        visitor.locals.insert((*func_stat).name);
                    }
                }
            }

            luaur_ast::visit::ast_expr_visit(condition, &mut visitor);

            if !visitor.undef.is_null() {
                CompileError::raise(
                    &(*condition).base.location,
                    format_args!(
                        "Local {} used in the repeat..until condition is undefined because continue statement on line {} jumps over it",
                        core::ffi::CStr::from_ptr((*visitor.undef).name.value).to_string_lossy(),
                        (*cont).base.location.begin.line + 1
                    )
                );
            }
        }
    }
}