use std::collections::HashMap; use crate::lexer::*; // Identifier, Token, TokenString, etc. pub type BuiltinFn = fn(&mut InterpreterState) -> bool; #[derive(Debug, Clone)] pub enum StackValue { Identifier(Identifier), I64(i64), I32(i32), I16(i16), I8(i8), U64(u64), U32(u32), U16(u16), U8(u8), Float(f32), Double(f64), Character(u8), Boolean(bool), TokenString(TokenString), Callable(FunctionItem), } #[derive(Debug, Clone)] pub enum FunctionItem { TokenString(TokenString), Builtin(BuiltinFn), } #[derive(Debug)] pub struct InterpreterState { pub stack: Vec, pub functions: HashMap, } impl InterpreterState { pub fn new() -> Self { Self { stack: Vec::new(), functions: HashMap::new(), } } } pub fn push_token(state: &mut InterpreterState, token: Token) -> bool { let value = match token { Token::Eof => return true, Token::Identifier(id) => { StackValue::Identifier(id) } Token::I64(v) => StackValue::I64(v), Token::I32(v) => StackValue::I32(v), Token::I16(v) => StackValue::I16(v), Token::I8(v) => StackValue::I8(v), Token::U64(v) => StackValue::U64(v), Token::U32(v) => StackValue::U32(v), Token::U16(v) => StackValue::U16(v), Token::U8(v) => StackValue::U8(v), Token::Float(v) => StackValue::Float(v), Token::Double(v) => StackValue::Double(v), Token::Character(c) => StackValue::Character(c), Token::Boolean(b) => StackValue::Boolean(b), Token::TokenString(ts) => StackValue::TokenString(ts), Token::StringLiteral(_) | Token::Array(_) | Token::TypeTuple(_) => return false, }; state.stack.push(value); true } pub fn execute_func(state: &mut InterpreterState, key: &str) -> bool { let item = match state.functions.get(key) { Some(v) => v.clone(), None => return false, }; match item { FunctionItem::Builtin(f) => f(state), FunctionItem::TokenString(ts) => execute_token_string(state, ts), } } pub fn execute_token_string(state: &mut InterpreterState, ts: TokenString) -> bool { for token in ts.tokens { if let Token::Identifier(id) = &token { if !id.is_literal { if !execute_func(state, &id.name) { return false; } continue; } } if !push_token(state, token) { return false; } } true } pub fn execute(state: &mut InterpreterState, token: Token) -> bool { match token { Token::Identifier(id) if !id.is_literal => { execute_func(state, &id.name) } _ => push_token(state, token), } } pub fn interpreter_create(load_builtins: fn(&mut InterpreterState) -> bool) -> Option { let mut state = InterpreterState::new(); if !load_builtins(&mut state) { return None; } Some(state) }