luaur_compiler/methods/
compiler_validate_continue_until.rs1use 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}