mirror of
https://github.com/artegoser/ONLang
synced 2024-12-23 09:33:44 +03:00
feat: define, get, assign variables
This commit is contained in:
parent
4cf0471d66
commit
4a9332e34a
2 changed files with 204 additions and 118 deletions
|
@ -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,103 +27,157 @@ 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(&vec![Value::String(value.to_string())], false);
|
||||||
self.print(&mut 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");
|
}
|
||||||
|
},
|
||||||
|
"println" => match value {
|
||||||
|
Value::Array(value) => {
|
||||||
|
self.print(value, true);
|
||||||
|
}
|
||||||
|
Value::String(value) => {
|
||||||
|
self.print(&vec![Value::String(value.to_string())], true);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.error("Unsupported data type for the println argument");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"calc" => match value {
|
||||||
|
Value::Array(value) => {
|
||||||
|
if value.len() == 3 {
|
||||||
|
return self.calc(value);
|
||||||
|
} else {
|
||||||
|
self.error("Unsupported data type for the calc arguments");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Value::Null;
|
_ => {
|
||||||
}
|
self.error("Unsupported data type for the calc arguments");
|
||||||
"println" => {
|
}
|
||||||
match value {
|
},
|
||||||
Value::Array(value) => {
|
"comp" => match value {
|
||||||
self.print(value, true);
|
Value::Array(value) => {
|
||||||
}
|
if value.len() == 3 {
|
||||||
Value::String(value) => {
|
return self.comp(value);
|
||||||
self.print(&mut vec![Value::String(value.to_string())], true);
|
} else {
|
||||||
}
|
self.error("Unsupported data type for the comp arguments");
|
||||||
_ => {
|
|
||||||
self.error("Unsupported data type for the println argument");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Value::Null;
|
_ => {
|
||||||
}
|
self.error("Unsupported data type for the comp arguments");
|
||||||
"calc" => {
|
|
||||||
match value {
|
|
||||||
Value::Array(value) => {
|
|
||||||
if value.len() == 3 {
|
|
||||||
return self.calc(value);
|
|
||||||
} else {
|
|
||||||
return Value::Null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.error("Unsupported data type for the println argument");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Value::Null;
|
},
|
||||||
}
|
"let" => match value {
|
||||||
"comp" => {
|
Value::Object(value) => {
|
||||||
match value {
|
return self.define(value);
|
||||||
Value::Array(value) => {
|
|
||||||
if value.len() == 3 {
|
|
||||||
return self.comp(value);
|
|
||||||
} else {
|
|
||||||
return Value::Null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.error("Unsupported data type for the println argument");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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();
|
|
||||||
}
|
|
||||||
"ErrExit" => {
|
|
||||||
self.err_exit();
|
|
||||||
}
|
|
||||||
value => {
|
|
||||||
self.print(&mut vec![Value::String(value.to_string())], false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Value::Null
|
"ErrExit" => {
|
||||||
}
|
self.err_exit();
|
||||||
|
}
|
||||||
|
value => {
|
||||||
|
self.print(&vec![Value::String(value.to_string())], false);
|
||||||
|
}
|
||||||
|
},
|
||||||
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");
|
||||||
Value::Null
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
36
test.json5
36
test.json5
|
@ -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: [
|
||||||
// {
|
// {
|
||||||
|
|
Loading…
Add table
Reference in a new issue