luaur-compiler 0.1.3

Luau source-to-bytecode compiler (Rust).
Documentation
use luaur_ast::records::ast_expr::AstExpr;
use luaur_ast::records::ast_node::AstNode;
use luaur_ast::records::ast_stat::AstStat;
use luaur_ast::records::ast_stat_block::AstStatBlock;
use luaur_ast::records::ast_stat_break::AstStatBreak;
use luaur_ast::records::ast_stat_continue::AstStatContinue;
use luaur_ast::records::ast_stat_if::AstStatIf;
use luaur_ast::records::ast_stat_return::AstStatReturn;
use luaur_common::records::dense_hash_map::DenseHashMap;

use crate::functions::is_constant_false::is_constant_false;
use crate::functions::is_constant_true::is_constant_true;
use crate::records::constant::Constant;

pub fn always_terminates(
    constants: &DenseHashMap<*mut AstExpr, Constant>,
    node: *mut AstStat,
) -> bool {
    unsafe {
        let stat_block = luaur_ast::rtti::ast_node_as::<AstStatBlock>(node as *mut AstNode);
        if !stat_block.is_null() {
            let body = (*stat_block).body;
            for i in 0..body.size {
                let item = *body.data.add(i);
                if always_terminates(constants, item) {
                    return true;
                }
            }
            return false;
        }

        if luaur_ast::rtti::ast_node_is::<AstStatReturn>(&*(node as *mut AstNode)) {
            return true;
        }

        if luaur_ast::rtti::ast_node_is::<AstStatBreak>(&*(node as *mut AstNode))
            || luaur_ast::rtti::ast_node_is::<AstStatContinue>(&*(node as *mut AstNode))
        {
            return true;
        }

        let stat_if = luaur_ast::rtti::ast_node_as::<AstStatIf>(node as *mut AstNode);
        if !stat_if.is_null() {
            let condition = (*stat_if).condition;
            let thenbody = (*stat_if).thenbody;
            let elsebody = (*stat_if).elsebody;

            if is_constant_true(constants, condition) {
                return always_terminates(constants, thenbody as *mut AstStat);
            }

            if is_constant_false(constants, condition) && !elsebody.is_null() {
                return always_terminates(constants, elsebody);
            }

            return !elsebody.is_null()
                && always_terminates(constants, thenbody as *mut AstStat)
                && always_terminates(constants, elsebody);
        }

        false
    }
}