138 lines
3.1 KiB
Rust
138 lines
3.1 KiB
Rust
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<StackValue>,
|
|
pub functions: HashMap<String, FunctionItem>,
|
|
}
|
|
|
|
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<InterpreterState>
|
|
{
|
|
let mut state = InterpreterState::new();
|
|
|
|
if !load_builtins(&mut state) {
|
|
return None;
|
|
}
|
|
|
|
Some(state)
|
|
}
|