neige-lua 0.1.3

一个简单的lua运行时
Documentation
use std::rc::Rc;

use neige_infra::LuaCompare;

use crate::{state::LuaState, value::value::LuaValue};

pub trait CompareApi {
    fn compare(&mut self, idx1: isize, idx2: isize, op: LuaCompare) -> bool;
    fn raw_equal(&mut self, idx1: isize, idx2: isize) -> bool;
}

impl CompareApi for LuaState {
    fn compare(&mut self, idx1: isize, idx2: isize, op: LuaCompare) -> bool {
        let a = self.stack_get(idx1);
        let b = self.stack_get(idx2);
        match op {
            LuaCompare::Eq => self.eq(a, b, false),
            LuaCompare::Lt => self.lt(a, b),
            LuaCompare::Le => self.le(a, b),
        }
    }

    fn raw_equal(&mut self, idx1: isize, idx2: isize) -> bool {
        if !self.stack_is_valid(idx1) || self.stack_is_valid(idx2) {
            false
        } else {
            let a = self.stack_get(idx1);
            let b = self.stack_get(idx2);
            self.eq(a, b, true)
        }
    }
}

impl LuaState {
    fn eq(&mut self, a: LuaValue, b: LuaValue, raw: bool) -> bool {
        match (a, b) {
            (LuaValue::Nil, LuaValue::Nil) => return true,
            (LuaValue::Boolean(x), LuaValue::Boolean(y)) => x == y,
            (LuaValue::Integer(x), LuaValue::Integer(y)) => x == y,
            (LuaValue::Integer(x), LuaValue::Number(y)) => x as f64 == y,
            (LuaValue::Number(x), LuaValue::Integer(y)) => x == y as f64,
            (LuaValue::Number(x), LuaValue::Number(y)) => x == y,
            (LuaValue::Str(x), LuaValue::Str(y)) => x == y,
            (a, b) => {
                if !raw {
                    let mt = self.call_meta_method(a.clone(), b.clone(), "__eq");
                    if let Some(mt) = mt {
                        return mt.convert_to_boolean();
                    }
                }
                if let LuaValue::Table(x) = &a {
                    if let LuaValue::Table(y) = &b {
                        return Rc::ptr_eq(x, y);
                    }
                }
                panic!("comparsion error!")
            }
        }
    }

    fn lt(&mut self, a: LuaValue, b: LuaValue) -> bool {
        match (a, b) {
            (LuaValue::Integer(x), LuaValue::Integer(y)) => x < y,
            (LuaValue::Integer(x), LuaValue::Number(y)) => (x as f64) < y,
            (LuaValue::Number(x), LuaValue::Integer(y)) => x < (y as f64),
            (LuaValue::Number(x), LuaValue::Number(y)) => x < y,
            (LuaValue::Str(x), LuaValue::Str(y)) => x < y,
            (a, b) => {
                let mt = self.call_meta_method(a, b, "__lt");
                if let Some(mt) = mt {
                    return mt.convert_to_boolean();
                }

                panic!("comparsion error!")
            }
        }
    }

    fn le(&mut self, a: LuaValue, b: LuaValue) -> bool {
        match (a, b) {
            (LuaValue::Integer(x), LuaValue::Integer(y)) => x <= y,
            (LuaValue::Integer(x), LuaValue::Number(y)) => (x as f64) <= y,
            (LuaValue::Number(x), LuaValue::Integer(y)) => x <= (y as f64),
            (LuaValue::Number(x), LuaValue::Number(y)) => x <= y,
            (LuaValue::Str(x), LuaValue::Str(y)) => x <= y,
            (a, b) => {
                let mt = self.call_meta_method(a.clone(), b.clone(), "__le");
                if let Some(mt) = mt {
                    return mt.convert_to_boolean();
                }
                let mt = self.call_meta_method(b, a, "__lt");
                if let Some(mt) = mt {
                    return mt.convert_to_boolean();
                }
                panic!("comparsion error!");
            }
        }
    }
}