use std::{cell::RefCell, path::PathBuf, rc::Rc}; use crate::{ ast::{Block, Function, LuaNumber}, token_stream::{ TokenStream, lexer::{Token, tokenize}, }, vm::{RuntimeError, RustFunction, VirtualMachine}, }; mod ast; mod compile; mod token_stream; mod vm; static TEST: &str = include_str!("../examples/test.lua"); #[derive(Debug)] pub struct Max; impl RustFunction for Max { fn execute(&self, parameters: Vec) -> Result, RuntimeError> { let lhs = parameters.get(0).cloned().unwrap_or(vm::Value::Nil); let rhs = parameters.get(1).cloned().unwrap_or(vm::Value::Nil); match lhs.lt(&rhs)? { vm::Value::Number(value) => { let res = LuaNumber::from_bits(value); Ok(vec![if res > 0. { rhs } else { lhs }]) } _ => Ok(vec![vm::Value::Nil]), } } } #[derive(Debug)] pub struct Print; impl RustFunction for Print { fn execute(&self, parameters: Vec) -> Result, RuntimeError> { println!("{:?}", parameters); Ok(Vec::new()) } } fn main() { let file_path = PathBuf::from("../examples/test.lua"); let tokens = tokenize(TEST).unwrap(); let mut stream = TokenStream::from(&file_path, &tokens); dbg!(&tokens); let chunk = stream.parse::().unwrap(); stream.expect(Token::Eof).unwrap(); dbg!(&chunk); let constants = chunk .find_constants(&mut Default::default()) .into_iter() .collect::>(); dbg!(&constants); let mut state = compile::State { constants: constants.clone(), prototypes: Vec::new(), }; let mut scope = Default::default(); let instructions = chunk.compile(&mut state, &mut scope); let mut vm = VirtualMachine { environment: Default::default(), constants, prototypes: Default::default(), }; vm.prototypes.insert(0, instructions); for (i, prototype) in state.prototypes.into_iter().enumerate() { vm.prototypes.insert((i + 1) as u32, prototype); } dbg!(&vm.prototypes); vm.environment.borrow_mut().globals.insert( vm::Constant::String("max".to_owned()), vm::Value::RustFunction(Rc::new(RefCell::new(Max))), ); vm.environment.borrow_mut().globals.insert( vm::Constant::String("print".to_owned()), vm::Value::RustFunction(Rc::new(RefCell::new(Print))), ); let closure = vm.create_closure(0); let mut run = closure.run(Vec::new()); while run.next().unwrap().is_none() {} dbg!(&vm.environment.borrow().globals); }