117 lines
3.5 KiB
Rust
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);
|
|
}
|
|
}
|
|
}
|
|
}
|