error handling
This commit is contained in:
26
sample/handle.pl.xml
Normal file
26
sample/handle.pl.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<program name="handle">
|
||||
<main>
|
||||
<handle>
|
||||
<try>
|
||||
<integer value="non" />
|
||||
<call function="print-line">
|
||||
<arguments>
|
||||
<string value="there is no bug" />
|
||||
</arguments>
|
||||
</call>
|
||||
</try>
|
||||
<catch variable="err">
|
||||
<call function="print-line">
|
||||
<arguments>
|
||||
<string value="oh no there is a bug" />
|
||||
</arguments>
|
||||
</call>
|
||||
<call function="print-line">
|
||||
<arguments>
|
||||
<value variable="err" />
|
||||
</arguments>
|
||||
</call>
|
||||
</catch>
|
||||
</handle>
|
||||
</main>
|
||||
</program>
|
||||
13
src/error.rs
13
src/error.rs
@@ -17,7 +17,7 @@ pub struct MissingAttribute(pub &'static str, pub &'static str);
|
||||
|
||||
impl fmt::Display for MissingAttribute {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "missing '{}' child in '{}' node", self.1, self.0)
|
||||
write!(f, "missing '{}' attribute in '{}' node", self.1, self.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,3 +118,14 @@ impl fmt::Display for UnknownVariable {
|
||||
}
|
||||
|
||||
impl Error for UnknownVariable {}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct InaccessibleFile(pub String);
|
||||
|
||||
impl fmt::Display for InaccessibleFile {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "unable to access file '{}'", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InaccessibleFile {}
|
||||
|
||||
@@ -43,6 +43,7 @@ pub enum Instruction {
|
||||
},
|
||||
Each(String, Box<Instruction>, Vec<Instruction>),
|
||||
While(Box<Instruction>, Vec<Instruction>),
|
||||
Handle(Vec<Instruction>, Vec<Instruction>, String),
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
@@ -230,6 +231,19 @@ impl Instruction {
|
||||
util::find_node(&node, "do").ok_or(MissingChild("while", "from"))?,
|
||||
)?,
|
||||
),
|
||||
"handle" => Instruction::Handle(
|
||||
Instruction::from_children(
|
||||
util::find_node(&node, "try").ok_or(MissingChild("handle", "try"))?,
|
||||
)?,
|
||||
Instruction::from_children(
|
||||
util::find_node(&node, "catch").ok_or(MissingChild("handle", "try"))?,
|
||||
)?,
|
||||
util::find_node(&node, "catch")
|
||||
.ok_or(MissingChild("handle", "try"))?
|
||||
.attribute("variable")
|
||||
.ok_or(MissingAttribute("catch", "variable"))?
|
||||
.to_string(),
|
||||
),
|
||||
tag => Err(format!("unknown tag '{}'", tag))?,
|
||||
})
|
||||
}
|
||||
@@ -698,6 +712,18 @@ impl Instruction {
|
||||
}
|
||||
None
|
||||
}
|
||||
Instruction::Handle(try_block, catch_block, variable) => {
|
||||
for ins in try_block {
|
||||
if let Err(e) = ins.run(ctx, globals) {
|
||||
ctx.assign(variable.clone(), Value::String(e.to_string()));
|
||||
for ins in catch_block {
|
||||
ins.run(ctx, globals)?;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
|
||||
10
src/stl.rs
10
src/stl.rs
@@ -1,3 +1,5 @@
|
||||
use crate::error::InaccessibleFile;
|
||||
|
||||
use super::error::{BadArgumentCount, InvalidArgument};
|
||||
use super::{Context, Value};
|
||||
use std::cell::RefCell;
|
||||
@@ -232,12 +234,12 @@ fn write_file(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
.open(path)
|
||||
{
|
||||
if let Ok(_) = write!(file, "{}", contents) {
|
||||
Ok(Some(Value::Integer(1)))
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(Value::Integer(0)))
|
||||
Err(InaccessibleFile(path.clone()).into())
|
||||
}
|
||||
} else {
|
||||
Ok(Some(Value::Integer(0)))
|
||||
Err(InaccessibleFile(path.clone()).into())
|
||||
}
|
||||
} else {
|
||||
Err(InvalidArgument("write-file", "string").into())
|
||||
@@ -256,7 +258,7 @@ fn read_file(vals: Vec<Value>) -> Result<Option<Value>, Box<dyn Error>> {
|
||||
if let Ok(contents) = fs::read_to_string(path) {
|
||||
Ok(Some(Value::String(contents)))
|
||||
} else {
|
||||
Ok(None)
|
||||
Err(InaccessibleFile(path.clone()).into())
|
||||
}
|
||||
} else {
|
||||
Err(InvalidArgument("read-file", "string").into())
|
||||
|
||||
Reference in New Issue
Block a user