diff --git a/sample/arrays.pl.xml b/sample/arrays.pl.xml
index 8beebcc..2339b32 100644
--- a/sample/arrays.pl.xml
+++ b/sample/arrays.pl.xml
@@ -32,29 +32,35 @@
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/bf.pl.xml b/sample/bf.pl.xml
new file mode 100644
index 0000000..9c33d0e
--- /dev/null
+++ b/sample/bf.pl.xml
@@ -0,0 +1,369 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/if.pl.xml b/sample/if.pl.xml
index a081857..f46ae66 100644
--- a/sample/if.pl.xml
+++ b/sample/if.pl.xml
@@ -3,14 +3,18 @@
-
-
-
+
+
+
+
+
-
+
+
-
+
+
diff --git a/sample/stl.pl.xml b/sample/stl.pl.xml
new file mode 100644
index 0000000..4bee69a
--- /dev/null
+++ b/sample/stl.pl.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/test.pl.xml b/sample/test.pl.xml
index c14114c..d67f739 100644
--- a/sample/test.pl.xml
+++ b/sample/test.pl.xml
@@ -24,8 +24,10 @@
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/sample/while.pl.xml b/sample/while.pl.xml
index 7fa9237..22b566e 100644
--- a/sample/while.pl.xml
+++ b/sample/while.pl.xml
@@ -6,9 +6,11 @@
-
-
-
+
+
+
+
+
diff --git a/src/lib.rs b/src/lib.rs
index 82a4eeb..39cc262 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,6 +37,9 @@ pub enum Instruction {
And(Vec),
Or(Vec),
Not(Box),
+ Equal(Box, Box),
+ Greater(Box, Box),
+ Lower(Box, Box),
Call(Box, Vec),
CallNamed(String, Vec),
Return(Box),
@@ -51,14 +54,10 @@ pub enum Instruction {
},
Each(String, Box, Vec),
While(Box, Vec),
- Print(Box),
- AssignArray(Box, Box, Box),
- InsertArray(Box, Box),
}
impl Instruction {
pub fn new(node: Node) -> Result> {
- // println!("parsing '{}'", util::tag_name(&node));
Ok(match util::tag_name(&node).as_str() {
"value" => Instruction::Value(
node.attribute("variable")
@@ -100,6 +99,39 @@ impl Instruction {
node.first_element_child()
.ok_or("missing value child element in 'not' tag")?,
)?)),
+ "equal" => {
+ let children: Vec = node.children().filter(Node::is_element).collect();
+ if children.len() == 2 {
+ Instruction::Equal(
+ Box::new(Instruction::new(children[0])?),
+ Box::new(Instruction::new(children[1])?),
+ )
+ } else {
+ Err("bad child count in 'equal' tag")?
+ }
+ }
+ "greater" => {
+ let children: Vec = node.children().filter(Node::is_element).collect();
+ if children.len() == 2 {
+ Instruction::Greater(
+ Box::new(Instruction::new(children[0])?),
+ Box::new(Instruction::new(children[1])?),
+ )
+ } else {
+ Err("bad child count in 'greater' tag")?
+ }
+ }
+ "lower" => {
+ let children: Vec = node.children().filter(Node::is_element).collect();
+ if children.len() == 2 {
+ Instruction::Lower(
+ Box::new(Instruction::new(children[0])?),
+ Box::new(Instruction::new(children[1])?),
+ )
+ } else {
+ Err("bad child count in 'lower' tag")?
+ }
+ }
"call" => {
if let Some(function) = node.attribute("function") {
Instruction::CallNamed(
@@ -180,39 +212,6 @@ impl Instruction {
)?),
Instruction::from_children(util::find_node(&node, "do")?)?,
),
- "print" => Instruction::Print(Box::new(Instruction::new(
- node.first_element_child()
- .ok_or("missing value child element in 'print' tag")?,
- )?)),
- "assign-array" => Instruction::AssignArray(
- Box::new(Instruction::new(
- util::find_node(&node, "array")?
- .first_element_child()
- .ok_or("missing 'array' in 'assign-array' tag")?,
- )?),
- Box::new(Instruction::new(
- util::find_node(&node, "index")?
- .first_element_child()
- .ok_or("missing 'index' in 'assign-array' tag")?,
- )?),
- Box::new(Instruction::new(
- util::find_node(&node, "value")?
- .first_element_child()
- .ok_or("missing 'value' in 'assign-array' tag")?,
- )?),
- ),
- "insert-array" => Instruction::InsertArray(
- Box::new(Instruction::new(
- util::find_node(&node, "array")?
- .first_element_child()
- .ok_or("missing 'array' in 'insert-array' tag")?,
- )?),
- Box::new(Instruction::new(
- util::find_node(&node, "value")?
- .first_element_child()
- .ok_or("missing 'value' in 'insert-array' tag")?,
- )?),
- ),
tag => Err(format!("unknown tag '{}'", tag))?,
})
}
@@ -406,6 +405,61 @@ impl Instruction {
})
}
+ fn compare(v1: Value, v2: Value) -> Result> {
+ use std::cmp::Ordering;
+ match v1 {
+ Value::Integer(i1) => match v2 {
+ Value::Integer(i2) => Ok(i1 - i2),
+ Value::Float(f2) => Ok(
+ match (i1 as f64)
+ .partial_cmp(&f2)
+ .ok_or("incompatible comparison values")?
+ {
+ Ordering::Less => -1,
+ Ordering::Equal => 0,
+ Ordering::Greater => 1,
+ },
+ ),
+ _ => Err("incompatible comparison values")?,
+ },
+ Value::Float(f1) => match v2 {
+ Value::Integer(i2) => Ok(
+ match f1
+ .partial_cmp(&(i2 as f64))
+ .ok_or("incompatible comparison values")?
+ {
+ Ordering::Less => -1,
+ Ordering::Equal => 0,
+ Ordering::Greater => 1,
+ },
+ ),
+ Value::Float(f2) => Ok(
+ match f1
+ .partial_cmp(&f2)
+ .ok_or("incompatible comparison values")?
+ {
+ Ordering::Less => -1,
+ Ordering::Equal => 0,
+ Ordering::Greater => 1,
+ },
+ ),
+ _ => Err("incompatible comparison values")?,
+ },
+ Value::String(s1) => {
+ if let Value::String(s2) = v2 {
+ Ok(match s1.cmp(&s2) {
+ Ordering::Less => -1,
+ Ordering::Equal => 0,
+ Ordering::Greater => 1,
+ })
+ } else {
+ Err("incompatible comparison values")?
+ }
+ }
+ _ => Err("incompatible comparison values")?,
+ }
+ }
+
fn run_all(
ins: &Vec,
ctx: &mut Context,
@@ -469,6 +523,39 @@ impl Instruction {
.run(ctx)?
.ok_or("invalid child value in 'not' tag")?
.to_bool()
+ {
+ 0
+ } else {
+ 1
+ },
+ )),
+ Instruction::Equal(v1, v2) => Some(Value::Integer(
+ if Instruction::compare(
+ v1.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ v2.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ )? == 0
+ {
+ 1
+ } else {
+ 0
+ },
+ )),
+ Instruction::Greater(v1, v2) => Some(Value::Integer(
+ if Instruction::compare(
+ v1.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ v2.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ )? > 0
+ {
+ 1
+ } else {
+ 0
+ },
+ )),
+ Instruction::Lower(v1, v2) => Some(Value::Integer(
+ if Instruction::compare(
+ v1.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ v2.run(ctx)?.ok_or("invalid child value in 'equal' tag")?,
+ )? < 0
{
1
} else {
@@ -483,6 +570,8 @@ impl Instruction {
.ok_or("invalid child function in 'call' tag")?;
if let Value::Function(f) = fct_val {
f.run(vals, ctx)?
+ } else if let Value::StdFunction(f) = fct_val {
+ f(vals)?
} else {
Err("invalid function")?
}
@@ -494,6 +583,8 @@ impl Instruction {
if let Value::Function(f) = fct_val {
let mut local = ctx.clone();
f.run(vals, &mut local)?
+ } else if let Value::StdFunction(f) = fct_val {
+ f(vals)?
} else {
Err("invalid function")?
}
@@ -586,38 +677,6 @@ impl Instruction {
}
None
}
- Instruction::Print(ins) => {
- match ins.run(ctx)?.ok_or("invalid child value in 'print' tag")? {
- Value::Integer(i) => println!("{}", i),
- Value::Float(f) => println!("{}", f),
- Value::String(s) => println!("{}", s),
- _ => Err("Unprintable value")?,
- };
- None
- }
- Instruction::AssignArray(array_ins, index_ins, value_ins) => {
- if let Some(Value::Array(vec)) = array_ins.run(ctx)? {
- if let Some(Value::Integer(index)) = index_ins.run(ctx)? {
- vec.borrow_mut().insert(
- index.try_into()?,
- value_ins
- .run(ctx)?
- .ok_or("invalid 'value' value in 'assign-array' tag")?,
- );
- }
- }
- None
- }
- Instruction::InsertArray(array_ins, value_ins) => {
- if let Some(Value::Array(vec)) = array_ins.run(ctx)? {
- vec.borrow_mut().push(
- value_ins
- .run(ctx)?
- .ok_or("invalid 'value' value in 'insert-array' tag")?,
- );
- }
- None
- }
}
} else {
None
@@ -658,6 +717,7 @@ pub enum Value {
String(String),
Array(Rc>>),
Function(Function),
+ StdFunction(fn(Vec) -> Result