Commit 17e1832c authored by Jeff Smits's avatar Jeff Smits

We're getting there...

parent d6bd79e1
......@@ -197,7 +197,7 @@ pub enum Term<'s, B> {
Application(&'s str, Box<[ATermRef<'s>]>),
String(&'s str),
List(Rc<TermList<'s>>),
Placeholder(aterm::TermPlaceholder<ATermRef<'s>>),
Placeholder(aterm::TermPlaceholder<ATermRef<'s>>, ATermRef<'s>),
Blob(B),
}
......@@ -216,7 +216,7 @@ impl<'s, B: PartialEq> PartialEq for Term<'s, B> {
ptr::eq(lc, rc) && lch == rch
}
(&List(ref l), &List(ref r)) => l == r,
(&Placeholder(ref l), &Placeholder(ref r)) => l == r,
(&Placeholder(_, ref l), &Placeholder(_, ref r)) => l == r,
(&Blob(ref l), &Blob(ref r)) => l == r,
_ => false,
}
......@@ -251,7 +251,11 @@ where
l.to_ascii(writer)?;
write!(writer, "]")
}
Placeholder(ref tp) => tp.to_ascii(writer),
Placeholder(_, ref tp) => {
write!(writer, "<")?;
tp.to_ascii(writer)?;
write!(writer, ">")
},
Blob(ref b) => b.to_ascii(writer),
}
}
......@@ -351,12 +355,20 @@ impl<'s> ATerm<'s> {
RefCell::borrow(&self.attachments).clone()
}
#[allow(dead_code)]
pub fn set_attachments<I>(&self, attachments: I)
where
I: IntoIterator<Item=Attachment>,
{
*self.attachments.borrow_mut() = attachments.into_iter().collect();
}
pub fn get_placeholder_term(&self) -> Option<ATermRef<'s>> {
match self.term {
Term::Placeholder(_, ref t) => Some(t.clone()),
_ => None,
}
}
}
impl<'s> aterm::ATerm<'s> for ATerm<'s> {
......@@ -400,7 +412,7 @@ impl<'s> aterm::ATerm<'s> for ATerm<'s> {
fn get_placeholder(&self) -> Option<&aterm::TermPlaceholder<Self::Rec>> {
match self.term {
Term::Placeholder(ref tp) => Some(tp),
Term::Placeholder(ref tp, _) => Some(tp),
_ => None,
}
}
......@@ -460,6 +472,10 @@ impl<'s> ATermFactory {
{
Rc::new(ATerm::with_annos_attachments(aterm.term.clone(), annos, attachments))
}
pub fn stratego_placeholder(&'s self, term: ATermRef<'s>) -> ATermRef<'s> {
Rc::new(ATerm::no_annos(Term::Placeholder(aterm::TermPlaceholder::Term, term)))
}
}
impl Default for ATermFactory {
......@@ -537,7 +553,7 @@ impl<'s> aterm::ATermFactory<'s> for ATermFactory {
}
fn placeholder(&'s self, value: aterm::TermPlaceholder<Self::ATermRef>) -> Self::ATermRef {
Rc::new(ATerm::no_annos(Term::Placeholder(value)))
Rc::new(ATerm::no_annos(Term::Placeholder(aterm::TermPlaceholder::Term, value.to_template(self))))
}
fn blob(&'s self, value: <Self::ATerm as aterm::ATerm<'s>>::Blob) -> Self::ATermRef {
......
......@@ -351,8 +351,8 @@ fn eval_match<'d, 'f : 'd>(
let current_cons = &context.factory.string(current_cons.to_owned());
eval_match(context, cons, current_cons)?;
let current_children =
context.factory.list(current_children.into_iter().cloned());
eval_match(context, children, &current_children)?;
&context.factory.list(current_children.into_iter().cloned());
eval_match(context, children, current_children)?;
}
List(ref list) => {
eval_match(context, cons, &context.factory.nil())?;
......@@ -362,12 +362,12 @@ fn eval_match<'d, 'f : 'd>(
&context.factory.list_term(list.clone()),
)?;
}
Blob(_) |
Placeholder(_) => {
return Err(Error::UnknownBehaviour(
"Blob or ATerm placeholder in match of \
explode pattern (#) first argument",
))
Blob(_) => return Err(Error::StrategyFailed),
Placeholder(_, ref t) => {
let current_cons = &context.factory.string("<>");
let current_children = &context.factory.list(::std::iter::once(t.clone()));
eval_match(context, cons, current_cons)?;
eval_match(context, children, current_children)?;
}
Int(_) | Long(_) | String(_) | Real(_) => {
eval_match(context, cons, current)?;
......@@ -389,7 +389,6 @@ where
F: Fn(&Box<[ATermRef<'f>]>, &'d preprocess::Strategy, &MutContext<'d, 'f>) -> Result<Box<[ATermRef<'f>]>>
{
use factory::Term::*;
use aterm::TermPlaceholder as TP;
let annos = current.get_annotations();
match current.term {
......@@ -405,15 +404,17 @@ where
context.factory.with_annos(t, annos.into_iter().cloned())
})
}
Placeholder(TP::Application(ref r)) => {
fun(r, strat, context)
.map(TP::Application)
.map(|p| context.factory.placeholder(p))
Placeholder(_, ref r) => {
fun(&vec![r.clone()].into_boxed_slice(), strat, context)
.map(|p| {
debug_assert!(p.len() == 1);
context.factory.stratego_placeholder(p[0].clone())
})
.map(|t| {
context.factory.with_annos(t, annos.into_iter().cloned())
})
}
Placeholder(_) | Int(_) | Long(_) | Real(_) | String(_) | Blob(_) => Err(Error::StrategyFailed),
Int(_) | Long(_) | Real(_) | String(_) | Blob(_) => Err(Error::StrategyFailed),
}
}
......
use context::MutContext;
use error::{Error, Result};
use factory::ATermRef;
use factory::{Term, ATermRef};
use preprocess::StrategyDef;
use aterm::{ATermFactory as ATF, ATerm as A};
......@@ -214,15 +214,16 @@ pub fn newname<'d, 'f: 'd>(
"Primitive newname called with wrong argument count",
));
}
targs[0].get_string()
.or_else(|| targs[0].get_application().map(|t| t.0))
.map(|s| {
match targs[0].term {
Term::String(s) |
Term::Application(s, _) => {
let mut ssl_state = context.ssl_state.borrow_mut();
let mut counter = ssl_state.string.newname_counters.entry(s).or_insert(0);
let result = format!("{}{}", s, counter);
*counter += 1;
// TODO: extend factory to provide unique_string which fails if the string was built before.
Ok(context.factory.string(result))
})
.unwrap_or_else(|| new(context, sargs, Vec::new(), current))
}
_ => new(context, sargs, Vec::new(), current)
}
}
use context::MutContext;
use error::{Error, Result};
use factory::ATermRef;
use factory::{Term, ATermRef};
use preprocess::StrategyDef;
use aterm::{ATermFactory as ATF, ATerm as A};
......@@ -800,9 +800,8 @@ pub fn copy<'d, 'f: 'd>(
return Ok(current);
}
let mut input = targs[0]
.get_string()
.and_then(|input_file| {
let mut input = match targs[0].term {
Term::String(input_file) => {
let input_path = ssl_state.sys.cwd_with_file_name(&input_file);
File::open(input_path)
.map_err(|e| {
......@@ -811,25 +810,16 @@ pub fn copy<'d, 'f: 'd>(
e.description(),
targs[1]
);
e
Error::StrategyFailed
})
.map(|f| Box::new(f) as Box<Read>)
.ok()
})
.or_else(|| {
targs[0].get_application().and_then(
|(c, _)| if c == "stdin" {
Some(Box::new(io::stdin()) as Box<Read>)
} else {
None
},
)
})
.ok_or(Error::StrategyFailed)?;
.map(|f| Box::new(f) as Box<Read>)?
}
Term::Application("stdin", _) => Box::new(io::stdin()) as Box<Read>,
_ => return Err(Error::StrategyFailed)
};
let mut output = targs[1]
.get_string()
.and_then(|output_file| {
let mut output = match targs[1].term {
Term::String(output_file) => {
let output_path = ssl_state.sys.cwd_with_file_name(&output_file);
File::open(output_path)
.map_err(|e| {
......@@ -838,23 +828,14 @@ pub fn copy<'d, 'f: 'd>(
e.description(),
targs[1]
);
e
Error::StrategyFailed
})
.map(|f| Box::new(f) as Box<Write>)
.ok()
})
.or_else(|| {
targs[0].get_application().and_then(
|(c, _)| if c == "stdout" {
Some(Box::new(io::stdout()) as Box<Write>)
} else if c == "stderr" {
Some(Box::new(io::stderr()) as Box<Write>)
} else {
None
},
)
})
.ok_or(Error::StrategyFailed)?;
.map(|f| Box::new(f) as Box<Write>)?
}
Term::Application("stdout", _) => Box::new(io::stdout()) as Box<Write>,
Term::Application("stderr", _) => Box::new(io::stderr()) as Box<Write>,
_ => return Err(Error::StrategyFailed),
};
let _ = io::copy(&mut input, &mut output).map_err(
|_| Error::StrategyFailed,
......
......@@ -23,11 +23,11 @@ pub fn get_constructor<'d, 'f: 'd>(
match targs[0].term {
Term::Int(_) |
Term::Long(_) |
Term::Placeholder(_) |
Term::Real(_) => Ok(targs[0].clone()),
Term::List(_) => Ok(context.factory.nil()),
Term::String(v) |
Term::Application(v, _) => Ok(context.factory.string(v.clone())),
Term::Placeholder(_, _) => Ok(context.factory.string("<>")),
Term::Blob(ref b) => {
let mut str_repr = String::from("BLOB_");
b.to_ascii(&mut str_repr).map_err(|_| Error::StrategyFailed)?;
......@@ -42,6 +42,9 @@ pub fn mkterm<'d, 'f: 'd>(
targs: Vec<ATermRef<'f>>,
current: ATermRef<'f>,
) -> Result<ATermRef<'f>> {
use aterm::utils::string_unescape;
use factory::Term::*;
fn truncate_at_illegal_chars(s: &str) -> &str {
if let Some(index) = s.find(|c: char| {
!(c.is_alphanumeric() || c == '_' || c == '-' || c == '+' || c == '*' || c == '$')
......@@ -59,12 +62,11 @@ pub fn mkterm<'d, 'f: 'd>(
));
}
targs[0]
.get_string()
.ok_or(Error::StrategyFailed)
.and_then(|s| {
match targs[0].term {
String(s) => {
if s.starts_with('"') && s.ends_with('"') {
Ok(context.factory.application(s, ::std::iter::empty()))
// TODO: attempt to parse the string into an aterm, only unescape on failure?
Ok(context.factory.string(string_unescape(s)))
} else {
let s = truncate_at_illegal_chars(s);
targs[1]
......@@ -72,28 +74,11 @@ pub fn mkterm<'d, 'f: 'd>(
.map(|l| context.factory.application(s, l.into_iter()))
.ok_or(Error::StrategyFailed)
}
})
.or_else(|_| {
targs[0].get_int().map(|_| targs[0].clone()).ok_or(
Error::StrategyFailed,
)
})
.or_else(|_| {
targs[0].get_long().map(|_| targs[0].clone()).ok_or(
Error::StrategyFailed,
)
})
.or_else(|_| {
targs[0].get_real().map(|_| targs[0].clone()).ok_or(
Error::StrategyFailed,
)
})
.or_else(|_| {
targs[0]
.get_list()
.and_then(|_| targs[1].get_list().map(|_| targs[1].clone()))
.ok_or(Error::StrategyFailed)
})
}
Int(_) | Long(_) | Real(_) => Ok(targs[0].clone()),
List(_) => targs[1].get_list().map(|_| targs[1].clone()).ok_or(Error::StrategyFailed),
_ => Err(Error::StrategyFailed)
}
}
pub fn get_arguments<'d, 'f: 'd>(
......@@ -102,27 +87,21 @@ pub fn get_arguments<'d, 'f: 'd>(
targs: Vec<ATermRef<'f>>,
current: ATermRef<'f>,
) -> Result<ATermRef<'f>> {
use factory::Term::*;
if targs.len() < 1 {
return Err(Error::UnknownBehaviour(
"Primitive get_arguments called with wrong argument \
count",
));
}
let empty_list = context.factory.nil();
// filter out strings first as we'll match on application later
targs[0]
.get_int()
.map(|_| empty_list.clone())
.or_else(|| targs[0].get_real().map(|_| empty_list.clone()))
.or_else(|| targs[0].get_blob().map(|_| empty_list.clone()))
.or_else(|| targs[0].get_list().map(|_| targs[0].clone()))
.or_else(|| {
targs[0].get_application().map(|(_, r)| {
context.factory.list(r.into_iter().cloned())
})
})
.ok_or(Error::StrategyFailed)
// TODO: Handle Stratego Placeholder
match current.term {
Application(_, ref r) => Ok(context.factory.list(r.into_iter().cloned())),
Int(_) | Long(_) | Real(_) | String(_) | Blob(_) => Ok(context.factory.nil()),
List(_) => Ok(current.clone()),
Placeholder(_, ref t) => Ok(context.factory.list(::std::iter::once(t.clone()))),
}
}
pub fn explode_term<'d, 'f: 'd>(
......@@ -200,8 +179,16 @@ pub fn isPlaceholder<'d, 'f: 'd>(
targs: Vec<ATermRef<'f>>,
current: ATermRef<'f>,
) -> Result<ATermRef<'f>> {
// TODO: Handle Stratego Placeholder
unimplemented!();
if targs.len() < 1 {
return Err(Error::UnknownBehaviour(
"Primitive isPlaceholder called with wrong argument count",
));
}
if let Some(_) = current.get_placeholder() {
Ok(current)
} else {
Err(Error::StrategyFailed)
}
}
pub fn makePlaceholder<'d, 'f: 'd>(
......@@ -210,8 +197,12 @@ pub fn makePlaceholder<'d, 'f: 'd>(
targs: Vec<ATermRef<'f>>,
current: ATermRef<'f>,
) -> Result<ATermRef<'f>> {
// TODO: Handle Stratego Placeholder
unimplemented!();
if targs.len() < 1 {
return Err(Error::UnknownBehaviour(
"Primitive makePlaceholder called with wrong argument count",
));
}
Ok(context.factory.stratego_placeholder(targs[0].clone()))
}
pub fn getPlaceholder<'d, 'f: 'd>(
......@@ -220,8 +211,12 @@ pub fn getPlaceholder<'d, 'f: 'd>(
targs: Vec<ATermRef<'f>>,
current: ATermRef<'f>,
) -> Result<ATermRef<'f>> {
// TODO: Handle Stratego Placeholder
unimplemented!();
if targs.len() < 1 {
return Err(Error::UnknownBehaviour(
"Primitive makePlaceholder called with wrong argument count",
));
}
targs[0].get_placeholder_term().ok_or(Error::StrategyFailed)
}
pub fn preserve_annotations_attachments<'d, 'f: 'd>(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment