From 86e46e96959e1e21ae8a40157894e568862e8b6f Mon Sep 17 00:00:00 2001 From: Artemy Date: Wed, 3 Aug 2022 22:59:54 +0300 Subject: [PATCH] feat: if cond, loop cycle --- src/interpreter.rs | 117 ++++++++++++++++++++++++++++++++++++++++++--- test.json5 | 34 +++++++++++++ 2 files changed, 145 insertions(+), 6 deletions(-) diff --git a/src/interpreter.rs b/src/interpreter.rs index 3a74280..6892557 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -102,6 +102,22 @@ impl Interpreter { self.error("Unsupported data type for the let argument"); } }, + "if" => match value { + Value::Object(value) => { + return self.if_node(value); + } + _ => { + self.error("Unsupported data type for the if argument"); + } + }, + "loop" => match value { + Value::Array(value) => { + return self.loop_cycle(value); + } + _ => { + self.error("Unsupported data type for the loop cycle argument"); + } + }, name => { self.unk_token(&name); } @@ -115,12 +131,14 @@ impl Interpreter { "ErrExit" => { self.err_exit(); } + "break" => return Value::String("break".to_string()), + "continue" => return Value::String("continue".to_string()), value => { - self.print(&vec![Value::String(value.to_string())], false); + self.print(&vec![Value::String(value.to_string())], true); } }, Value::Array(command) => { - self.print(command, false); + self.print(command, true); } _ => { self.error("Unsupported data type for the command"); @@ -129,6 +147,96 @@ impl Interpreter { return Value::Null; } + fn if_node(&mut self, value: &Map) -> Value { + let condition = self.eval_node(&value["condition"]); + let nodes = &value.get("body"); + let else_nodes = &value.get("else"); + + match nodes { + Some(nodes) => match nodes { + Value::Array(nodes) => match else_nodes { + Some(else_nodes) => match else_nodes { + Value::Array(else_nodes) => { + if condition == true { + let name = self.run_nodes(nodes); + if name == "break" { + return Value::String("break".to_string()); + } + if name == "continue" { + return Value::String("continue".to_string()); + } + return Value::Null; + } else { + let name = self.run_nodes(else_nodes); + if name == "break" { + return Value::String("break".to_string()); + } + if name == "continue" { + return Value::String("continue".to_string()); + } + return Value::Null; + }; + } + _ => { + if condition == true { + let name = self.run_nodes(nodes); + if name == "break" { + return Value::String("break".to_string()); + } + if name == "continue" { + return Value::String("continue".to_string()); + } + return Value::Null; + } + return Value::Null; + } + }, + None => { + if condition == true { + let name = self.run_nodes(nodes); + if name == "break" { + return Value::String("break".to_string()); + } + if name == "continue" { + return Value::String("continue".to_string()); + } + return Value::Null; + } + return Value::Null; + } + }, + _ => return Value::Null, + }, + None => { + self.error("if must have a body"); + panic!() + } + } + } + + fn loop_cycle(&mut self, value: &Vec) -> Value { + loop { + let name = self.run_nodes(value); + if name == "break" { + break Value::Null; + } + if name == "continue" { + continue; + } + } + } + + fn run_nodes(&mut self, arr: &Vec) -> String { + for command in arr { + let to_do = self.eval_node(command); + match to_do { + Value::String(name) => return name, + _ => {} + } + } + "end".to_string() + } + fn define(&mut self, vars: &Map) -> Value { for (name, value) in vars { match value { @@ -358,11 +466,8 @@ impl Interpreter { fn print(&mut self, args: &Vec, ln: bool) { for arg in args { self.print_one(arg); - if ln == true { - println!(); - } } - if ln == false { + if ln == true { println!(); } } diff --git a/test.json5 b/test.json5 index ab8462d..c7d34ba 100644 --- a/test.json5 +++ b/test.json5 @@ -162,6 +162,40 @@ ["After executing calculated = ", { var: "calculated" }], + "\nRun loop", + { + loop: [ + { + assign: { + calculated: { calc: [{ var: "calculated" }, "+", 1] }, + }, + }, + { print: ["\rcalculated = ", { var: "calculated" }] }, + { + if: { + condition: { comp: [{ var: "calculated" }, ">=", 200000] }, + body: ["\n", "break"], + }, + }, + ], + }, + + { + if: { + condition: { comp: [{ var: "calculated" }, ">=", 199999] }, + body: [["Calculated is >= ", 199999]], + else: [["Calculated is < ", 199999]], + }, + }, + + { + if: { + condition: { comp: [{ var: "calculated" }, ">", 200000] }, + body: [["Calculated is > ", 200000]], + else: [["Calculated is <= ", 200000]], + }, + }, + // { // print: [ // {