105 lines
3.2 KiB
Rust
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);
|
|
}
|
|
}
|
|
}
|
|
}
|