YREA-SLS/SLS_Rust/sls/src/repl.rs

105 lines
3.2 KiB
Rust

use std::io::{self, Write};
use crate::lexer::{Lexer, LexerInfo, lexical_analysis};
use crate::meta::print_version;
use crate::interpreter::{InterpreterState, StackType};
use crate::string::{SlsStr};
use crate::errors::{LexerTokenResult, LexerResult};
static REPL_FILE_NAME: &str = "<STDIN>";
fn print_top_of_stack(state: &InterpreterState) {
let Some(item) = state.stack_top() else {
println!("#0: <STACK IS EMPTY>");
return;
};
match &item.value {
StackType::Identifier(id) => {
println!("#0: ::{}", id.name);
}
StackType::I64(v) => println!("#0: {}", v),
StackType::I32(v) => println!("#0: {}:i32", v),
StackType::I16(v) => println!("#0: {}:i16", v),
StackType::I8(v) => println!("#0: {}:i8", v),
StackType::U64(v) => println!("#0: {}:u64", v),
StackType::U32(v) => println!("#0: {}:u32", v),
StackType::U16(v) => println!("#0: {}:u16", v),
StackType::U8(v) => println!("#0: {}:u8", v),
StackType::F32(v) => println!("#0: {}:f32", v),
StackType::F64(v) => println!("#0: {}", v),
StackType::Character(ch) => println!("#0: {}", ch),
StackType::Boolean(b) => println!("#0: {}", if *b { "TRUE" } else { "FALSE" }),
StackType::TokenString(_) => println!("#0: <TOKEN STRING>"),
StackType::Callable(_) => println!("#0: <CALLABLE>"),
};
}
pub fn repl() -> i32 {
print_version();
println!("===== YREA SLS REPL =====");
println!("Type `#exit` to exit.");
io::stdout().flush().unwrap();
let mut interpreter = match InterpreterState::new() {
Some(i) => i,
None => return 1,
};
let stdin = io::stdin();
let mut buf = String::new();
loop {
buf.clear();
if stdin.read_line(&mut buf).is_err() {
return 1;
}
if buf.trim_end() == "#exit" {
return 0;
}
let code = SlsStr::from_string(buf.clone());
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME.into(), code.clone());
let result = lexical_analysis(&mut lexer_info);
match result {
LexerResult::Error(err) => {
println!("{}", err.message);
}
LexerResult::Ok(mut head) => {
let mut node = Some(head.as_mut());
while let Some(tok_node) = node {
match tok_node {
LexerTokenResult::Error(err) => {
println!("{}", err.message);
break;
}
LexerTokenResult::Token(tok) => {
if !interpreter.execute(tok) {
println!("A runtime error occurred!");
break;
}
}
LexerTokenResult::Next(_, next) => {
node = next.as_deref_mut();
continue;
}
}
node = None;
}
print_top_of_stack(&interpreter);
}
}
}
}