Made interpreter state json serializable in Rust port
This commit is contained in:
parent
7b57807fc7
commit
dc5d75cf75
|
|
@ -6,6 +6,8 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bitflags = "2.4"
|
||||
rand = "0.8"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.4"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
use crate::interpreter::{InterpreterState, StackValue, FunctionItem};
|
||||
use crate::interpreter::{
|
||||
InterpreterState,
|
||||
StackValue,
|
||||
FunctionItem,
|
||||
BuiltinFunction,
|
||||
BuiltinFn,
|
||||
};
|
||||
use crate::lexer::{Token, Identifier};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -1005,13 +1011,73 @@ pub fn builtin_type_of(state: &mut InterpreterState) -> bool {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn lookup_builtin(name: &str) -> Option<BuiltinFn> {
|
||||
if name == "+" { Some(builtin_addition) }
|
||||
else if name == "-" { Some(builtin_subtraction) }
|
||||
else if name == "*" { Some(builtin_multiplication) }
|
||||
else if name == "/" { Some(builtin_division) }
|
||||
else if name == "%" { Some(builtin_modulus) }
|
||||
else if name == "^" { Some(builtin_exponential) }
|
||||
else if name == ">" { Some(builtin_greater_than) }
|
||||
else if name == ">=" { Some(builtin_greater_than_or_equal_to) }
|
||||
else if name == "<" { Some(builtin_less_than) }
|
||||
else if name == "<=" { Some(builtin_less_than_or_equal_to) }
|
||||
else if name == "==" { Some(builtin_equal_to) }
|
||||
else if name == "!=" { Some(builtin_not_equal_to) }
|
||||
else if name == "abs" { Some(builtin_abs) }
|
||||
else if name == "acos" { Some(builtin_acos) }
|
||||
else if name == "asin" { Some(builtin_asin) }
|
||||
else if name == "atan" { Some(builtin_atan) }
|
||||
else if name == "atan2" { Some(builtin_atan2) }
|
||||
else if name == "ceil" { Some(builtin_ceil) }
|
||||
else if name == "floor" { Some(builtin_floor) }
|
||||
else if name == "round" { Some(builtin_round) }
|
||||
else if name == "sqrt" { Some(builtin_sqrt) }
|
||||
else if name == "sin" { Some(builtin_sin) }
|
||||
else if name == "cos" { Some(builtin_cos) }
|
||||
else if name == "tan" { Some(builtin_tan) }
|
||||
else if name == "ln" { Some(builtin_ln) }
|
||||
else if name == "log" { Some(builtin_log) }
|
||||
else if name == "and" { Some(builtin_and) }
|
||||
else if name == "or" { Some(builtin_or) }
|
||||
else if name == "not" { Some(builtin_not) }
|
||||
else if name == "bitand" { Some(builtin_bitand) }
|
||||
else if name == "bitnot" { Some(builtin_bitnot) }
|
||||
else if name == "bitor" { Some(builtin_bitor) }
|
||||
else if name == "bitxor" { Some(builtin_bitxor) }
|
||||
else if name == "shl" { Some(builtin_shl) }
|
||||
else if name == "shr" { Some(builtin_shr) }
|
||||
else if name == "depth" { Some(builtin_depth) }
|
||||
else if name == "drop" { Some(builtin_drop) }
|
||||
else if name == "dup" { Some(builtin_dup) }
|
||||
else if name == "swap" { Some(builtin_swap) }
|
||||
else if name == "pick" { Some(builtin_pick) }
|
||||
else if name == "roll" { Some(builtin_roll) }
|
||||
else if name == "if" { Some(builtin_if) }
|
||||
else if name == "while" { Some(builtin_while) }
|
||||
else if name == "for" { Some(builtin_for) }
|
||||
else if name == "lambda" { Some(builtin_lambda) }
|
||||
else if name == "eval" { Some(builtin_eval) }
|
||||
else if name == "const" { Some(builtin_const) }
|
||||
else if name == "type_of" { Some(builtin_type_of) }
|
||||
else if name == "rand" { Some(builtin_rand) }
|
||||
else if name == "seed" { Some(builtin_seed) }
|
||||
else { None }
|
||||
}
|
||||
|
||||
// Helper to add builtin to function table
|
||||
fn register_builtin(
|
||||
functions: &mut HashMap<String, FunctionItem>,
|
||||
name: &str,
|
||||
func: fn(&mut InterpreterState) -> bool,
|
||||
) {
|
||||
functions.insert(name.to_string(), FunctionItem::Builtin(func));
|
||||
functions.insert(name.to_string(), FunctionItem::Builtin(BuiltinFunction {
|
||||
name: name.to_string(),
|
||||
function: match lookup_builtin(name) {
|
||||
Some(func) => func,
|
||||
None => panic!("Builtin Not Found!"),
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
pub fn load_builtins(state: &mut InterpreterState) -> bool {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use std::collections::HashMap;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::lexer::*; // Identifier, Token, TokenString, etc.
|
||||
use crate::builtin::load_builtins;
|
||||
use crate::builtin::{lookup_builtin, load_builtins};
|
||||
|
||||
pub type BuiltinFn = fn(&mut InterpreterState) -> bool;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum StackValue {
|
||||
Identifier(Identifier),
|
||||
|
||||
|
|
@ -31,12 +32,47 @@ pub enum StackValue {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FunctionItem {
|
||||
TokenString(TokenString),
|
||||
Builtin(BuiltinFn),
|
||||
pub struct BuiltinFunction {
|
||||
pub name: String,
|
||||
pub function: BuiltinFn,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
impl BuiltinFunction {
|
||||
fn call(&self, interpreter: &mut InterpreterState) -> bool {
|
||||
(self.function)(interpreter)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for BuiltinFunction {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.name)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for BuiltinFunction {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let name = String::deserialize(deserializer)?;
|
||||
|
||||
let function = lookup_builtin(&name)
|
||||
.ok_or_else(|| serde::de::Error::custom(format!("Unknown builtin: {}", name)))?;
|
||||
|
||||
Ok(BuiltinFunction { name, function })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum FunctionItem {
|
||||
TokenString(TokenString),
|
||||
Builtin(BuiltinFunction),
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InterpreterState {
|
||||
pub stack: Vec<StackValue>,
|
||||
pub functions: HashMap<String, FunctionItem>,
|
||||
|
|
@ -96,7 +132,7 @@ impl InterpreterState {
|
|||
};
|
||||
|
||||
match item {
|
||||
FunctionItem::Builtin(f) => f(self),
|
||||
FunctionItem::Builtin(f) => f.call(self),
|
||||
FunctionItem::TokenString(ts) => self.execute_token_string(&ts),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LexerInfo {
|
||||
pub filename: String,
|
||||
|
|
@ -60,7 +62,7 @@ impl LexerInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Identifier {
|
||||
pub name: String,
|
||||
pub is_literal: bool,
|
||||
|
|
@ -93,7 +95,7 @@ pub struct ShapedArray {
|
|||
pub _shape: Vec<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TokenString {
|
||||
pub tokens: Vec<Token>,
|
||||
}
|
||||
|
|
@ -121,7 +123,7 @@ pub enum StructValue {
|
|||
_Token(Token),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Token {
|
||||
Eof,
|
||||
Identifier(Identifier),
|
||||
|
|
@ -136,10 +138,13 @@ pub enum Token {
|
|||
Float(f32),
|
||||
Double(f64),
|
||||
Character(u8),
|
||||
#[serde(skip)]
|
||||
StringLiteral(String),
|
||||
Boolean(bool),
|
||||
#[serde(skip)]
|
||||
Array(ShapedArray),
|
||||
TokenString(TokenString),
|
||||
#[serde(skip)]
|
||||
TypeTuple(TypeTuple),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use std::io::{self, Write};
|
||||
use std::fs;
|
||||
use serde_json;
|
||||
|
||||
use crate::lexer::{LexerInfo, LexResult, lexical_analysis};
|
||||
use crate::print_version;
|
||||
|
|
@ -62,6 +64,34 @@ pub fn repl() -> i32 {
|
|||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue