feat: define, get, assign variables

This commit is contained in:
Artemy 2022-08-03 21:30:22 +03:00
parent 4cf0471d66
commit 4a9332e34a
2 changed files with 204 additions and 118 deletions

View file

@ -1,6 +1,6 @@
use colored::*; use colored::*;
use json5; use json5;
use serde_json::{json, Value}; use serde_json::{json, Map, Value};
use std::collections::HashMap; use std::collections::HashMap;
pub struct Interpreter { pub struct Interpreter {
input: String, input: String,
@ -18,8 +18,8 @@ impl Interpreter {
} }
pub fn run(&mut self) { pub fn run(&mut self) {
let mut obj = json5::from_str::<Value>(&self.input).unwrap(); let obj = json5::from_str::<Value>(&self.input).unwrap();
let arr = obj.as_array_mut().unwrap(); let arr = obj.as_array().unwrap();
for command in arr { for command in arr {
self.eval_node(command); self.eval_node(command);
@ -27,79 +27,88 @@ impl Interpreter {
} }
} }
fn eval_node(&self, command: &mut Value) -> Value { fn eval_node(&mut self, command: &Value) -> Value {
match command { match command {
Value::Object(command) => { Value::Object(command) => {
for (name, value) in command { for (name, value) in command {
match name.as_str() { match name.as_str() {
"print" => { "print" => match value {
match value {
Value::Array(value) => { Value::Array(value) => {
self.print(value, false); self.print(value, false);
} }
Value::String(value) => { Value::String(value) => {
self.print(&mut vec![Value::String(value.to_string())], false); self.print(&vec![Value::String(value.to_string())], false);
} }
_ => { _ => {
self.error("Unsupported data type for the print argument"); self.error("Unsupported data type for the print argument");
} }
} },
return Value::Null; "println" => match value {
}
"println" => {
match value {
Value::Array(value) => { Value::Array(value) => {
self.print(value, true); self.print(value, true);
} }
Value::String(value) => { Value::String(value) => {
self.print(&mut vec![Value::String(value.to_string())], true); self.print(&vec![Value::String(value.to_string())], true);
} }
_ => { _ => {
self.error("Unsupported data type for the println argument"); self.error("Unsupported data type for the println argument");
} }
} },
return Value::Null; "calc" => match value {
}
"calc" => {
match value {
Value::Array(value) => { Value::Array(value) => {
if value.len() == 3 { if value.len() == 3 {
return self.calc(value); return self.calc(value);
} else { } else {
return Value::Null; self.error("Unsupported data type for the calc arguments");
} }
} }
_ => { _ => {
self.error("Unsupported data type for the println argument"); self.error("Unsupported data type for the calc arguments");
} }
} },
return Value::Null; "comp" => match value {
}
"comp" => {
match value {
Value::Array(value) => { Value::Array(value) => {
if value.len() == 3 { if value.len() == 3 {
return self.comp(value); return self.comp(value);
} else { } else {
return Value::Null; self.error("Unsupported data type for the comp arguments");
} }
} }
_ => { _ => {
self.error("Unsupported data type for the println argument"); self.error("Unsupported data type for the comp arguments");
} }
},
"let" => match value {
Value::Object(value) => {
return self.define(value);
} }
return Value::Null; _ => {
self.error("Unsupported data type for the let argument");
} }
},
"assign" => match value {
Value::Object(value) => {
return self.assign(value);
}
_ => {
self.error("Unsupported data type for the let argument");
}
},
"var" => match value {
Value::String(value) => {
return self.get_var(value);
}
_ => {
self.error("Unsupported data type for the let argument");
}
},
name => { name => {
self.unk_token(&name); self.unk_token(&name);
return Value::Null;
} }
} }
} }
Value::Null
} }
Value::String(name) => { Value::String(name) => match name.as_str() {
match name.as_str() {
"Exit" => { "Exit" => {
self.exit(); self.exit();
} }
@ -107,23 +116,68 @@ impl Interpreter {
self.err_exit(); self.err_exit();
} }
value => { value => {
self.print(&mut vec![Value::String(value.to_string())], false); self.print(&vec![Value::String(value.to_string())], false);
}
}
Value::Null
} }
},
Value::Array(command) => { Value::Array(command) => {
self.print(command, false); self.print(command, false);
Value::Null
} }
_ => { _ => {
self.error("Unsupported data type for the command"); self.error("Unsupported data type for the command");
}
}
return Value::Null;
}
fn define(&mut self, vars: &Map<String, Value>) -> Value {
for (name, value) in vars {
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());
}
}
}
Value::Null Value::Null
} }
fn get_var(&mut self, var_name: &String) -> Value {
let var = self.vars.get(var_name);
match var {
Some(var) => var.clone(),
None => {
self.error(&format!("The variable {} does not exist", var_name));
panic!()
}
} }
} }
fn calc(&self, value: &mut Vec<Value>) -> Value { fn assign(&mut self, vars: &Map<String, Value>) -> Value {
for (name, value) in vars {
let var = self.vars.get(name);
match var {
Some(_) => 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());
}
},
None => {
self.error(&format!("The variable {} does not exist", name));
panic!();
}
}
}
Value::Null
}
fn calc(&mut self, value: &Vec<Value>) -> Value {
let op1 = &value[0]; let op1 = &value[0];
let operation = &value[1]; let operation = &value[1];
let op2 = &value[2]; let op2 = &value[2];
@ -158,27 +212,26 @@ impl Interpreter {
} }
} }
} }
Value::Object(_) => self.calc(&mut vec![ Value::Object(_) => {
Value::Number(op1.clone()), let op1 = Value::Number(op1.clone());
operation.clone(), let op2 = self.eval_node(&op2.clone());
self.eval_node(&mut op2.clone()), self.calc(&vec![op1, operation.clone(), op2])
]), }
_ => { _ => {
self.error("Unsupported operand type for calculation"); self.error("Unsupported operand type for calculation");
panic!(); panic!();
} }
}, },
Value::Object(_) => match op2 { Value::Object(_) => match op2 {
Value::Number(_) => self.calc(&mut vec![ Value::Number(_) => {
self.eval_node(&mut op1.clone()), let op1 = self.eval_node(&op1.clone());
operation.clone(), self.calc(&vec![op1, operation.clone(), op2.clone()])
op2.clone(), }
]), Value::Object(_) => {
Value::Object(_) => self.calc(&mut vec![ let op1 = self.eval_node(&op1.clone());
self.eval_node(&mut op1.clone()), let op2 = self.eval_node(&op2.clone());
operation.clone(), self.calc(&vec![op1, operation.clone(), op2])
self.eval_node(&mut op2.clone()), }
]),
_ => { _ => {
self.error("Unsupported operand type for calculation"); self.error("Unsupported operand type for calculation");
panic!(); panic!();
@ -191,29 +244,27 @@ impl Interpreter {
} }
} }
fn comp(&self, value: &mut Vec<Value>) -> Value { fn comp(&mut self, value: &Vec<Value>) -> Value {
let op1 = &value[0]; let op1 = &value[0];
let operation = &value[1]; let operation = &value[1];
let op2 = &value[2]; let op2 = &value[2];
match op1 { match op1 {
Value::Object(_) => match op2 { Value::Object(_) => match op2 {
Value::Object(_) => self.comp(&mut vec![ Value::Object(_) => {
self.eval_node(&mut op1.clone()), let op1 = self.eval_node(&op1.clone());
operation.clone(), let op2 = self.eval_node(&op2.clone());
self.eval_node(&mut op2.clone()), self.comp(&vec![op1, operation.clone(), op2])
]), }
_ => self.comp(&mut vec![ _ => {
self.eval_node(&mut op1.clone()), let op1 = self.eval_node(&op1.clone());
operation.clone(), self.comp(&vec![op1, operation.clone(), op2.clone()])
op2.clone(), }
]),
}, },
Value::Number(op1) => match op2 { Value::Number(op1) => match op2 {
Value::Object(_) => self.comp(&mut vec![ Value::Object(_) => {
Value::Number(op1.clone()), let op2 = self.eval_node(&op2.clone());
operation.clone(), self.comp(&vec![Value::Number(op1.clone()), operation.clone(), op2])
self.eval_node(&mut op2.clone()), }
]),
Value::Number(op2) => { Value::Number(op2) => {
let op1 = op1.as_f64().unwrap(); let op1 = op1.as_f64().unwrap();
let op2 = op2.as_f64().unwrap(); let op2 = op2.as_f64().unwrap();
@ -245,11 +296,10 @@ impl Interpreter {
} }
}, },
Value::Bool(op1) => match op2 { Value::Bool(op1) => match op2 {
Value::Object(_) => self.comp(&mut vec![ Value::Object(_) => {
Value::Bool(op1.clone()), let op2 = self.eval_node(&op2.clone());
operation.clone(), self.comp(&vec![Value::Bool(op1.clone()), operation.clone(), op2])
self.eval_node(&mut op2.clone()), }
]),
Value::Bool(op2) => match operation { Value::Bool(op2) => match operation {
Value::String(operation) => match operation.as_str() { Value::String(operation) => match operation.as_str() {
"==" => json!(op1 == op2), "==" => json!(op1 == op2),
@ -279,11 +329,10 @@ impl Interpreter {
} }
}, },
_ => match op2 { _ => match op2 {
Value::Object(_) => self.comp(&mut vec![ Value::Object(_) => {
op1.clone(), let op2 = self.eval_node(&op2.clone());
operation.clone(), self.comp(&vec![op1.clone(), operation.clone(), op2])
self.eval_node(&mut op2.clone()), }
]),
_ => match operation { _ => match operation {
Value::String(operation) => match operation.as_str() { Value::String(operation) => match operation.as_str() {
@ -306,7 +355,7 @@ impl Interpreter {
} }
} }
fn print(&self, args: &mut Vec<Value>, ln: bool) { fn print(&mut self, args: &Vec<Value>, ln: bool) {
for arg in args { for arg in args {
self.print_one(arg); self.print_one(arg);
if ln == true { if ln == true {
@ -318,7 +367,7 @@ impl Interpreter {
} }
} }
fn print_one(&self, arg: &Value) { fn print_one(&mut self, arg: &Value) {
match arg { match arg {
Value::Array(args) => { Value::Array(args) => {
print!("{}", serde_json::to_string_pretty(args).unwrap()); print!("{}", serde_json::to_string_pretty(args).unwrap());
@ -333,7 +382,8 @@ impl Interpreter {
print!("{}", arg.to_string().truecolor(180, 208, 143)); print!("{}", arg.to_string().truecolor(180, 208, 143));
} }
Value::Object(arg) => { Value::Object(arg) => {
self.print_one(&self.eval_node(&mut Value::Object(arg.clone()))); let to_print = self.eval_node(&Value::Object(arg.clone()));
self.print_one(&to_print);
} }
Value::Null => { Value::Null => {
print!("{}", "null".blue()); print!("{}", "null".blue());

View file

@ -126,6 +126,42 @@
], ],
}, },
"\nCreating variables",
{
let: {
str: "A",
num: 2,
arr: ["Array", "in", "variable"],
},
},
{
let: {
calculated: { calc: [{ var: "num" }, "*", 4] },
},
},
[
"Created 4 variables with values:\n",
"str = ",
{ var: "str" },
"\nnum = ",
{ var: "num" },
"\narr = ",
{ var: "arr" },
"\ncalculated (num * 4) = ",
{ var: "calculated" },
],
"Execute calculated = calculated + 1",
{
assign: {
calculated: { calc: [{ var: "calculated" }, "+", 1] },
},
},
["After executing calculated = ", { var: "calculated" }],
// { // {
// print: [ // print: [
// { // {