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

117 lines
3.5 KiB
Rust

use std::io::{self, Write};
use std::fs;
use serde_json;
use crate::lexer::{LexerInfo, LexResult, lexical_analysis};
use crate::print_version;
use crate::interpreter::{InterpreterState, StackValue};
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 {
StackValue::Identifier(id) => {
println!("#0: ::{}", id.name);
}
StackValue::I64(v) => println!("#0: {}", v),
StackValue::I32(v) => println!("#0: {}:i32", v),
StackValue::I16(v) => println!("#0: {}:i16", v),
StackValue::I8(v) => println!("#0: {}:i8", v),
StackValue::U64(v) => println!("#0: {}:u64", v),
StackValue::U32(v) => println!("#0: {}:u32", v),
StackValue::U16(v) => println!("#0: {}:u16", v),
StackValue::U8(v) => println!("#0: {}:u8", v),
StackValue::F32(v) => println!("#0: {}:f32", v),
StackValue::F64(v) => println!("#0: {}", v),
StackValue::Character(ch) => println!("#0: {}", ch),
StackValue::Boolean(b) => println!("#0: {}", if *b { "TRUE" } else { "FALSE" }),
StackValue::TokenString(_) => println!("#0: <TOKEN STRING>"),
StackValue::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 = InterpreterState::new();
if !interpreter.init() {
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;
}
if let Some(file) = buf.trim_end().strip_prefix("#save ") {
match serde_json::to_string(&interpreter) {
Ok(json) => {
if let Err(err) = fs::write(file, json) {
eprintln!("Failed to save state: {}", err);
} else {
println!("State saved to {}", file);
}
}
Err(err) => eprintln!("Serialization error: {}", err),
}
continue;
}
if let Some(file) = buf.trim_end().strip_prefix("#load ") {
match fs::read_to_string(file) {
Ok(json) => match serde_json::from_str(&json) {
Ok(state) => {
interpreter = state;
println!("State restored from {}", file);
}
Err(err) => eprintln!("Deserialization error: {}", err),
},
Err(err) => eprintln!("Failed to read file: {}", err),
}
continue;
}
let code = buf.clone();
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME, code.clone());
let result = lexical_analysis(&mut lexer_info);
match result {
LexResult::Ok(tokens) => {
for token in tokens {
if !interpreter.execute(&token) {
eprintln!("A runtime error occured!");
break;
}
}
print_top_of_stack(&interpreter);
}
LexResult::Err(err) => {
dbg!(err);
}
}
}
}