casting syntax
This commit is contained in:
99
src/lib.rs
99
src/lib.rs
@@ -27,8 +27,11 @@ pub enum Instruction {
|
|||||||
Value(String),
|
Value(String),
|
||||||
Assign(String, Box<Instruction>),
|
Assign(String, Box<Instruction>),
|
||||||
Integer(String),
|
Integer(String),
|
||||||
|
IntegerCast(Box<Instruction>),
|
||||||
Float(String),
|
Float(String),
|
||||||
|
FloatCast(Box<Instruction>),
|
||||||
String(String),
|
String(String),
|
||||||
|
StringCast(Box<Instruction>),
|
||||||
Array(Vec<Instruction>),
|
Array(Vec<Instruction>),
|
||||||
Add(Vec<Instruction>),
|
Add(Vec<Instruction>),
|
||||||
Subtract(Vec<Instruction>),
|
Subtract(Vec<Instruction>),
|
||||||
@@ -74,20 +77,45 @@ impl Instruction {
|
|||||||
.ok_or("missing child on 'assign' tag")?,
|
.ok_or("missing child on 'assign' tag")?,
|
||||||
)?),
|
)?),
|
||||||
),
|
),
|
||||||
"integer" => Instruction::Integer(
|
"integer" => node
|
||||||
node.attribute("value")
|
.attribute("value")
|
||||||
.ok_or("missing 'value' attribute on 'integer' tag")?
|
.and_then(|v| Some(Some(Ok(Instruction::Integer(String::from(v))))))
|
||||||
.parse()?,
|
.or_else(|| {
|
||||||
),
|
Some(node.first_element_child().and_then(|n| {
|
||||||
"float" => Instruction::Float(
|
Some(
|
||||||
node.attribute("value")
|
Instruction::new(n)
|
||||||
.ok_or("missing 'value' attribute on 'float' tag")?
|
.and_then(|ins| Ok(Instruction::IntegerCast(Box::new(ins)))),
|
||||||
.parse()?,
|
)
|
||||||
),
|
}))
|
||||||
"string" => Instruction::String(String::from(
|
})
|
||||||
node.attribute("value")
|
.ok_or("missing 'value' attribute or child in 'integer' tag")?
|
||||||
.ok_or("missing 'value' attribute on 'string' 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)?),
|
"array" => Instruction::Array(Instruction::from_children(node)?),
|
||||||
"add" => Instruction::Add(Instruction::from_children(node)?),
|
"add" => Instruction::Add(Instruction::from_children(node)?),
|
||||||
"subtract" => Instruction::Subtract(Instruction::from_children(node)?),
|
"subtract" => Instruction::Subtract(Instruction::from_children(node)?),
|
||||||
@@ -482,8 +510,32 @@ impl Instruction {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
Instruction::Integer(val) => Some(Value::Integer(val.parse()?)),
|
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::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::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::Array(args) => Some(Value::Array(Rc::new(RefCell::new(
|
||||||
Instruction::run_all(args, ctx)?
|
Instruction::run_all(args, ctx)?
|
||||||
.ok_or("invalid child values in 'array' tag")?,
|
.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-push"), Value::StdFunction(array_push));
|
||||||
ctx.assign(String::from("array-pop"), Value::StdFunction(array_pop));
|
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-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<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
fn print(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||||
@@ -785,8 +840,7 @@ mod stl {
|
|||||||
Value::Integer(i) => println!("{}", i),
|
Value::Integer(i) => println!("{}", i),
|
||||||
Value::Float(f) => println!("{}", f),
|
Value::Float(f) => println!("{}", f),
|
||||||
Value::String(s) => println!("{}", s),
|
Value::String(s) => println!("{}", s),
|
||||||
v => println!("{:?}", v)
|
v => println!("{:?}", v), // _ => Err("unprintable value")?,
|
||||||
// _ => Err("unprintable value")?,
|
|
||||||
};
|
};
|
||||||
Ok(Some(vals[0].clone()))
|
Ok(Some(vals[0].clone()))
|
||||||
} else {
|
} else {
|
||||||
@@ -809,9 +863,10 @@ mod stl {
|
|||||||
if vals.len() == 2 {
|
if vals.len() == 2 {
|
||||||
if let Value::String(s) = &vals[0] {
|
if let Value::String(s) = &vals[0] {
|
||||||
if let Value::String(d) = &vals[1] {
|
if let Value::String(d) = &vals[1] {
|
||||||
let mut v = s.split(d)
|
let mut v = s
|
||||||
.map(|sub| Value::String(sub.to_string()))
|
.split(d)
|
||||||
.collect::<Vec<Value>>();
|
.map(|sub| Value::String(sub.to_string()))
|
||||||
|
.collect::<Vec<Value>>();
|
||||||
v.remove(0);
|
v.remove(0);
|
||||||
v.pop();
|
v.pop();
|
||||||
Ok(Some(Value::Array(Rc::new(RefCell::new(v)))))
|
Ok(Some(Value::Array(Rc::new(RefCell::new(v)))))
|
||||||
@@ -901,9 +956,7 @@ mod stl {
|
|||||||
fn array_length(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
fn array_length(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||||
if vals.len() == 1 {
|
if vals.len() == 1 {
|
||||||
if let Value::Array(v) = &vals[0] {
|
if let Value::Array(v) = &vals[0] {
|
||||||
Ok(Some(
|
Ok(Some(Value::Integer(v.borrow().len() as i64)))
|
||||||
Value::Integer(v.borrow().len() as i64)
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
Err("invalid array in call to 'array-length'")?
|
Err("invalid array in call to 'array-length'")?
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user