From cb51d88726d1208775c72a808b6bcf8663a6eb3a Mon Sep 17 00:00:00 2001 From: Altareos Date: Thu, 24 Feb 2022 15:21:23 +0100 Subject: [PATCH] casting syntax --- src/lib.rs | 99 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 39cc262..b9d3686 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,8 +27,11 @@ pub enum Instruction { Value(String), Assign(String, Box), Integer(String), + IntegerCast(Box), Float(String), + FloatCast(Box), String(String), + StringCast(Box), Array(Vec), Add(Vec), Subtract(Vec), @@ -74,20 +77,45 @@ impl Instruction { .ok_or("missing child on 'assign' tag")?, )?), ), - "integer" => Instruction::Integer( - node.attribute("value") - .ok_or("missing 'value' attribute on 'integer' tag")? - .parse()?, - ), - "float" => Instruction::Float( - node.attribute("value") - .ok_or("missing 'value' attribute on 'float' tag")? - .parse()?, - ), - "string" => Instruction::String(String::from( - node.attribute("value") - .ok_or("missing 'value' attribute on 'string' tag")?, - )), + "integer" => node + .attribute("value") + .and_then(|v| Some(Some(Ok(Instruction::Integer(String::from(v)))))) + .or_else(|| { + Some(node.first_element_child().and_then(|n| { + Some( + Instruction::new(n) + .and_then(|ins| Ok(Instruction::IntegerCast(Box::new(ins)))), + ) + })) + }) + .ok_or("missing 'value' attribute or child in 'integer' tag")? + .ok_or("missing 'value' attribute or child in 'integer' tag")??, + "float" => node + .attribute("value") + .and_then(|v| Some(Some(Ok(Instruction::Float(String::from(v)))))) + .or_else(|| { + Some(node.first_element_child().and_then(|n| { + Some( + Instruction::new(n) + .and_then(|ins| Ok(Instruction::FloatCast(Box::new(ins)))), + ) + })) + }) + .ok_or("missing 'value' attribute or child in 'float' tag")? + .ok_or("missing 'value' attribute or child in 'float' tag")??, + "string" => node + .attribute("value") + .and_then(|v| Some(Some(Ok(Instruction::String(String::from(v)))))) + .or_else(|| { + Some(node.first_element_child().and_then(|n| { + Some( + Instruction::new(n) + .and_then(|ins| Ok(Instruction::StringCast(Box::new(ins)))), + ) + })) + }) + .ok_or("missing 'value' attribute or child in 'string' tag")? + .ok_or("missing 'value' attribute or child in 'string' tag")??, "array" => Instruction::Array(Instruction::from_children(node)?), "add" => Instruction::Add(Instruction::from_children(node)?), "subtract" => Instruction::Subtract(Instruction::from_children(node)?), @@ -482,8 +510,32 @@ impl Instruction { None } Instruction::Integer(val) => Some(Value::Integer(val.parse()?)), + Instruction::IntegerCast(ins) => Some( + Value::Integer(match ins.run(ctx)?.ok_or("no value to be cast to 'integer'")? { + Value::Integer(i) => i, + Value::Float(f) => f as i64, + Value::String(s) => s.parse()?, + _ => Err("value cannot be cast to 'integer'")? + }) + ), Instruction::Float(val) => Some(Value::Float(val.parse()?)), + Instruction::FloatCast(ins) => Some( + Value::Float(match ins.run(ctx)?.ok_or("no value to be cast to 'float'")? { + Value::Integer(i) => i as f64, + Value::Float(f) => f, + Value::String(s) => s.parse()?, + _ => Err("value cannot be cast to 'float'")? + }) + ), Instruction::String(val) => Some(Value::String(val.clone())), + Instruction::StringCast(ins) => Some( + Value::String(match ins.run(ctx)?.ok_or("no value to be cast to 'string'")? { + Value::Integer(i) => i.to_string(), + Value::Float(f) => f.to_string(), + Value::String(s) => s, + _ => Err("value cannot be cast to 'string'")? + }) + ), Instruction::Array(args) => Some(Value::Array(Rc::new(RefCell::new( Instruction::run_all(args, ctx)? .ok_or("invalid child values in 'array' tag")?, @@ -776,7 +828,10 @@ mod stl { ctx.assign(String::from("array-push"), Value::StdFunction(array_push)); ctx.assign(String::from("array-pop"), Value::StdFunction(array_pop)); ctx.assign(String::from("array-get"), Value::StdFunction(array_get)); - ctx.assign(String::from("array-length"), Value::StdFunction(array_length)); + ctx.assign( + String::from("array-length"), + Value::StdFunction(array_length), + ); } fn print(vals: Vec) -> Result, Box> { @@ -785,8 +840,7 @@ mod stl { Value::Integer(i) => println!("{}", i), Value::Float(f) => println!("{}", f), Value::String(s) => println!("{}", s), - v => println!("{:?}", v) - // _ => Err("unprintable value")?, + v => println!("{:?}", v), // _ => Err("unprintable value")?, }; Ok(Some(vals[0].clone())) } else { @@ -809,9 +863,10 @@ mod stl { if vals.len() == 2 { if let Value::String(s) = &vals[0] { if let Value::String(d) = &vals[1] { - let mut v = s.split(d) - .map(|sub| Value::String(sub.to_string())) - .collect::>(); + let mut v = s + .split(d) + .map(|sub| Value::String(sub.to_string())) + .collect::>(); v.remove(0); v.pop(); Ok(Some(Value::Array(Rc::new(RefCell::new(v))))) @@ -901,9 +956,7 @@ mod stl { fn array_length(vals: Vec) -> Result, Box> { if vals.len() == 1 { if let Value::Array(v) = &vals[0] { - Ok(Some( - Value::Integer(v.borrow().len() as i64) - )) + Ok(Some(Value::Integer(v.borrow().len() as i64))) } else { Err("invalid array in call to 'array-length'")? }