Made interpreter state json serializable in Rust port
This commit is contained in:
parent
7b57807fc7
commit
dc5d75cf75
|
|
@ -6,6 +6,8 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "2.4"
|
bitflags = "2.4"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
rustc_version = "0.4"
|
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 crate::lexer::{Token, Identifier};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
@ -1005,13 +1011,73 @@ pub fn builtin_type_of(state: &mut InterpreterState) -> bool {
|
||||||
true
|
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
|
// Helper to add builtin to function table
|
||||||
fn register_builtin(
|
fn register_builtin(
|
||||||
functions: &mut HashMap<String, FunctionItem>,
|
functions: &mut HashMap<String, FunctionItem>,
|
||||||
name: &str,
|
name: &str,
|
||||||
func: fn(&mut InterpreterState) -> bool,
|
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 {
|
pub fn load_builtins(state: &mut InterpreterState) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use crate::lexer::*; // Identifier, Token, TokenString, etc.
|
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;
|
pub type BuiltinFn = fn(&mut InterpreterState) -> bool;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum StackValue {
|
pub enum StackValue {
|
||||||
Identifier(Identifier),
|
Identifier(Identifier),
|
||||||
|
|
||||||
|
|
@ -31,12 +32,47 @@ pub enum StackValue {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FunctionItem {
|
pub struct BuiltinFunction {
|
||||||
TokenString(TokenString),
|
pub name: String,
|
||||||
Builtin(BuiltinFn),
|
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 struct InterpreterState {
|
||||||
pub stack: Vec<StackValue>,
|
pub stack: Vec<StackValue>,
|
||||||
pub functions: HashMap<String, FunctionItem>,
|
pub functions: HashMap<String, FunctionItem>,
|
||||||
|
|
@ -96,7 +132,7 @@ impl InterpreterState {
|
||||||
};
|
};
|
||||||
|
|
||||||
match item {
|
match item {
|
||||||
FunctionItem::Builtin(f) => f(self),
|
FunctionItem::Builtin(f) => f.call(self),
|
||||||
FunctionItem::TokenString(ts) => self.execute_token_string(&ts),
|
FunctionItem::TokenString(ts) => self.execute_token_string(&ts),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LexerInfo {
|
pub struct LexerInfo {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
|
|
@ -60,7 +62,7 @@ impl LexerInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Identifier {
|
pub struct Identifier {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub is_literal: bool,
|
pub is_literal: bool,
|
||||||
|
|
@ -93,7 +95,7 @@ pub struct ShapedArray {
|
||||||
pub _shape: Vec<usize>,
|
pub _shape: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct TokenString {
|
pub struct TokenString {
|
||||||
pub tokens: Vec<Token>,
|
pub tokens: Vec<Token>,
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +123,7 @@ pub enum StructValue {
|
||||||
_Token(Token),
|
_Token(Token),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum Token {
|
pub enum Token {
|
||||||
Eof,
|
Eof,
|
||||||
Identifier(Identifier),
|
Identifier(Identifier),
|
||||||
|
|
@ -136,10 +138,13 @@ pub enum Token {
|
||||||
Float(f32),
|
Float(f32),
|
||||||
Double(f64),
|
Double(f64),
|
||||||
Character(u8),
|
Character(u8),
|
||||||
|
#[serde(skip)]
|
||||||
StringLiteral(String),
|
StringLiteral(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
#[serde(skip)]
|
||||||
Array(ShapedArray),
|
Array(ShapedArray),
|
||||||
TokenString(TokenString),
|
TokenString(TokenString),
|
||||||
|
#[serde(skip)]
|
||||||
TypeTuple(TypeTuple),
|
TypeTuple(TypeTuple),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
use std::fs;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
use crate::lexer::{LexerInfo, LexResult, lexical_analysis};
|
use crate::lexer::{LexerInfo, LexResult, lexical_analysis};
|
||||||
use crate::print_version;
|
use crate::print_version;
|
||||||
|
|
@ -62,6 +64,34 @@ pub fn repl() -> i32 {
|
||||||
return 0;
|
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 code = buf.clone();
|
||||||
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME, code.clone());
|
let mut lexer_info = LexerInfo::new(REPL_FILE_NAME, code.clone());
|
||||||
let result = lexical_analysis(&mut lexer_info);
|
let result = lexical_analysis(&mut lexer_info);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue