From 9da82cde2a504ec3e2527aa8db73db3fbdf1bff6 Mon Sep 17 00:00:00 2001 From: Artemy Date: Mon, 8 Aug 2022 18:31:26 +0300 Subject: [PATCH] feat: scopes of visibility, delete variable now, after exiting the scope (loop, if), all the variables that were in it are deleted --- examples/example.json5 | 1 - src/interpreter.rs | 91 +++++++++++++++++++++++++++++++++--------- src/main.rs | 1 + src/types.rs | 7 ++++ 4 files changed, 80 insertions(+), 20 deletions(-) create mode 100644 src/types.rs diff --git a/examples/example.json5 b/examples/example.json5 index 9c7b92a..efaf3d7 100644 --- a/examples/example.json5 +++ b/examples/example.json5 @@ -179,7 +179,6 @@ body: ["break"], }, }, - { assign: { num: { calc: [{ var: "num" }, "+", 1] }, diff --git a/src/interpreter.rs b/src/interpreter.rs index ac9ace2..0f2f8dd 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,3 +1,4 @@ +use crate::types::*; use colored::*; use json5; use serde_json::{json, Map, Value}; @@ -6,8 +7,9 @@ use std::io::{self, Write}; use std::{thread, time}; pub struct Interpreter { input: String, - vars: HashMap, + vars: HashMap, pos: usize, + scope: usize, } impl Interpreter { @@ -16,6 +18,7 @@ impl Interpreter { input, vars: HashMap::new(), pos: 1, + scope: 0, } } @@ -112,6 +115,14 @@ impl Interpreter { self.error("Unsupported data type for the `var` argument, must be a string"); } }, + "delete" => match value { + Value::String(value) => { + self.delete(value); + } + _ => { + self.error("Unsupported data type for the `delete` argument, must be a string"); + } + }, "input" => match value { Value::String(value) => { return self.input(value); @@ -273,6 +284,7 @@ impl Interpreter { } fn run_nodes(&mut self, arr: &Vec) -> String { + self.scope += 1; for command in arr { let to_do = self.eval_node(command); match to_do { @@ -280,19 +292,38 @@ impl Interpreter { _ => {} } } + self.delete_last_scope(); + self.scope -= 1; "end".to_string() } + fn delete_last_scope(&mut self) { + let vars = self.vars.clone().into_iter(); + for (k, v) in vars { + if v.scope == self.scope { + self.delete(&k); + } + } + } + fn define(&mut self, vars: &Map) { for (name, value) in vars { if !self.var_exists(&name) { match value { Value::Object(_) => { let value = self.eval_node(value); - self.vars.insert(name.to_string(), value); + self.vars.insert( + name.to_string(), + Var { + scope: self.scope, + body: value, + }, + ); } _ => { - self.vars.insert(name.to_string(), value.clone()); + self.vars.insert( + name.to_string(), + Var { } } } else { @@ -302,14 +333,33 @@ impl Interpreter { } } - fn delete(&mut self, var_name: &String) {} + fn delete(&mut self, var_name: &String) { + if self.var_exists(var_name) { + self.vars.remove(var_name); + } else { + self.error(&format!( + "The variable {} does not exist and cannot be deleted", + var_name + )); + panic!(); + } + } - fn get_var(&mut self, var_name: &String) { + fn get_var(&mut self, var_name: &String) -> Value { let var = self.vars.get(var_name); match var { - Some(var) => { - var.clone(); + Some(var) => var.body.clone(), + None => { + self.error(&format!("The variable {} does not exist", var_name)); + panic!(); } + } + } + + fn get_var_scope(&mut self, var_name: &String) -> usize { + let var = self.vars.get(var_name); + match var { + Some(var) => var.scope, None => { self.error(&format!("The variable {} does not exist", var_name)); panic!(); @@ -319,19 +369,22 @@ impl Interpreter { fn assign(&mut self, vars: &Map) { for (name, value) in vars { - if self.var_exists(&name) { - match value { - Value::Object(_) => { - let value = self.eval_node(value); - self.vars.insert(name.to_string(), value); - } - _ => { - self.vars.insert(name.to_string(), value.clone()); - } + let scope = self.get_var_scope(name); + match value { + Value::Object(_) => { + let value = self.eval_node(value); + self.vars + .insert(name.to_string(), Var { scope, body: value }); + } + _ => { + self.vars.insert( + name.to_string(), + Var { + scope, + body: value.clone(), + }, + ); } - } else { - self.error(&format!("The variable {} does not exist, use define", name)); - panic!(); } } } diff --git a/src/main.rs b/src/main.rs index 39f459f..6f9180c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use clap::Parser; use std::fs; use std::time::Instant; +mod types; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Args { diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..6eee30c --- /dev/null +++ b/src/types.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Var { + pub scope: usize, + pub body: serde_json::Value, +}