luaur-compiler 0.1.2

Luau source-to-bytecode compiler (Rust).
Documentation
use luaur_ast::records::ast_expr::AstExpr;
use luaur_ast::records::ast_expr_binary::{AstExprBinary, AstExprBinary_Op};
use luaur_ast::records::ast_expr_global::AstExprGlobal;
use luaur_ast::records::ast_expr_index_name::AstExprIndexName;
use luaur_ast::records::ast_expr_local::AstExprLocal;
use luaur_ast::records::ast_local::AstLocal;
use luaur_ast::records::ast_name::AstName;
use luaur_ast::records::ast_node::AstNode;
use luaur_ast::rtti;
use luaur_common::records::dense_hash_map::DenseHashMap;

use crate::enums::global::Global;
use crate::functions::get_global_state::get_global_state;
use crate::records::builtin::Builtin;
use crate::records::variable::Variable;

pub fn get_builtin(
    node: *mut AstExpr,
    globals: &DenseHashMap<AstName, Global>,
    variables: &DenseHashMap<*mut AstLocal, Variable>,
) -> Builtin {
    let node_ptr = node;
    if node_ptr.is_null() {
        return Builtin::default();
    }

    let expr_local = unsafe { rtti::ast_node_as::<AstExprLocal>(node_ptr as *mut AstNode) };
    if !expr_local.is_null() {
        let expr = unsafe { &*expr_local };
        if let Some(v) = variables.find(&expr.local) {
            if !v.written && !v.init.is_null() {
                return get_builtin(v.init, globals, variables);
            }
        }
        return Builtin::default();
    }

    let expr_index = unsafe { rtti::ast_node_as::<AstExprIndexName>(node_ptr as *mut AstNode) };
    if !expr_index.is_null() {
        let expr = unsafe { &*expr_index };
        let object_local = unsafe { rtti::ast_node_as::<AstExprLocal>(expr.expr as *mut AstNode) };
        if !object_local.is_null() {
            let object = unsafe { &*object_local };
            if let Some(v) = variables.find(&object.local) {
                if !v.written && !v.init.is_null() {
                    let mut target_global: *mut AstExprGlobal = core::ptr::null_mut();

                    let global_expr =
                        unsafe { rtti::ast_node_as::<AstExprGlobal>(v.init as *mut AstNode) };
                    if !global_expr.is_null() {
                        target_global = global_expr;
                    } else {
                        let binary_expr =
                            unsafe { rtti::ast_node_as::<AstExprBinary>(v.init as *mut AstNode) };
                        if !binary_expr.is_null() {
                            let cond = unsafe { &*binary_expr };
                            if cond.op == AstExprBinary_Op::Or {
                                target_global = unsafe {
                                    rtti::ast_node_as::<AstExprGlobal>(cond.left as *mut AstNode)
                                };
                            }
                        }
                    }

                    if !target_global.is_null() {
                        let global = unsafe { &*target_global };
                        if get_global_state(globals, global.name) == Global::Default {
                            return Builtin {
                                object: global.name,
                                method: expr.index,
                            };
                        }
                    }
                }
            }
        }

        let object_global =
            unsafe { rtti::ast_node_as::<AstExprGlobal>(expr.expr as *mut AstNode) };
        if !object_global.is_null() {
            let object = unsafe { &*object_global };
            if get_global_state(globals, object.name) == Global::Default {
                return Builtin {
                    object: object.name,
                    method: expr.index,
                };
            }
        }

        return Builtin::default();
    }

    let expr_global = unsafe { rtti::ast_node_as::<AstExprGlobal>(node_ptr as *mut AstNode) };
    if !expr_global.is_null() {
        let expr = unsafe { &*expr_global };
        if get_global_state(globals, expr.name) == Global::Default {
            return Builtin {
                object: AstName::new(),
                method: expr.name,
            };
        }
    }

    Builtin::default()
}