mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
parent
2068063a5b
commit
a74d44c171
@ -42,13 +42,14 @@ fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
||||
for r in expect.iter() {
|
||||
if !b.assert_collector.success {
|
||||
if let None = r.find(&b.assert_collector.failures) {
|
||||
panic!(
|
||||
assert!(
|
||||
false,
|
||||
"[{}] was not found in Assertion Failures:\n{}",
|
||||
r, b.assert_collector.failures
|
||||
);
|
||||
}
|
||||
} else {
|
||||
panic!("Building input Did not panic!");
|
||||
assert!(false, "Building input Did not panic!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -57,7 +58,11 @@ fn assert_build_failure(input: &str, expect: Vec<Regex>) {
|
||||
let stack_trace = format!("{}", err);
|
||||
// Look for each expect to match the string.
|
||||
if let None = r.find(&stack_trace) {
|
||||
panic!("[{}] was not found in stacktrace:\n{}", r, stack_trace);
|
||||
assert!(
|
||||
false,
|
||||
"[{}] was not found in stacktrace:\n{}",
|
||||
r, stack_trace
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -224,3 +229,49 @@ fn test_assert_partial_tuple_bad_desc_compile_failures() {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_missing_path_compile_failure() {
|
||||
assert_build_failure(
|
||||
"import ;",
|
||||
vec![
|
||||
Regex::new(r"Expected import path: at <eval> line: 1, column: 8").unwrap(),
|
||||
Regex::new(r"Not a String: at <eval> line: 1, column: 8").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_path_not_a_string_compile_failure() {
|
||||
assert_build_failure(
|
||||
"import 1;",
|
||||
vec![
|
||||
Regex::new(r"Expected import path: at <eval> line: 1, column: 8").unwrap(),
|
||||
Regex::new(r"Not a String: at <eval> line: 1, column: 8").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_operator_missing_operand_compile_failure() {
|
||||
assert_build_failure(
|
||||
"1 +",
|
||||
vec![
|
||||
Regex::new(r"Abort while parsing operator expression: at <eval> line: 1, column: 1")
|
||||
.unwrap(),
|
||||
Regex::new(r"Missing operand for binary expression: at <eval> line: 1, column: 4")
|
||||
.unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_operator_wrong_type_on_rhs_compile_failure() {
|
||||
assert_build_failure(
|
||||
"1 + \"foo\";",
|
||||
vec![
|
||||
Regex::new(r"Expected Integer but got .foo.").unwrap(),
|
||||
Regex::new(r"at <eval> line: 1, column: 5").unwrap(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
@ -507,16 +507,17 @@ impl<'a> FileBuilder<'a> {
|
||||
|
||||
fn add_vals(
|
||||
&self,
|
||||
pos: &Position,
|
||||
lpos: &Position,
|
||||
rpos: &Position,
|
||||
left: Rc<Val>,
|
||||
right: Rc<Val>,
|
||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
match *left {
|
||||
Val::Int(i) => {
|
||||
eval_binary_expr!(&Val::Int(ii), pos, right, Val::Int(i + ii), "Integer")
|
||||
eval_binary_expr!(&Val::Int(ii), rpos, right, Val::Int(i + ii), "Integer")
|
||||
}
|
||||
Val::Float(f) => {
|
||||
eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f + ff), "Float")
|
||||
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f + ff), "Float")
|
||||
}
|
||||
Val::Str(ref s) => match right.as_ref() {
|
||||
&Val::Str(ref ss) => {
|
||||
@ -532,7 +533,7 @@ impl<'a> FileBuilder<'a> {
|
||||
val
|
||||
),
|
||||
error::ErrorType::TypeFail,
|
||||
pos.clone(),
|
||||
rpos.clone(),
|
||||
)));
|
||||
}
|
||||
},
|
||||
@ -553,7 +554,7 @@ impl<'a> FileBuilder<'a> {
|
||||
val
|
||||
),
|
||||
error::ErrorType::TypeFail,
|
||||
pos.clone(),
|
||||
rpos.clone(),
|
||||
)));
|
||||
}
|
||||
},
|
||||
@ -561,7 +562,7 @@ impl<'a> FileBuilder<'a> {
|
||||
return Err(Box::new(error::BuildError::new(
|
||||
format!("{} does not support the '+' operation", expr.type_name()),
|
||||
error::ErrorType::Unsupported,
|
||||
pos.clone(),
|
||||
lpos.clone(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@ -569,22 +570,23 @@ impl<'a> FileBuilder<'a> {
|
||||
|
||||
fn subtract_vals(
|
||||
&self,
|
||||
pos: &Position,
|
||||
lpos: &Position,
|
||||
rpos: &Position,
|
||||
left: Rc<Val>,
|
||||
right: Rc<Val>,
|
||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
match *left {
|
||||
Val::Int(i) => {
|
||||
eval_binary_expr!(&Val::Int(ii), pos, right, Val::Int(i - ii), "Integer")
|
||||
eval_binary_expr!(&Val::Int(ii), rpos, right, Val::Int(i - ii), "Integer")
|
||||
}
|
||||
Val::Float(f) => {
|
||||
eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f - ff), "Float")
|
||||
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f - ff), "Float")
|
||||
}
|
||||
ref expr => {
|
||||
return Err(Box::new(error::BuildError::new(
|
||||
format!("{} does not support the '-' operation", expr.type_name()),
|
||||
error::ErrorType::Unsupported,
|
||||
pos.clone(),
|
||||
lpos.clone(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@ -592,22 +594,23 @@ impl<'a> FileBuilder<'a> {
|
||||
|
||||
fn multiply_vals(
|
||||
&self,
|
||||
pos: &Position,
|
||||
lpos: &Position,
|
||||
rpos: &Position,
|
||||
left: Rc<Val>,
|
||||
right: Rc<Val>,
|
||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
match *left {
|
||||
Val::Int(i) => {
|
||||
eval_binary_expr!(&Val::Int(ii), pos, right, Val::Int(i * ii), "Integer")
|
||||
eval_binary_expr!(&Val::Int(ii), rpos, right, Val::Int(i * ii), "Integer")
|
||||
}
|
||||
Val::Float(f) => {
|
||||
eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f * ff), "Float")
|
||||
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f * ff), "Float")
|
||||
}
|
||||
ref expr => {
|
||||
return Err(Box::new(error::BuildError::new(
|
||||
format!("{} does not support the '*' operation", expr.type_name()),
|
||||
error::ErrorType::Unsupported,
|
||||
pos.clone(),
|
||||
lpos.clone(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@ -615,22 +618,23 @@ impl<'a> FileBuilder<'a> {
|
||||
|
||||
fn divide_vals(
|
||||
&self,
|
||||
pos: &Position,
|
||||
lpos: &Position,
|
||||
rpos: &Position,
|
||||
left: Rc<Val>,
|
||||
right: Rc<Val>,
|
||||
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||
match *left {
|
||||
Val::Int(i) => {
|
||||
eval_binary_expr!(&Val::Int(ii), pos, right, Val::Int(i / ii), "Integer")
|
||||
eval_binary_expr!(&Val::Int(ii), rpos, right, Val::Int(i / ii), "Integer")
|
||||
}
|
||||
Val::Float(f) => {
|
||||
eval_binary_expr!(&Val::Float(ff), pos, right, Val::Float(f / ff), "Float")
|
||||
eval_binary_expr!(&Val::Float(ff), rpos, right, Val::Float(f / ff), "Float")
|
||||
}
|
||||
ref expr => {
|
||||
return Err(Box::new(error::BuildError::new(
|
||||
format!("{} does not support the '*' operation", expr.type_name()),
|
||||
error::ErrorType::Unsupported,
|
||||
pos.clone(),
|
||||
lpos.clone(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
@ -976,10 +980,10 @@ impl<'a> FileBuilder<'a> {
|
||||
};
|
||||
match kind {
|
||||
// Handle math and concatenation operators here
|
||||
&BinaryExprType::Add => self.add_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Sub => self.subtract_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Mul => self.multiply_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Div => self.divide_vals(&def.pos, left, right),
|
||||
&BinaryExprType::Add => self.add_vals(&def.pos, def.right.pos(), left, right),
|
||||
&BinaryExprType::Sub => self.subtract_vals(&def.pos, def.right.pos(), left, right),
|
||||
&BinaryExprType::Mul => self.multiply_vals(&def.pos, def.right.pos(), left, right),
|
||||
&BinaryExprType::Div => self.divide_vals(&def.pos, def.right.pos(), left, right),
|
||||
// Handle Comparison operators here
|
||||
&BinaryExprType::Equal => self.do_deep_equal(&def.pos, left, right),
|
||||
&BinaryExprType::GT => self.do_gt(&def.pos, left, right),
|
||||
|
@ -254,7 +254,12 @@ fn parse_operand_list<'a>(i: SliceIter<'a, Token>) -> ParseResult<'a, Vec<Elemen
|
||||
// if we have successfully parsed an element and an operator then
|
||||
// failing to parse a second expression is an abort since we know
|
||||
// for sure now that the next expression is supposed to be there.
|
||||
return Result::Abort(e);
|
||||
let err = Error::caused_by(
|
||||
"Missing operand for binary expression",
|
||||
Box::new(e),
|
||||
Box::new(_i.clone()),
|
||||
);
|
||||
return Result::Abort(err);
|
||||
}
|
||||
return Result::Fail(e);
|
||||
}
|
||||
@ -388,7 +393,6 @@ pub fn parse_precedence(i: SliceIter<Element>) -> Result<SliceIter<Element>, Exp
|
||||
|
||||
/// Parse a binary operator expression.
|
||||
pub fn op_expression<'a>(i: SliceIter<'a, Token>) -> Result<SliceIter<Token>, Expression> {
|
||||
// TODO(jwall): We need to implement the full on precedence climbing method here.
|
||||
let preparse = parse_operand_list(i.clone());
|
||||
match preparse {
|
||||
Result::Fail(e) => {
|
||||
@ -401,11 +405,11 @@ pub fn op_expression<'a>(i: SliceIter<'a, Token>) -> Result<SliceIter<Token>, Ex
|
||||
}
|
||||
Result::Abort(e) => {
|
||||
let err = Error::caused_by(
|
||||
"Failed while parsing operator expression",
|
||||
"Abort while parsing operator expression",
|
||||
Box::new(e),
|
||||
Box::new(i),
|
||||
);
|
||||
Result::Fail(err)
|
||||
Result::Abort(err)
|
||||
}
|
||||
Result::Incomplete(i) => Result::Incomplete(i),
|
||||
Result::Complete(rest, oplist) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user