Thread position information through to more places.

This commit is contained in:
Jeremy Wall 2017-11-06 21:06:30 -06:00
parent 1e3d19755c
commit 4f3cc3dbf6
3 changed files with 453 additions and 419 deletions

View File

@ -14,6 +14,12 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::convert::Into; use std::convert::Into;
use std::cmp::Ordering;
use std::cmp::PartialOrd;
use std::cmp::Eq;
use std::cmp::PartialEq;
use std::hash::Hasher;
use std::hash::Hash;
#[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)] #[derive(Debug,PartialEq,Eq,Clone,PartialOrd,Ord,Hash)]
pub struct Position { pub struct Position {
@ -28,15 +34,7 @@ pub struct Token {
} }
impl Token { impl Token {
pub fn new(f: &str) -> Self { pub fn new(f: &str, pos: Position) -> Self {
Self::new_with_pos(f,
Position {
line: 0,
column: 0,
})
}
pub fn new_with_pos(f: &str, pos: Position) -> Self {
Token { Token {
fragment: f.to_string(), fragment: f.to_string(),
pos: pos, pos: pos,
@ -51,11 +49,8 @@ impl Borrow<str> for Token {
} }
macro_rules! value_node { macro_rules! value_node {
($v:expr) => {
LocatedNode::new($v)
};
($v:expr, $p:expr) => { ($v:expr, $p:expr) => {
LocatedNode::new_with_pos($v, $p) LocatedNode::new($v, $p)
}; };
} }
@ -64,21 +59,15 @@ pub type SelectorList = Vec<Token>; // str is expected to always be a symbol.
#[derive(Debug,PartialEq,Clone)] #[derive(Debug,PartialEq,Clone)]
pub struct LocatedNode<T> { pub struct LocatedNode<T> {
pub pos: Option<Position>, // TODO(jwall): Make this non-optional, Should we just use positioned instead?
pub pos: Position,
pub val: T, pub val: T,
} }
impl<T> LocatedNode<T> { impl<T> LocatedNode<T> {
pub fn new(v: T) -> Self { pub fn new<P: Into<Position>>(v: T, pos: P) -> Self {
Self { Self {
pos: None, pos: pos.into(),
val: v,
}
}
pub fn new_with_pos<P: Into<Position>>(v: T, pos: P) -> Self {
Self {
pos: Some(pos.into()),
val: v, val: v,
} }
} }
@ -89,8 +78,9 @@ impl<T> LocatedNode<T> {
} }
pub fn make_value_node<T>(v: T) -> LocatedNode<T> { // TODO(jwall): This should take a line and a column as argumentsn now.
LocatedNode::new(v) pub fn make_value_node<T>(v: T, line: usize, column: usize) -> LocatedNode<T> {
LocatedNode::new(v, Position{line: line, column: column})
} }
/// Value represents a Value in the UCG parsed AST. /// Value represents a Value in the UCG parsed AST.
@ -141,7 +131,7 @@ impl Value {
} }
} }
pub fn pos(&self) -> &Option<Position> { pub fn pos(&self) -> &Position {
match self { match self {
&Value::Int(ref i) => &i.pos, &Value::Int(ref i) => &i.pos,
&Value::Float(ref f) => &f.pos, &Value::Float(ref f) => &f.pos,
@ -173,7 +163,7 @@ pub struct SelectDef {
} }
// TODO(jwall): This should have a way of rendering with position information. // TODO(jwall): This should have a way of rendering with position information.
#[derive(PartialEq,Debug,Eq,PartialOrd,Ord,Clone,Hash)] #[derive(Debug,Clone)]
pub struct Positioned<T> { pub struct Positioned<T> {
pub pos: Option<Position>, pub pos: Option<Position>,
pub val: T, pub val: T,
@ -195,6 +185,33 @@ impl<T> Positioned<T> {
} }
} }
impl<T: PartialEq> PartialEq for Positioned<T> {
fn eq(&self, other: &Self) -> bool {
self.val == other.val
}
}
impl<T: Eq> Eq for Positioned<T> {
}
impl<T: Ord> Ord for Positioned<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.val.cmp(&other.val)
}
}
impl<T: PartialOrd> PartialOrd for Positioned<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.val.partial_cmp(&other.val)
}
}
impl<T: Hash> Hash for Positioned<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.val.hash(state);
}
}
impl<'a> From<&'a Token> for Positioned<String> { impl<'a> From<&'a Token> for Positioned<String> {
fn from(t: &'a Token) -> Positioned<String> { fn from(t: &'a Token) -> Positioned<String> {
Positioned { Positioned {
@ -207,7 +224,7 @@ impl<'a> From<&'a Token> for Positioned<String> {
impl<'a> From<&'a LocatedNode<String>> for Positioned<String> { impl<'a> From<&'a LocatedNode<String>> for Positioned<String> {
fn from(t: &LocatedNode<String>) -> Positioned<String> { fn from(t: &LocatedNode<String>) -> Positioned<String> {
Positioned { Positioned {
pos: t.pos.clone(), pos: Some(t.pos.clone()),
val: t.val.clone(), val: t.val.clone(),
} }
} }
@ -401,10 +418,10 @@ mod ast_test {
Positioned::new("foo".to_string()) Positioned::new("foo".to_string())
], ],
fields: vec![ fields: vec![
(Token::new("f1"), Expression::Binary(BinaryOpDef{ (Token::new("f1", Position { line: 1, column: 1}), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Symbol(make_value_node("foo".to_string())), left: Value::Symbol(make_value_node("foo".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
})), })),
], ],
@ -420,10 +437,10 @@ mod ast_test {
Positioned::new("foo".to_string()) Positioned::new("foo".to_string())
], ],
fields: vec![ fields: vec![
(Token::new("f1"), Expression::Binary(BinaryOpDef{ (Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Symbol(make_value_node("bar".to_string())), left: Value::Symbol(make_value_node("bar".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
})), })),
], ],
@ -441,10 +458,12 @@ mod ast_test {
Positioned::new("foo".to_string()) Positioned::new("foo".to_string())
], ],
fields: vec![ fields: vec![
(Token::new("f1"), Expression::Binary(BinaryOpDef{ (Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Selector(make_value_node(vec![Token::new("foo"), Token::new("quux")])), left: Value::Selector(make_value_node(vec![
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), Token::new("foo", Position{line: 1, column: 1}),
Token::new("quux", Position{line: 1, column: 1})], 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
})), })),
], ],
@ -460,10 +479,12 @@ mod ast_test {
Positioned::new("foo".to_string()), Positioned::new("foo".to_string()),
], ],
fields: vec![ fields: vec![
(Token::new("f1"), Expression::Binary(BinaryOpDef{ (Token::new("f1", Position{line: 1, column: 1}), Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Selector(make_value_node(vec![Token::new("bar"), Token::new("quux")])), left: Value::Selector(make_value_node(vec![
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), Token::new("bar", Position{line: 1, column: 1}),
Token::new("quux", Position{line: 1, column: 1})], 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
})), })),
], ],

View File

@ -43,9 +43,9 @@ impl MacroDef {
// If the expressions reference Symbols not defined in the MacroDef that is also an error. // If the expressions reference Symbols not defined in the MacroDef that is also an error.
// TODO(jwall): We should probably enforce that the Expression Symbols must be in argdefs rules // TODO(jwall): We should probably enforce that the Expression Symbols must be in argdefs rules
// at Macro definition time not evaluation time. // at Macro definition time not evaluation time.
let mut scope = HashMap::<String, Rc<Val>>::new(); let mut scope = HashMap::<Positioned<String>, Rc<Val>>::new();
for (i, arg) in args.drain(0..).enumerate() { for (i, arg) in args.drain(0..).enumerate() {
scope.entry(self.argdefs[i].val.clone()).or_insert(arg.clone()); scope.entry(self.argdefs[i].clone()).or_insert(arg.clone());
} }
let b = Builder::new_with_scope(scope); let b = Builder::new_with_scope(scope);
let mut result: Vec<(Positioned<String>, Rc<Val>)> = Vec::new(); let mut result: Vec<(Positioned<String>, Rc<Val>)> = Vec::new();
@ -217,7 +217,7 @@ impl From<Val> for String {
} }
/// ValueMap defines a set of values in a parsed file. /// ValueMap defines a set of values in a parsed file.
type ValueMap = HashMap<String, Rc<Val>>; type ValueMap = HashMap<Positioned<String>, Rc<Val>>;
/// Builder parses one or more statements into a out Tuple. /// Builder parses one or more statements into a out Tuple.
pub struct Builder { pub struct Builder {
@ -285,7 +285,7 @@ impl Builder {
} }
} }
pub fn new_with_scope(scope: HashMap<String, Rc<Val>>) -> Self { pub fn new_with_scope(scope: ValueMap) -> Self {
Builder { Builder {
assets: HashMap::new(), assets: HashMap::new(),
files: HashSet::new(), files: HashSet::new(),
@ -331,7 +331,7 @@ impl Builder {
&Statement::Let { name: ref sym, value: ref expr } => { &Statement::Let { name: ref sym, value: ref expr } => {
let val = try!(self.eval_expr(expr)); let val = try!(self.eval_expr(expr));
self.last = Some(val.clone()); self.last = Some(val.clone());
match self.out.entry(sym.fragment.clone()) { match self.out.entry(sym.into()) {
Entry::Occupied(e) => { Entry::Occupied(e) => {
return Err(Box::new(BuildError::DuplicateBinding(format!("Let binding \ return Err(Box::new(BuildError::DuplicateBinding(format!("Let binding \
for {:?} already \ for {:?} already \
@ -346,14 +346,14 @@ impl Builder {
&Statement::Import { path: ref val, name: ref sym } => { &Statement::Import { path: ref val, name: ref sym } => {
if !self.files.contains(val) { if !self.files.contains(val) {
// Only parse the file once on import. // Only parse the file once on import.
if self.assets.get(&sym.fragment).is_none() { let positioned_sym = sym.into();
if self.assets.get(&positioned_sym).is_none() {
let mut b = Self::new(); let mut b = Self::new();
try!(b.build_file(&val)); try!(b.build_file(&val));
let fields: Vec<(Positioned<String>, Rc<Val>)> = let fields: Vec<(Positioned<String>, Rc<Val>)> =
b.out.drain().map(|t| (Positioned::new(t.0), t.1)) b.out.drain().collect();
.collect();
let result = Rc::new(Val::Tuple(fields)); let result = Rc::new(Val::Tuple(fields));
self.assets.entry(sym.fragment.clone()).or_insert(result.clone()); self.assets.entry(positioned_sym).or_insert(result.clone());
self.files.insert(val.clone()); self.files.insert(val.clone());
self.last = Some(result); self.last = Some(result);
} }
@ -367,11 +367,11 @@ impl Builder {
} }
fn lookup_sym(&self, sym: &Positioned<String>) -> Option<Rc<Val>> { fn lookup_sym(&self, sym: &Positioned<String>) -> Option<Rc<Val>> {
if self.out.contains_key(&sym.val) { if self.out.contains_key(sym) {
return Some(self.out[&sym.val].clone()); return Some(self.out[sym].clone());
} }
if self.assets.contains_key(&sym.val) { if self.assets.contains_key(sym) {
return Some(self.assets[&sym.val].clone()); return Some(self.assets[sym].clone());
} }
None None
} }
@ -569,10 +569,10 @@ impl Builder {
&Expression::Copy(ref def) => { &Expression::Copy(ref def) => {
let v = try!(self.lookup_selector(&def.selector)); let v = try!(self.lookup_selector(&def.selector));
if let Val::Tuple(ref src_fields) = *v { if let Val::Tuple(ref src_fields) = *v {
let mut m = HashMap::<&String, Rc<Val>>::new(); let mut m = HashMap::<Positioned<String>, Rc<Val>>::new();
// loop through fields and build up a hasmap // loop through fields and build up a hahsmap
for &(ref key, ref val) in src_fields.iter() { for &(ref key, ref val) in src_fields.iter() {
if let Entry::Vacant(v) = m.entry(&key.val) { if let Entry::Vacant(v) = m.entry(key.clone()) {
v.insert(val.clone()); v.insert(val.clone());
} else { } else {
return Err(Box::new(BuildError::TypeFail(format!("Duplicate \ return Err(Box::new(BuildError::TypeFail(format!("Duplicate \
@ -583,7 +583,7 @@ impl Builder {
} }
for &(ref key, ref val) in def.fields.iter() { for &(ref key, ref val) in def.fields.iter() {
let expr_result = try!(self.eval_expr(val)); let expr_result = try!(self.eval_expr(val));
match m.entry(&key.fragment) { match m.entry(key.into()) {
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert(expr_result); v.insert(expr_result);
} }
@ -601,9 +601,7 @@ impl Builder {
} }
}; };
} }
let mut new_fields: Vec<(Positioned<String>, Rc<Val>)> = m.drain() let mut new_fields: Vec<(Positioned<String>, Rc<Val>)> = m.drain().collect();
.map(|(s, v)| (Positioned::new(s.to_string()), v))
.collect();
// We want a stable order for the fields to make comparing tuples // We want a stable order for the fields to make comparing tuples
// easier in later code. So we sort by the field name before constructing a new tuple. // easier in later code. So we sort by the field name before constructing a new tuple.
new_fields.sort_by(|a, b| a.0.cmp(&b.0)); new_fields.sort_by(|a, b| a.0.cmp(&b.0));
@ -697,16 +695,16 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Int(make_value_node(2)), left: Value::Int(make_value_node(2, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Int(1)), Val::Int(1)),
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))), right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -722,8 +720,8 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -738,16 +736,16 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Int(make_value_node(2)), left: Value::Int(make_value_node(2, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Int(4)), Val::Int(4)),
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0)))), right: Box::new(Expression::Simple(Value::Float(make_value_node(2.0, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(4.0)), Val::Float(4.0)),
@ -763,8 +761,8 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(20)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(20, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -779,16 +777,16 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Int(make_value_node(2)), left: Value::Int(make_value_node(2, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Int(1)), Val::Int(1)),
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))), right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -804,8 +802,8 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -820,24 +818,24 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(make_value_node(1)), left: Value::Int(make_value_node(1, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Int(2)), Val::Int(2)),
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Float(make_value_node(1.0)), left: Value::Float(make_value_node(1.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0)))), right: Box::new(Expression::Simple(Value::Float(make_value_node(1.0, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(2.0)), Val::Float(2.0)),
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::String(make_value_node("foo".to_string())), left: Value::String(make_value_node("foo".to_string(), 1, 1)),
right: Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string())))), right: Box::new(Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))),
pos: None, pos: None,
}), }),
Val::String("foobar".to_string())), Val::String("foobar".to_string())),
@ -852,8 +850,8 @@ mod test {
(Expression::Binary( (Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Float(make_value_node(2.0)), left: Value::Float(make_value_node(2.0, 1, 1)),
right: Box::new(Expression::Simple(Value::Int(make_value_node(2)))), right: Box::new(Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
pos: None, pos: None,
}), }),
Val::Float(1.0)), Val::Float(1.0)),
@ -864,14 +862,14 @@ mod test {
#[test] #[test]
fn test_eval_simple_expr() { fn test_eval_simple_expr() {
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Simple(Value::Int(make_value_node(1))), Val::Int(1)), (Expression::Simple(Value::Int(make_value_node(1, 1, 1))), Val::Int(1)),
(Expression::Simple(Value::Float(make_value_node(2.0))), Val::Float(2.0)), (Expression::Simple(Value::Float(make_value_node(2.0, 1, 1))), Val::Float(2.0)),
(Expression::Simple(Value::String(make_value_node("foo".to_string()))), (Expression::Simple(Value::String(make_value_node("foo".to_string(), 1, 1))),
Val::String("foo".to_string())), Val::String("foo".to_string())),
(Expression::Simple(Value::Tuple(make_value_node(vec![ (Expression::Simple(Value::Tuple(make_value_node(vec![
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(1)))) (Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(1, 1, 1))))
]))), ], 1, 1))),
Val::Tuple(vec![(Positioned::new_with_pos("bar".to_string(), Position{line: 0, column: 0}), Val::Tuple(vec![(Positioned::new_with_pos("bar".to_string(), Position{line: 1, column: 1}),
Rc::new(Val::Int(1)))])), Rc::new(Val::Int(1)))])),
], ],
Builder::new()); Builder::new());
@ -880,9 +878,9 @@ mod test {
#[test] #[test]
fn test_eval_simple_lookup_expr() { fn test_eval_simple_lookup_expr() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Int(1))); b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Int(1)));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Simple(Value::Symbol(make_value_node("var1".to_string()))), Val::Int(1)), (Expression::Simple(Value::Symbol(make_value_node("var1".to_string(), 1, 1))), Val::Int(1)),
], ],
b); b);
} }
@ -890,8 +888,8 @@ mod test {
#[test] #[test]
fn test_eval_simple_lookup_error() { fn test_eval_simple_lookup_error() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Int(1))); b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Int(1)));
let expr = Expression::Simple(Value::Symbol(make_value_node("var".to_string()))); let expr = Expression::Simple(Value::Symbol(make_value_node("var".to_string(), 1, 1)));
assert!(b.eval_expr(&expr).is_err()); assert!(b.eval_expr(&expr).is_err());
} }
@ -899,20 +897,20 @@ mod test {
fn test_eval_selector_expr() { fn test_eval_selector_expr() {
// TODO(jwall): Tests for this expression. // TODO(jwall): Tests for this expression.
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("var1".to_string()).or_insert(Rc::new(Val::Tuple(vec![ b.out.entry(Positioned::new("var1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
(Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple( (Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple(
vec![ vec![
(Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))), (Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))),
] ]
))), ))),
]))); ])));
b.out.entry("var2".to_string()).or_insert(Rc::new(Val::Int(2))); b.out.entry(Positioned::new("var2".to_string())).or_insert(Rc::new(Val::Int(2)));
b.out b.out
.entry("var3".to_string()) .entry(Positioned::new("var3".to_string()))
.or_insert(Rc::new(Val::Tuple(vec![(Positioned::new("lvl1".to_string()), .or_insert(Rc::new(Val::Tuple(vec![(Positioned::new("lvl1".to_string()),
Rc::new(Val::Int(4)))]))); Rc::new(Val::Int(4)))])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1")]))), Val::Tuple( (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1})], 1, 1))), Val::Tuple(
vec![ vec![
(Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple( (Positioned::new("lvl1".to_string()), Rc::new(Val::Tuple(
vec![ vec![
@ -921,21 +919,21 @@ mod test {
))), ))),
] ]
)), )),
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1"), (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1}),
Token::new("lvl1")]))), Token::new("lvl1", Position{line: 1, column: 1})], 1, 1))),
Val::Tuple( Val::Tuple(
vec![ vec![
(Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))), (Positioned::new("lvl2".to_string()), Rc::new(Val::Int(3))),
] ]
)), )),
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1"), (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var1", Position{line: 1, column: 1}),
Token::new("lvl1"), Token::new("lvl1", Position{line: 1, column: 1}),
Token::new("lvl2")]))), Token::new("lvl2", Position{line: 1, column: 1})], 1, 1))),
Val::Int(3)), Val::Int(3)),
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var2")]))), (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var2", Position{line: 1, column: 1})], 1, 1))),
Val::Int(2)), Val::Int(2)),
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var3"), (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("var3", Position{line: 1, column: 1}),
Token::new("lvl1")]))), Token::new("lvl1", Position{line: 1, column: 1})], 1, 1))),
Val::Int(4)), Val::Int(4)),
], b); ], b);
} }
@ -945,7 +943,7 @@ mod test {
fn test_expr_copy_no_such_tuple() { fn test_expr_copy_no_such_tuple() {
let b = Builder::new(); let b = Builder::new();
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1")], fields: Vec::new(), pos: None}), (Expression::Copy(CopyDef{selector: vec![Token::new("tpl1", Position{line: 1, column: 1})], fields: Vec::new(), pos: None}),
Val::Tuple(Vec::new())), Val::Tuple(Vec::new())),
], b); ], b);
} }
@ -954,9 +952,9 @@ mod test {
#[should_panic(expected = "Expected Tuple got Integer")] #[should_panic(expected = "Expected Tuple got Integer")]
fn test_expr_copy_not_a_tuple() { fn test_expr_copy_not_a_tuple() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Int(1))); b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Int(1)));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy(CopyDef{selector: vec![Token::new("tpl1")], fields: Vec::new(), pos: None}), (Expression::Copy(CopyDef{selector: vec![Token::new("tpl1", Position{line: 1, column: 1})], fields: Vec::new(), pos: None}),
Val::Tuple(Vec::new())), Val::Tuple(Vec::new())),
], b); ], b);
} }
@ -965,19 +963,19 @@ mod test {
#[should_panic(expected = "Expected type Integer for field fld1 but got String")] #[should_panic(expected = "Expected type Integer for field fld1 but got String")]
fn test_expr_copy_field_type_error() { fn test_expr_copy_field_type_error() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Tuple(vec![ b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))), (Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
]))); ])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy( (Expression::Copy(
CopyDef{ CopyDef{
selector: vec![Token::new("tpl1")], selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
fields: vec![(Token::new("fld1"), fields: vec![(Token::new("fld1", Position{line: 1, column: 1}),
Expression::Simple(Value::String(make_value_node("2".to_string()))))], Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1))))],
pos: None}), pos: None}),
Val::Tuple( Val::Tuple(
vec![ vec![
(Positioned::new("fld1".to_string()), Rc::new(Val::String("2".to_string()))), (Positioned::new_with_pos("fld1".to_string(), Position{line: 1, column: 1}), Rc::new(Val::String("2".to_string()))),
], ],
)), )),
], b); ], b);
@ -989,15 +987,15 @@ mod test {
fn test_expr_copy() { fn test_expr_copy() {
// TODO(jwall): Tests for this expression. // TODO(jwall): Tests for this expression.
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("tpl1".to_string()).or_insert(Rc::new(Val::Tuple(vec![ b.out.entry(Positioned::new("tpl1".to_string())).or_insert(Rc::new(Val::Tuple(vec![
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))), (Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
]))); ])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Copy( (Expression::Copy(
CopyDef{ CopyDef{
selector: vec![Token::new("tpl1")], selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
fields: vec![(Token::new("fld2"), fields: vec![(Token::new("fld2", Position{line: 1, column: 1}),
Expression::Simple(Value::String(make_value_node("2".to_string()))))], Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1))))],
pos: None, pos: None,
}), }),
// Add a new field to the copy // Add a new field to the copy
@ -1007,18 +1005,18 @@ mod test {
// semantics though so at some point we should probably be less restrictive. // semantics though so at some point we should probably be less restrictive.
vec![ vec![
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))), (Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
(Positioned::new("fld2".to_string()), Rc::new(Val::String("2".to_string()))), (Positioned::new_with_pos("fld2".to_string(), Position{line: 1, column: 1}), Rc::new(Val::String("2".to_string()))),
], ],
)), )),
// Overwrite a field in the copy // Overwrite a field in the copy
(Expression::Copy( (Expression::Copy(
CopyDef{ CopyDef{
selector: vec![Token::new("tpl1")], selector: vec![Token::new("tpl1", Position{line: 1, column: 1})],
fields: vec![ fields: vec![
(Token::new("fld1"), (Token::new("fld1", Position{line: 1, column: 1}),
Expression::Simple(Value::Int(make_value_node(3)))), Expression::Simple(Value::Int(make_value_node(3, 1, 1)))),
(Token::new("fld2"), (Token::new("fld2", Position{line: 1, column: 1}),
Expression::Simple(Value::String(make_value_node("2".to_string())))), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
], ],
pos: None, pos: None,
}), }),
@ -1029,7 +1027,7 @@ mod test {
], ],
)), )),
// The source tuple is still unmodified. // The source tuple is still unmodified.
(Expression::Simple(Value::Selector(make_value_node(vec![Token::new("tpl1")]))), (Expression::Simple(Value::Selector(make_value_node(vec![Token::new("tpl1", Position{line: 1, column: 1})], 1, 1))),
Val::Tuple( Val::Tuple(
vec![ vec![
(Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))), (Positioned::new("fld1".to_string()), Rc::new(Val::Int(1))),
@ -1041,21 +1039,21 @@ mod test {
#[test] #[test]
fn test_macro_call() { fn test_macro_call() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("tstmac".to_string()).or_insert(Rc::new(Val::Macro(MacroDef{ b.out.entry(Positioned::new("tstmac".to_string())).or_insert(Rc::new(Val::Macro(MacroDef{
argdefs: vec![Positioned::new("arg1".to_string())], argdefs: vec![Positioned::new("arg1".to_string())],
fields: vec![ fields: vec![
(Token::new("foo"), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string())))), (Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string(), 1, 1)))),
], ],
pos: None, pos: None,
}))); })));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Call(CallDef{ (Expression::Call(CallDef{
macroref: vec![Token::new("tstmac")], macroref: vec![Token::new("tstmac", Position{line: 1, column: 1})],
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string())))], arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))],
pos: None, pos: None,
}), }),
Val::Tuple(vec![ Val::Tuple(vec![
(Positioned::new_with_pos("foo".to_string(), Position{line: 0, column: 0}), (Positioned::new_with_pos("foo".to_string(), Position{line: 1, column: 1}),
Rc::new(Val::String("bar".to_string()))), Rc::new(Val::String("bar".to_string()))),
])), ])),
], b); ], b);
@ -1066,19 +1064,19 @@ mod test {
fn test_macro_hermetic() { fn test_macro_hermetic() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out b.out
.entry("arg1".to_string()) .entry(Positioned::new("arg1".to_string()))
.or_insert(Rc::new(Val::String("bar".to_string()))); .or_insert(Rc::new(Val::String("bar".to_string())));
b.out.entry("tstmac".to_string()).or_insert(Rc::new(Val::Macro(MacroDef{ b.out.entry(Positioned::new("tstmac".to_string())).or_insert(Rc::new(Val::Macro(MacroDef{
argdefs: vec![Positioned::new("arg2".to_string())], argdefs: vec![Positioned::new("arg2".to_string())],
fields: vec![ fields: vec![
(Token::new("foo"), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string())))), (Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::Symbol(make_value_node("arg1".to_string(), 1, 1)))),
], ],
pos: None, pos: None,
}))); })));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Call(CallDef{ (Expression::Call(CallDef{
macroref: vec![Token::new("tstmac")], macroref: vec![Token::new("tstmac", Position{line: 1, column: 1})],
arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string())))], arglist: vec![Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1)))],
pos: None, pos: None,
}), }),
Val::Tuple(vec![ Val::Tuple(vec![
@ -1091,28 +1089,28 @@ mod test {
fn test_select_expr() { fn test_select_expr() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out b.out
.entry("foo".to_string()) .entry(Positioned::new("foo".to_string()))
.or_insert(Rc::new(Val::String("bar".to_string()))); .or_insert(Rc::new(Val::String("bar".to_string())));
b.out b.out
.entry("baz".to_string()) .entry(Positioned::new("baz".to_string()))
.or_insert(Rc::new(Val::String("boo".to_string()))); .or_insert(Rc::new(Val::String("boo".to_string())));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Select(SelectDef{ (Expression::Select(SelectDef{
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string())))), val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1)))),
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
tuple: vec![ tuple: vec![
(Token::new("foo"), Expression::Simple(Value::String(make_value_node("2".to_string())))), (Token::new("foo", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))), (Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
], ],
pos: None, pos: None,
}), }),
Val::Int(2)), Val::Int(2)),
(Expression::Select(SelectDef{ (Expression::Select(SelectDef{
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("baz".to_string())))), val: Box::new(Expression::Simple(Value::Symbol(make_value_node("baz".to_string(), 1, 1)))),
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
tuple: vec![ tuple: vec![
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))), (Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
(Token::new("quux"), Expression::Simple(Value::String(make_value_node("2".to_string())))), (Token::new("quux", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
], ],
pos: None, pos: None,
}), }),
@ -1125,14 +1123,14 @@ mod test {
#[should_panic(expected ="Expected String but got Integer in Select expression")] #[should_panic(expected ="Expected String but got Integer in Select expression")]
fn test_select_expr_not_a_string() { fn test_select_expr_not_a_string() {
let mut b = Builder::new(); let mut b = Builder::new();
b.out.entry("foo".to_string()).or_insert(Rc::new(Val::Int(4))); b.out.entry(Positioned::new("foo".to_string())).or_insert(Rc::new(Val::Int(4)));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Select(SelectDef{ (Expression::Select(SelectDef{
val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string())))), val: Box::new(Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1)))),
default: Box::new(Expression::Simple(Value::Int(make_value_node(1)))), default: Box::new(Expression::Simple(Value::Int(make_value_node(1, 1, 1)))),
tuple: vec![ tuple: vec![
(Token::new("bar"), Expression::Simple(Value::Int(make_value_node(2)))), (Token::new("bar", Position{line: 1, column: 1}), Expression::Simple(Value::Int(make_value_node(2, 1, 1)))),
(Token::new("quux"), Expression::Simple(Value::String(make_value_node("2".to_string())))), (Token::new("quux", Position{line: 1, column: 1}), Expression::Simple(Value::String(make_value_node("2".to_string(), 1, 1)))),
], ],
pos: None, pos: None,
}), }),
@ -1144,12 +1142,12 @@ mod test {
fn test_let_statement() { fn test_let_statement() {
let mut b = Builder::new(); let mut b = Builder::new();
let stmt = Statement::Let { let stmt = Statement::Let {
name: Token::new("foo"), name: Token::new("foo", Position{line: 1, column: 1}),
value: Expression::Simple(Value::String(make_value_node("bar".to_string()))), value: Expression::Simple(Value::String(make_value_node("bar".to_string(), 1, 1))),
}; };
b.build_stmt(&stmt).unwrap(); b.build_stmt(&stmt).unwrap();
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string()))), (Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1))),
Val::String("bar".to_string())), Val::String("bar".to_string())),
], ],
b); b);
@ -1159,20 +1157,20 @@ mod test {
fn test_build_file_string() { fn test_build_file_string() {
let mut b = Builder::new(); let mut b = Builder::new();
b.build_file_string("foo.ucg", "let foo = 1;".to_string()).unwrap(); b.build_file_string("foo.ucg", "let foo = 1;".to_string()).unwrap();
let key = "foo"; let key = Positioned::new("foo".to_string());
assert!(b.out.contains_key(key)); assert!(b.out.contains_key(&key));
} }
#[test] #[test]
fn test_asset_symbol_lookups() { fn test_asset_symbol_lookups() {
let mut b = Builder::new(); let mut b = Builder::new();
b.assets.entry("foo".to_string()).or_insert(Rc::new(Val::Tuple(vec![ b.assets.entry(Positioned::new("foo".to_string())).or_insert(Rc::new(Val::Tuple(vec![
(Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![ (Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![
(Positioned::new("quux".to_string()), Rc::new(Val::Int(1))), (Positioned::new("quux".to_string()), Rc::new(Val::Int(1))),
]))), ]))),
]))); ])));
test_expr_to_val(vec![ test_expr_to_val(vec![
(Expression::Simple(Value::Symbol(make_value_node("foo".to_string()))), (Expression::Simple(Value::Symbol(make_value_node("foo".to_string(), 1, 1))),
Val::Tuple(vec![ Val::Tuple(vec![
(Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![ (Positioned::new("bar".to_string()), Rc::new(Val::Tuple(vec![
(Positioned::new("quux".to_string()), Rc::new(Val::Int(1))), (Positioned::new("quux".to_string()), Rc::new(Val::Int(1))),

View File

@ -13,6 +13,7 @@
// limitations under the License. // limitations under the License.
use std::str::FromStr; use std::str::FromStr;
use std::error::Error; use std::error::Error;
use std::borrow::Borrow;
use ast::*; use ast::*;
use tokenizer::*; use tokenizer::*;
@ -32,20 +33,19 @@ quick_error! {
} }
// TODO(jwall): Convert to tokenizer steps followed by parser steps.
// TODO(jwall): Error Reporting with Line and Column information. // TODO(jwall): Error Reporting with Line and Column information.
type ParseResult<O> = Result<O, Box<Error>>; type ParseResult<O> = Result<O, Box<Error>>;
fn symbol_to_value(s: Token) -> ParseResult<Value> { fn symbol_to_value(s: Token) -> ParseResult<Value> {
Ok(Value::Symbol(value_node!(s.fragment.to_string()))) Ok(Value::Symbol(value_node!(s.fragment.to_string(), s.pos)))
} }
// symbol is a bare unquoted field. // symbol is a bare unquoted field.
named!(symbol( Span ) -> Value, map_res!(barewordtok, symbol_to_value)); named!(symbol( Span ) -> Value, map_res!(barewordtok, symbol_to_value));
fn str_to_value(s: Token) -> ParseResult<Value> { fn str_to_value(s: Token) -> ParseResult<Value> {
Ok(Value::String(value_node!(s.fragment.to_string()))) Ok(Value::String(value_node!(s.fragment.to_string(), s.pos)))
} }
// quoted_value is a quoted string. // quoted_value is a quoted string.
@ -55,15 +55,19 @@ named!(quoted_value( Span ) -> Value,
// Helper function to make the return types work for down below. // Helper function to make the return types work for down below.
fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseResult<Value> { fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseResult<Value> {
let pref = match v.0 { let (pref, mut pref_pos) = match v.0 {
None => "", None => ("", Position{line: 0, column: 0}),
Some(ref bs) => &bs.fragment, Some(ref bs) => (bs.fragment.borrow(), bs.pos.clone()),
}; };
let has_dot = v.1.is_some(); let has_dot = v.1.is_some();
if v.0.is_some() && !has_dot && v.2.is_none() { if v.0.is_some() && !has_dot && v.2.is_none() {
return Ok(Value::Int(value_node!(try!(FromStr::from_str(pref))))); return Ok(Value::Int(value_node!(try!(FromStr::from_str(pref)), pref_pos)));
}
if v.0.is_none() && has_dot {
pref_pos = v.1.unwrap().pos;
} }
let suf = match v.2 { let suf = match v.2 {
@ -72,8 +76,9 @@ fn triple_to_number(v: (Option<Token>, Option<Token>, Option<Token>)) -> ParseRe
}; };
let to_parse = pref.to_string() + "." + suf; let to_parse = pref.to_string() + "." + suf;
// TODO(jwall): if there is an error we should report where that error occured.
let f = try!(FromStr::from_str(&to_parse)); let f = try!(FromStr::from_str(&to_parse));
return Ok(Value::Float(value_node!(f))); return Ok(Value::Float(value_node!(f, pref_pos)));
} }
// NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters // NOTE(jwall): HERE THERE BE DRAGONS. The order for these matters
@ -130,8 +135,8 @@ named!(
); );
// Helper function to make the return types work for down below. // Helper function to make the return types work for down below.
fn vec_to_tuple(v: FieldList) -> ParseResult<Value> { fn vec_to_tuple(t: (Span, FieldList)) -> ParseResult<Value> {
Ok(Value::Tuple(value_node!(v))) Ok(Value::Tuple(value_node!(t.1, Position{line: t.0.line as usize, column: t.0.offset as usize})))
} }
named!(field_list( Span ) -> FieldList, named!(field_list( Span ) -> FieldList,
@ -141,9 +146,13 @@ named!(
#[doc="Capture a tuple of named fields with values. {<field>=<value>,...}"], #[doc="Capture a tuple of named fields with values. {<field>=<value>,...}"],
tuple( Span ) -> Value, tuple( Span ) -> Value,
map_res!( map_res!(
delimited!(lbracetok, do_parse!(
pos: position!() >>
v: delimited!(lbracetok,
ws!(field_list), ws!(field_list),
rbracetok), rbracetok) >>
(pos, v)
),
vec_to_tuple vec_to_tuple
) )
); );
@ -161,12 +170,12 @@ named!(simple_expression( Span ) -> Expression,
) )
); );
fn tuple_to_binary_expression(tpl: (BinaryExprType, Value, Expression)) -> ParseResult<Expression> { fn tuple_to_binary_expression(tpl: (Span, BinaryExprType, Value, Expression)) -> ParseResult<Expression> {
Ok(Expression::Binary(BinaryOpDef { Ok(Expression::Binary(BinaryOpDef {
kind: tpl.0, kind: tpl.1,
left: tpl.1, left: tpl.2,
right: Box::new(tpl.2), right: Box::new(tpl.3),
pos: None, pos: Some(Position{line: tpl.0.line as usize, column: tpl.0.offset as usize}),
})) }))
} }
@ -178,10 +187,11 @@ macro_rules! do_binary_expr {
// particularly like this but I'm living with it for now. // particularly like this but I'm living with it for now.
map_res!( map_res!(
$i, do_parse!( $i, do_parse!(
pos: position!() >>
left: value >> left: value >>
ws!($fn) >> ws!($fn) >>
right: expression >> right: expression >>
($typ, left, right) (pos, $typ, left, right)
), ),
tuple_to_binary_expression tuple_to_binary_expression
) )
@ -222,7 +232,6 @@ fn assert_nonempty_list<T>(v: Vec<T>) -> ParseResult<Vec<T>> {
return Ok(v); return Ok(v);
} }
// TODO(jwall): We should assert that this is a nonempty list that comes out of here.
named!(selector_list( Span ) -> SelectorList, named!(selector_list( Span ) -> SelectorList,
map_res!( map_res!(
separated_list!(dottok, barewordtok), separated_list!(dottok, barewordtok),
@ -230,43 +239,43 @@ named!(selector_list( Span ) -> SelectorList,
) )
); );
fn tuple_to_copy(t: (SelectorList, FieldList)) -> ParseResult<Expression> { fn tuple_to_copy(t: (Span, SelectorList, FieldList)) -> ParseResult<Expression> {
Ok(Expression::Copy(CopyDef { Ok(Expression::Copy(CopyDef {
selector: t.0, selector: t.1,
fields: t.1, fields: t.2,
pos: None, pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
})) }))
} }
named!(copy_expression( Span ) -> Expression, named!(copy_expression( Span ) -> Expression,
map_res!( map_res!(
do_parse!( do_parse!(
pos: position!() >>
selector: selector_list >> selector: selector_list >>
lbracetok >> lbracetok >>
fields: ws!(field_list) >> fields: ws!(field_list) >>
rbracetok >> rbracetok >>
(selector, fields) (pos, selector, fields)
), ),
tuple_to_copy tuple_to_copy
) )
); );
fn tuple_to_macro(mut t: (Vec<Value>, Value)) -> ParseResult<Expression> { fn tuple_to_macro(mut t: (Span, Vec<Value>, Value)) -> ParseResult<Expression> {
match t.1 { match t.2 {
Value::Tuple(v) => { Value::Tuple(v) => {
Ok(Expression::Macro(MacroDef { Ok(Expression::Macro(MacroDef {
// TODO(jwall): The position information here is not as accurate as we might want. argdefs: t.1
argdefs: t.0
.drain(0..) .drain(0..)
.map(|s| { .map(|s| {
Positioned { Positioned {
pos: v.pos.clone(), pos: Some(s.pos().clone()),
val: s.to_string(), val: s.to_string(),
} }
}) })
.collect(), .collect(),
fields: v.val, fields: v.val,
pos: v.pos, pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
})) }))
} }
// TODO(jwall): Show a better version of the unexpected parsed value. // TODO(jwall): Show a better version of the unexpected parsed value.
@ -281,26 +290,27 @@ named!(arglist( Span ) -> Vec<Value>, separated_list!(ws!(commatok), symbol));
named!(macro_expression( Span ) -> Expression, named!(macro_expression( Span ) -> Expression,
map_res!( map_res!(
do_parse!( do_parse!(
pos: position!() >>
macrotok >> macrotok >>
ws!(lparentok) >> ws!(lparentok) >>
arglist: ws!(arglist) >> arglist: ws!(arglist) >>
rparentok >> rparentok >>
ws!(fatcommatok) >> ws!(fatcommatok) >>
map: tuple >> map: tuple >>
(arglist, map) (pos, arglist, map)
), ),
tuple_to_macro tuple_to_macro
) )
); );
fn tuple_to_select(t: (Expression, Expression, Value)) -> ParseResult<Expression> { fn tuple_to_select(t: (Span, Expression, Expression, Value)) -> ParseResult<Expression> {
match t.2 { match t.3 {
Value::Tuple(v) => { Value::Tuple(v) => {
Ok(Expression::Select(SelectDef { Ok(Expression::Select(SelectDef {
val: Box::new(t.0), val: Box::new(t.1),
default: Box::new(t.1), default: Box::new(t.2),
tuple: v.val, tuple: v.val,
pos: None, pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
})) }))
} }
// TODO(jwall): Show a better version of the unexpected parsed value. // TODO(jwall): Show a better version of the unexpected parsed value.
@ -313,11 +323,12 @@ fn tuple_to_select(t: (Expression, Expression, Value)) -> ParseResult<Expression
named!(select_expression( Span ) -> Expression, named!(select_expression( Span ) -> Expression,
map_res!( map_res!(
do_parse!( do_parse!(
pos: position!() >>
selecttok >> selecttok >>
val: ws!(terminated!(expression, commatok)) >> val: ws!(terminated!(expression, commatok)) >>
default: ws!(terminated!(expression, commatok)) >> default: ws!(terminated!(expression, commatok)) >>
map: ws!(tuple) >> map: ws!(tuple) >>
(val, default, map) (pos, val, default, map)
), ),
tuple_to_select tuple_to_select
) )
@ -345,25 +356,29 @@ named!(format_expression( Span ) -> Expression,
) )
); );
fn tuple_to_call(t: (Value, Vec<Expression>)) -> ParseResult<Expression> { fn tuple_to_call(t: (Span, Value, Vec<Expression>)) -> ParseResult<Expression> {
if let Value::Selector(sl) = t.0 { if let Value::Selector(sl) = t.1 {
Ok(Expression::Call(CallDef { Ok(Expression::Call(CallDef {
macroref: sl.val, macroref: sl.val,
arglist: t.1, arglist: t.2,
pos: None, pos: Some(Position{line: t.0.line as usize, column: t.0.offset as usize}),
})) }))
} else { } else {
Err(Box::new(ParseError::UnexpectedToken("Selector".to_string(), format!("{:?}", t.0)))) Err(Box::new(ParseError::UnexpectedToken("Selector".to_string(), format!("{:?}", t.0))))
} }
} }
fn vec_to_selector_value(v: SelectorList) -> ParseResult<Value> { fn vec_to_selector_value(t: (Span, SelectorList)) -> ParseResult<Value> {
Ok(Value::Selector(value_node!(v))) Ok(Value::Selector(value_node!(t.1, Position{line: t.0.line as usize, column: t.0.offset as usize})))
} }
named!(selector_value( Span ) -> Value, named!(selector_value( Span ) -> Value,
map_res!( map_res!(
ws!(selector_list), do_parse!(
pos: position!() >>
sl: ws!(selector_list) >>
(pos, sl)
),
vec_to_selector_value vec_to_selector_value
) )
); );
@ -371,11 +386,12 @@ named!(selector_value( Span ) -> Value,
named!(call_expression( Span ) -> Expression, named!(call_expression( Span ) -> Expression,
map_res!( map_res!(
do_parse!( do_parse!(
pos: position!() >>
macroname: selector_value >> macroname: selector_value >>
lparentok >> lparentok >>
args: ws!(separated_list!(ws!(commatok), expression)) >> args: ws!(separated_list!(ws!(commatok), expression)) >>
rparentok >> rparentok >>
(macroname, args) (pos, macroname, args)
), ),
tuple_to_call tuple_to_call
) )
@ -468,8 +484,6 @@ named!(statement( Span ) -> Statement,
named!(pub parse( Span ) -> Vec<Statement>, many1!(ws!(statement))); named!(pub parse( Span ) -> Vec<Statement>, many1!(ws!(statement)));
// TODO(jwall): Full Statement parsing tests.
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::{Statement, Expression, Value, MacroDef, SelectDef, CallDef}; use super::{Statement, Expression, Value, MacroDef, SelectDef, CallDef};
@ -525,7 +539,7 @@ mod test {
column: 5, column: 5,
}, },
}, },
value: Expression::Simple(Value::Float(value_node!(1.0))) value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 11})))
})); }));
stmt = "1.0;"; stmt = "1.0;";
let input = LocatedSpan::new(stmt); let input = LocatedSpan::new(stmt);
@ -537,7 +551,7 @@ mod test {
fragment: "", fragment: "",
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Float(value_node!(1.0)))))); Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
} }
#[test] #[test]
@ -593,7 +607,7 @@ mod test {
column: 5, column: 5,
}, },
}, },
value: Expression::Simple(Value::Float(value_node!(1.0))) value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 11})))
})); }));
let_stmt = "let foo= 1.0;"; let_stmt = "let foo= 1.0;";
@ -610,7 +624,7 @@ mod test {
column: 5, column: 5,
} }
}, },
value: Expression::Simple(Value::Float(value_node!(1.0)))})); value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 10})))}));
let_stmt = "let foo =1.0;"; let_stmt = "let foo =1.0;";
assert_eq!(let_statement(LocatedSpan::new(let_stmt)), assert_eq!(let_statement(LocatedSpan::new(let_stmt)),
IResult::Done(LocatedSpan{ IResult::Done(LocatedSpan{
@ -625,7 +639,7 @@ mod test {
column: 5, column: 5,
} }
}, },
value: Expression::Simple(Value::Float(value_node!(1.0)))})); value: Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 10})))}));
} }
#[test] #[test]
@ -638,7 +652,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Float(value_node!(1.0)))))); Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new("1.0 ;")), assert_eq!(expression_statement(LocatedSpan::new("1.0 ;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -646,7 +660,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Float(value_node!(1.0)))))); Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new(" 1.0;")), assert_eq!(expression_statement(LocatedSpan::new(" 1.0;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -654,7 +668,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Float(value_node!(1.0)))))); Expression::Simple(Value::Float(value_node!(1.0, Position{line: 1, column: 2}))))));
assert_eq!(expression_statement(LocatedSpan::new("foo;")), assert_eq!(expression_statement(LocatedSpan::new("foo;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -662,7 +676,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Symbol(value_node!("foo".to_string())))))); Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new("foo ;")), assert_eq!(expression_statement(LocatedSpan::new("foo ;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -670,7 +684,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Symbol(value_node!("foo".to_string())))))); Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new(" foo;")), assert_eq!(expression_statement(LocatedSpan::new(" foo;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -678,7 +692,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::Symbol(value_node!("foo".to_string())))))); Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 2}))))));
assert_eq!(expression_statement(LocatedSpan::new("\"foo\";")), assert_eq!(expression_statement(LocatedSpan::new("\"foo\";")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -686,7 +700,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::String(value_node!("foo".to_string())))))); Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new("\"foo\" ;")), assert_eq!(expression_statement(LocatedSpan::new("\"foo\" ;")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -694,7 +708,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::String(value_node!("foo".to_string())))))); Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 1}))))));
assert_eq!(expression_statement(LocatedSpan::new(" \"foo\";")), assert_eq!(expression_statement(LocatedSpan::new(" \"foo\";")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -702,7 +716,7 @@ mod test {
line: 1, line: 1,
}, },
Statement::Expression( Statement::Expression(
Expression::Simple(Value::String(value_node!("foo".to_string())))))); Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 2}))))));
} }
#[test] #[test]
@ -713,14 +727,14 @@ mod test {
offset: 1, offset: 1,
line: 1, line: 1,
}, },
Expression::Simple(Value::Int(value_node!(1))))); Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 1})))));
assert_eq!(expression(LocatedSpan::new("foo")), assert_eq!(expression(LocatedSpan::new("foo")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
offset: 3, offset: 3,
line: 1, line: 1,
}, },
Expression::Simple(Value::Symbol(value_node!("foo".to_string()))))); Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1})))));
assert_eq!(expression(LocatedSpan::new("1 + 1")), assert_eq!(expression(LocatedSpan::new("1 + 1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
fragment: "", fragment: "",
@ -729,9 +743,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1 - 1")), assert_eq!(expression(LocatedSpan::new("1 - 1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -741,9 +755,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1 * 1")), assert_eq!(expression(LocatedSpan::new("1 * 1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -753,9 +767,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1 / 1")), assert_eq!(expression(LocatedSpan::new("1 / 1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -765,9 +779,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 5})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1+1")), assert_eq!(expression(LocatedSpan::new("1+1")),
@ -778,9 +792,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1-1")), assert_eq!(expression(LocatedSpan::new("1-1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -790,9 +804,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Sub, kind: BinaryExprType::Sub,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1*1")), assert_eq!(expression(LocatedSpan::new("1*1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -802,9 +816,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Mul, kind: BinaryExprType::Mul,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
assert_eq!(expression(LocatedSpan::new("1/1")), assert_eq!(expression(LocatedSpan::new("1/1")),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -814,9 +828,9 @@ mod test {
}, },
Expression::Binary(BinaryOpDef{ Expression::Binary(BinaryOpDef{
kind: BinaryExprType::Div, kind: BinaryExprType::Div,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 1})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 3})))),
pos: None, pos: Some(Position { line: 1, column: 0 }),
}))); })));
let macro_expr = "macro (arg1, arg2) => { foo = arg1 }"; let macro_expr = "macro (arg1, arg2) => { foo = arg1 }";
assert_eq!(expression(LocatedSpan::new(macro_expr)), assert_eq!(expression(LocatedSpan::new(macro_expr)),
@ -827,14 +841,15 @@ mod test {
}, },
Expression::Macro(MacroDef{ Expression::Macro(MacroDef{
argdefs: vec![ argdefs: vec![
Positioned::new("arg1".to_string()), Positioned::new_with_pos("arg1".to_string(), Position{line: 1, column: 8}),
Positioned::new("arg2".to_string()), Positioned::new_with_pos("arg2".to_string(), Position{line: 1, column: 14}),
], ],
fields: vec![ fields: vec![
(Token::new_with_pos("foo", Position{line: 1, column: 25}), (Token::new("foo", Position{line: 1, column: 25}),
Expression::Simple(Value::Symbol(value_node!("arg1".to_string())))), Expression::Simple(Value::Symbol(value_node!("arg1".to_string(), Position{line: 1, column: 31})))),
], ],
pos: None, // FIXME(jwall): I think this is incorrect.
pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -846,13 +861,13 @@ mod test {
line: 1, line: 1,
}, },
Expression::Select(SelectDef{ Expression::Select(SelectDef{
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string())))), val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 8})))),
default: Box::new(Expression::Simple(Value::Int(value_node!(1)))), default: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 13})))),
tuple: vec![ tuple: vec![
(Token::new_with_pos("foo", Position{line: 1, column: 18}), (Token::new("foo", Position{line: 1, column: 18}),
Expression::Simple(Value::Int(value_node!(2)))) Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 24}))))
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -864,13 +879,13 @@ mod test {
line: 1, line: 1,
}, },
Expression::Call(CallDef{ Expression::Call(CallDef{
macroref: vec![Token::new_with_pos("foo", Position{line:1,column: 1}), macroref: vec![Token::new("foo", Position{line:1,column: 1}),
Token::new_with_pos("bar", Position{line:1,column: 5})], Token::new("bar", Position{line:1,column: 5})],
arglist: vec![ arglist: vec![
Expression::Simple(Value::Int(value_node!(1))), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 10}))),
Expression::Simple(Value::String(value_node!("foo".to_string()))), Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 13}))),
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -885,9 +900,9 @@ mod test {
Expression::Binary( Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 2})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 6})))),
pos: None, pos: Some(Position { line: 1, column: 1 }),
} }
) )
) )
@ -913,8 +928,8 @@ mod test {
Expression::Format( Expression::Format(
FormatDef{ FormatDef{
template: "foo @ @".to_string(), template: "foo @ @".to_string(),
args: vec![Expression::Simple(Value::Int(value_node!(1))), args: vec![Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 14}))),
Expression::Simple(Value::Int(value_node!(2)))], Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 17})))],
pos: Some(Position{line: 1, column: 1}), pos: Some(Position{line: 1, column: 1}),
} }
) )
@ -931,8 +946,8 @@ mod test {
Expression::Format( Expression::Format(
FormatDef{ FormatDef{
template: "foo @ @".to_string(), template: "foo @ @".to_string(),
args: vec![Expression::Simple(Value::Int(value_node!(1))), args: vec![Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 12}))),
Expression::Simple(Value::Int(value_node!(2)))], Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 15})))],
pos: Some(Position { line: 1, column: 1 }), pos: Some(Position { line: 1, column: 1 }),
} }
) )
@ -957,12 +972,12 @@ mod test {
offset: copy_expr.len(), offset: copy_expr.len(),
}, },
Expression::Call(CallDef{ Expression::Call(CallDef{
macroref: vec![Token::new_with_pos("foo", Position{line:1, column: 1})], macroref: vec![Token::new("foo", Position{line:1, column: 1})],
arglist: vec![ arglist: vec![
Expression::Simple(Value::Int(value_node!(1))), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 6}))),
Expression::Simple(Value::String(value_node!("foo".to_string()))), Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 9}))),
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -976,13 +991,13 @@ mod test {
offset: copy_expr.len(), offset: copy_expr.len(),
}, },
Expression::Call(CallDef{ Expression::Call(CallDef{
macroref: vec![Token::new_with_pos("foo", Position{line: 1, column: 1}), macroref: vec![Token::new("foo", Position{line: 1, column: 1}),
Token::new_with_pos("bar", Position{line: 1, column: 5})], Token::new("bar", Position{line: 1, column: 5})],
arglist: vec![ arglist: vec![
Expression::Simple(Value::Int(value_node!(1))), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 10}))),
Expression::Simple(Value::String(value_node!("foo".to_string()))), Expression::Simple(Value::String(value_node!("foo".to_string(), Position{line: 1, column: 13}))),
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -1003,12 +1018,12 @@ mod test {
line: 1, line: 1,
}, },
Expression::Select(SelectDef{ Expression::Select(SelectDef{
val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string())))), val: Box::new(Expression::Simple(Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 8})))),
default: Box::new(Expression::Simple(Value::Int(value_node!(1)))), default: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 13})))),
tuple: vec![ tuple: vec![
(Token::new_with_pos("foo", Position{line: 1, column: 18}), Expression::Simple(Value::Int(value_node!(2)))) (Token::new("foo", Position{line: 1, column: 18}), Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 24}))))
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -1037,12 +1052,12 @@ mod test {
line: 1 line: 1
}, },
Expression::Macro(MacroDef{ Expression::Macro(MacroDef{
argdefs: vec![Positioned::new("arg1".to_string()), argdefs: vec![Positioned::new_with_pos("arg1".to_string(), Position{line: 1, column: 8}),
Positioned::new("arg2".to_string())], Positioned::new_with_pos("arg2".to_string(), Position{line: 1, column: 14})],
fields: vec![(Token::new_with_pos("foo", Position{line: 1, column: 24}), Expression::Simple(Value::Int(value_node!(1)))), fields: vec![(Token::new("foo", Position{line: 1, column: 24}), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 28})))),
(Token::new_with_pos("bar", Position{line: 1, column: 30}), Expression::Simple(Value::Int(value_node!(2)))) (Token::new("bar", Position{line: 1, column: 30}), Expression::Simple(Value::Int(value_node!(2, Position{line: 1, column: 34}))))
], ],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -1063,9 +1078,9 @@ mod test {
line: 1 line: 1
}, },
Expression::Copy(CopyDef{ Expression::Copy(CopyDef{
selector: vec![Token::new_with_pos("foo", Position{line: 1, column: 1})], selector: vec![Token::new("foo", Position{line: 1, column: 1})],
fields: Vec::new(), fields: Vec::new(),
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -1079,10 +1094,10 @@ mod test {
line: 1 line: 1
}, },
Expression::Copy(CopyDef{ Expression::Copy(CopyDef{
selector: vec![Token::new_with_pos("foo", Position{line: 1, column: 1})], selector: vec![Token::new("foo", Position{line: 1, column: 1})],
fields: vec![(Token::new_with_pos("bar", Position{line: 1, column: 5}), fields: vec![(Token::new("bar", Position{line: 1, column: 5}),
Expression::Simple(Value::Int(value_node!(1))))], Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9}))))],
pos: None, pos: Some(Position{line: 1, column: 0}),
}) })
) )
); );
@ -1097,7 +1112,7 @@ mod test {
Expression::Grouped( Expression::Grouped(
Box::new( Box::new(
Expression::Simple( Expression::Simple(
Value::Symbol(value_node!("foo".to_string())))))) Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 2}))))))
); );
assert_eq!(grouped_expression(LocatedSpan::new("(1 + 1)")), assert_eq!(grouped_expression(LocatedSpan::new("(1 + 1)")),
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
@ -1106,10 +1121,10 @@ mod test {
Expression::Binary( Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 2})),
right: Box::new(Expression::Simple( right: Box::new(Expression::Simple(
Value::Int(value_node!(1)))), Value::Int(value_node!(1, Position{line: 1, column: 6})))),
pos: None, pos: Some(Position { line: 1, column: 1 }),
} }
) )
) )
@ -1135,7 +1150,7 @@ mod test {
line: 1, line: 1,
}, },
Value::Tuple( Value::Tuple(
value_node!(vec![])))); value_node!(vec![], Position{line: 1, column: 0}))));
tuple_expr = "{ foo = 1 }"; tuple_expr = "{ foo = 1 }";
assert_eq!(tuple(LocatedSpan::new(tuple_expr)), assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
@ -1146,9 +1161,9 @@ mod test {
}, },
Value::Tuple( Value::Tuple(
value_node!(vec![ value_node!(vec![
(Token::new_with_pos("foo", Position{line:1, column: 3}), (Token::new("foo", Position{line:1, column: 3}),
Expression::Simple(Value::Int(value_node!(1)))) Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9}))))
])))); ], Position{line: 1, column: 0}))));
tuple_expr = "{ foo = 1, bar = \"1\" }"; tuple_expr = "{ foo = 1, bar = \"1\" }";
assert_eq!(tuple(LocatedSpan::new(tuple_expr)), assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
@ -1159,11 +1174,11 @@ mod test {
}, },
Value::Tuple( Value::Tuple(
value_node!(vec![ value_node!(vec![
(Token::new_with_pos("foo", Position{line: 1, column: 3}), (Token::new("foo", Position{line: 1, column: 3}),
Expression::Simple(Value::Int(value_node!(1)))), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9})))),
(Token::new_with_pos("bar", Position{line: 1, column: 12}), (Token::new("bar", Position{line: 1, column: 12}),
Expression::Simple(Value::String(value_node!("1".to_string())))) Expression::Simple(Value::String(value_node!("1".to_string(), Position{line: 1, column: 18}))))
])))); ], Position{line: 1, column: 0}))));
tuple_expr = "{ foo = 1, bar = {} }"; tuple_expr = "{ foo = 1, bar = {} }";
assert_eq!(tuple(LocatedSpan::new(tuple_expr)), assert_eq!(tuple(LocatedSpan::new(tuple_expr)),
IResult::Done(LocatedSpan { IResult::Done(LocatedSpan {
@ -1173,11 +1188,11 @@ mod test {
}, },
Value::Tuple( Value::Tuple(
value_node!(vec![ value_node!(vec![
(Token::new_with_pos("foo", Position{line: 1, column: 3}), (Token::new("foo", Position{line: 1, column: 3}),
Expression::Simple(Value::Int(value_node!(1)))), Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 9})))),
(Token::new_with_pos("bar", Position{line: 1, column: 12}), (Token::new("bar", Position{line: 1, column: 12}),
Expression::Simple(Value::Tuple(value_node!(Vec::new())))) Expression::Simple(Value::Tuple(value_node!(Vec::new(), Position{line: 1, column: 17}))))
])))); ], Position{line: 1, column: 0}))));
} }
#[test] #[test]
@ -1187,20 +1202,20 @@ mod test {
assert_eq!(field_value(LocatedSpan::new("foo = 1")), assert_eq!(field_value(LocatedSpan::new("foo = 1")),
IResult::Done(LocatedSpan { offset: 7, line: 1, fragment: "" }, IResult::Done(LocatedSpan { offset: 7, line: 1, fragment: "" },
(Token::new_with_pos("foo", Position{line: 1, column: 1}), (Token::new("foo", Position{line: 1, column: 1}),
Expression::Simple(Value::Int(value_node!(1))))) ); Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 7}))))) );
assert_eq!(field_value(LocatedSpan::new("foo = \"1\"")), assert_eq!(field_value(LocatedSpan::new("foo = \"1\"")),
IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" }, IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" },
(Token::new_with_pos("foo", Position{line: 1, column: 1}), (Token::new("foo", Position{line: 1, column: 1}),
Expression::Simple(Value::String(value_node!("1".to_string()))))) ); Expression::Simple(Value::String(value_node!("1".to_string(), Position{line: 1, column: 7}))))) );
assert_eq!(field_value(LocatedSpan::new("foo = bar")), assert_eq!(field_value(LocatedSpan::new("foo = bar")),
IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" }, IResult::Done(LocatedSpan { offset: 9, line: 1, fragment: "" },
(Token::new_with_pos("foo", Position{line: 1, column: 1}), (Token::new("foo", Position{line: 1, column: 1}),
Expression::Simple(Value::Symbol(value_node!("bar".to_string()))))) ); Expression::Simple(Value::Symbol(value_node!("bar".to_string(), Position{line: 1, column: 7}))))) );
assert_eq!(field_value(LocatedSpan::new("foo = bar ")), assert_eq!(field_value(LocatedSpan::new("foo = bar ")),
IResult::Done(LocatedSpan { offset: 10, line: 1, fragment: "" }, IResult::Done(LocatedSpan { offset: 10, line: 1, fragment: "" },
(Token::new_with_pos("foo", Position{line: 1, column: 1}), (Token::new("foo", Position{line: 1, column: 1}),
Expression::Simple(Value::Symbol(value_node!("bar".to_string()))))) ); Expression::Simple(Value::Symbol(value_node!("bar".to_string(), Position{line: 1, column: 7}))))) );
} }
#[test] #[test]
@ -1209,29 +1224,29 @@ mod test {
assert!(number(LocatedSpan::new(". ")).is_err() ); assert!(number(LocatedSpan::new(". ")).is_err() );
assert_eq!(number(LocatedSpan::new("1.0")), assert_eq!(number(LocatedSpan::new("1.0")),
IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1},
Value::Float(value_node!(1.0))) ); Value::Float(value_node!(1.0, Position{line: 1, column: 1}))) );
assert_eq!(number(LocatedSpan::new("1.")), assert_eq!(number(LocatedSpan::new("1.")),
IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1},
Value::Float(value_node!(1.0))) ); Value::Float(value_node!(1.0, Position{line: 1, column: 1}))) );
assert_eq!(number(LocatedSpan::new("1")), assert_eq!(number(LocatedSpan::new("1")),
IResult::Done(LocatedSpan{fragment: "", offset: 1, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 1, line: 1},
Value::Int(value_node!(1))) ); Value::Int(value_node!(1, Position{line: 1, column: 1}))) );
assert_eq!(number(LocatedSpan::new(".1")), assert_eq!(number(LocatedSpan::new(".1")),
IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 2, line: 1},
Value::Float(value_node!(0.1))) ); Value::Float(value_node!(0.1, Position{line: 1, column: 1}))) );
} }
#[test] #[test]
fn test_symbol_parsing() { fn test_symbol_parsing() {
assert_eq!(symbol(LocatedSpan::new("foo")), assert_eq!(symbol(LocatedSpan::new("foo")),
IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 3, line: 1},
Value::Symbol(value_node!("foo".to_string()))) ); Value::Symbol(value_node!("foo".to_string(), Position{line: 1, column: 1}))) );
assert_eq!(symbol(LocatedSpan::new("foo-bar")), assert_eq!(symbol(LocatedSpan::new("foo-bar")),
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
Value::Symbol(value_node!("foo-bar".to_string()))) ); Value::Symbol(value_node!("foo-bar".to_string(), Position{line: 1, column: 1}))) );
assert_eq!(symbol(LocatedSpan::new("foo_bar")), assert_eq!(symbol(LocatedSpan::new("foo_bar")),
IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1}, IResult::Done(LocatedSpan{fragment: "", offset: 7, line: 1},
Value::Symbol(value_node!("foo_bar".to_string()))) ); Value::Symbol(value_node!("foo_bar".to_string(), Position{line: 1, column: 1}))) );
} }
#[test] #[test]
@ -1267,15 +1282,15 @@ mod test {
column: 27, column: 27,
} }
}, },
value: Expression::Simple(Value::Int(value_node!(1))) value: Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 33})))
}, },
Statement::Expression( Statement::Expression(
Expression::Binary( Expression::Binary(
BinaryOpDef{ BinaryOpDef{
kind: BinaryExprType::Add, kind: BinaryExprType::Add,
left: Value::Int(value_node!(1)), left: Value::Int(value_node!(1, Position{line: 1, column: 35})),
right: Box::new(Expression::Simple(Value::Int(value_node!(1)))), right: Box::new(Expression::Simple(Value::Int(value_node!(1, Position{line: 1, column: 37})))),
pos: None, pos: Some(Position { line: 1, column: 34 }),
}) })
) )
]); ]);