Skip to main content

luaur_compiler/methods/
compiler_validate_continue_until.rs

1use crate::records::compile_error::CompileError;
2use crate::records::compiler::Compiler;
3use crate::records::undefined_local_visitor::UndefinedLocalVisitor;
4use luaur_ast::records::ast_expr::AstExpr;
5use luaur_ast::records::ast_stat::AstStat;
6use luaur_ast::records::ast_stat_block::AstStatBlock;
7use luaur_ast::records::ast_stat_local::AstStatLocal;
8use luaur_ast::records::ast_stat_local_function::AstStatLocalFunction;
9use luaur_ast::rtti;
10
11impl Compiler {
12    pub fn validate_continue_until(
13        &mut self,
14        cont: *mut AstStat,
15        condition: *mut AstExpr,
16        body: *mut AstStatBlock,
17        start: usize,
18    ) {
19        let mut visitor = UndefinedLocalVisitor {
20            self_: self as *mut Compiler,
21            undef: core::ptr::null_mut(),
22            locals: luaur_common::records::dense_hash_set::DenseHashSet::new(core::ptr::null_mut()),
23        };
24
25        unsafe {
26            let body_ref = &*body;
27            for i in start..body_ref.body.size {
28                let stat = *body_ref.body.data.add(i);
29                let local_stat = rtti::ast_node_as::<AstStatLocal>(stat as *mut _);
30                if !local_stat.is_null() {
31                    for &var in (*local_stat).vars.iter() {
32                        visitor.locals.insert(var);
33                    }
34                } else {
35                    let func_stat = rtti::ast_node_as::<AstStatLocalFunction>(stat as *mut _);
36                    if !func_stat.is_null() {
37                        visitor.locals.insert((*func_stat).name);
38                    }
39                }
40            }
41
42            luaur_ast::visit::ast_expr_visit(condition, &mut visitor);
43
44            if !visitor.undef.is_null() {
45                CompileError::raise(
46                    &(*condition).base.location,
47                    format_args!(
48                        "Local {} used in the repeat..until condition is undefined because continue statement on line {} jumps over it",
49                        core::ffi::CStr::from_ptr((*visitor.undef).name.value).to_string_lossy(),
50                        (*cont).base.location.begin.line + 1
51                    )
52                );
53            }
54        }
55    }
56}