feat: scopes of visibility, delete variable

now, after exiting the scope (loop, if), all the variables that were in it are deleted
This commit is contained in:
Artemy 2022-08-08 18:31:26 +03:00
parent fdd7e2abc8
commit 9da82cde2a
4 changed files with 80 additions and 20 deletions

View file

@ -179,7 +179,6 @@
body: ["break"], body: ["break"],
}, },
}, },
{ {
assign: { assign: {
num: { calc: [{ var: "num" }, "+", 1] }, num: { calc: [{ var: "num" }, "+", 1] },

View file

@ -1,3 +1,4 @@
use crate::types::*;
use colored::*; use colored::*;
use json5; use json5;
use serde_json::{json, Map, Value}; use serde_json::{json, Map, Value};
@ -6,8 +7,9 @@ use std::io::{self, Write};
use std::{thread, time}; use std::{thread, time};
pub struct Interpreter { pub struct Interpreter {
input: String, input: String,
vars: HashMap<String, Value>, vars: HashMap<String, Var>,
pos: usize, pos: usize,
scope: usize,
} }
impl Interpreter { impl Interpreter {
@ -16,6 +18,7 @@ impl Interpreter {
input, input,
vars: HashMap::new(), vars: HashMap::new(),
pos: 1, pos: 1,
scope: 0,
} }
} }
@ -112,6 +115,14 @@ impl Interpreter {
self.error("Unsupported data type for the `var` argument, must be a string"); 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 { "input" => match value {
Value::String(value) => { Value::String(value) => {
return self.input(value); return self.input(value);
@ -273,6 +284,7 @@ impl Interpreter {
} }
fn run_nodes(&mut self, arr: &Vec<Value>) -> String { fn run_nodes(&mut self, arr: &Vec<Value>) -> String {
self.scope += 1;
for command in arr { for command in arr {
let to_do = self.eval_node(command); let to_do = self.eval_node(command);
match to_do { match to_do {
@ -280,19 +292,38 @@ impl Interpreter {
_ => {} _ => {}
} }
} }
self.delete_last_scope();
self.scope -= 1;
"end".to_string() "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<String, Value>) { fn define(&mut self, vars: &Map<String, Value>) {
for (name, value) in vars { for (name, value) in vars {
if !self.var_exists(&name) { if !self.var_exists(&name) {
match value { match value {
Value::Object(_) => { Value::Object(_) => {
let value = self.eval_node(value); 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 { } 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); let var = self.vars.get(var_name);
match var { match var {
Some(var) => { Some(var) => var.body.clone(),
var.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 => { None => {
self.error(&format!("The variable {} does not exist", var_name)); self.error(&format!("The variable {} does not exist", var_name));
panic!(); panic!();
@ -319,20 +369,23 @@ impl Interpreter {
fn assign(&mut self, vars: &Map<String, Value>) { fn assign(&mut self, vars: &Map<String, Value>) {
for (name, value) in vars { for (name, value) in vars {
if self.var_exists(&name) { let scope = self.get_var_scope(name);
match value { match value {
Value::Object(_) => { Value::Object(_) => {
let value = self.eval_node(value); let value = self.eval_node(value);
self.vars.insert(name.to_string(), value); self.vars
.insert(name.to_string(), Var { scope, body: value });
} }
_ => { _ => {
self.vars.insert(name.to_string(), value.clone()); self.vars.insert(
name.to_string(),
Var {
scope,
body: value.clone(),
},
);
} }
} }
} else {
self.error(&format!("The variable {} does not exist, use define", name));
panic!();
}
} }
} }

View file

@ -1,6 +1,7 @@
use clap::Parser; use clap::Parser;
use std::fs; use std::fs;
use std::time::Instant; use std::time::Instant;
mod types;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)] #[clap(author, version, about, long_about = None)]
struct Args { struct Args {

7
src/types.rs Normal file
View file

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Var {
pub scope: usize,
pub body: serde_json::Value,
}