From dc5d75cf7598ef5b48ab74de421b36412e7ccbbd Mon Sep 17 00:00:00 2001 From: Kyler Date: Thu, 4 Dec 2025 23:06:42 -0700 Subject: [PATCH] Made interpreter state json serializable in Rust port --- SLS_Rust/sls/Cargo.toml | 2 + SLS_Rust/sls/src/builtin.rs | 70 ++++++++++++++++++++++++++++++++- SLS_Rust/sls/src/interpreter.rs | 50 +++++++++++++++++++---- SLS_Rust/sls/src/lexer.rs | 11 ++++-- SLS_Rust/sls/src/repl.rs | 30 ++++++++++++++ 5 files changed, 151 insertions(+), 12 deletions(-) diff --git a/SLS_Rust/sls/Cargo.toml b/SLS_Rust/sls/Cargo.toml index 7d3fec8..47d7338 100644 --- a/SLS_Rust/sls/Cargo.toml +++ b/SLS_Rust/sls/Cargo.toml @@ -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" diff --git a/SLS_Rust/sls/src/builtin.rs b/SLS_Rust/sls/src/builtin.rs index 37a3cfd..46c23ad 100644 --- a/SLS_Rust/sls/src/builtin.rs +++ b/SLS_Rust/sls/src/builtin.rs @@ -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 { + 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, 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 { diff --git a/SLS_Rust/sls/src/interpreter.rs b/SLS_Rust/sls/src/interpreter.rs index 9c7bfc4..b1ddf9a 100644 --- a/SLS_Rust/sls/src/interpreter.rs +++ b/SLS_Rust/sls/src/interpreter.rs @@ -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(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(&self.name) + } +} + +impl<'de> Deserialize<'de> for BuiltinFunction { + fn deserialize(deserializer: D) -> Result + 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, pub functions: HashMap, @@ -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), } } diff --git a/SLS_Rust/sls/src/lexer.rs b/SLS_Rust/sls/src/lexer.rs index 8b6df6f..a199a81 100644 --- a/SLS_Rust/sls/src/lexer.rs +++ b/SLS_Rust/sls/src/lexer.rs @@ -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, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct TokenString { pub tokens: Vec, } @@ -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), } diff --git a/SLS_Rust/sls/src/repl.rs b/SLS_Rust/sls/src/repl.rs index 32d2728..5e48356 100644 --- a/SLS_Rust/sls/src/repl.rs +++ b/SLS_Rust/sls/src/repl.rs @@ -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);