mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
FEATURE: Add the not operator.
This commit is contained in:
parent
2409f0c64e
commit
016e4a22db
@ -219,4 +219,19 @@ let name = "foo";
|
|||||||
assert {
|
assert {
|
||||||
ok = (name) in {foo="bar"},
|
ok = (name) in {foo="bar"},
|
||||||
desc = "(name) in {foo=\"bar\"} works",
|
desc = "(name) in {foo=\"bar\"} works",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert {
|
||||||
|
ok = not false,
|
||||||
|
desc = "not false is true",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert {
|
||||||
|
ok = not true == false,
|
||||||
|
desc = "not true is false",
|
||||||
|
};
|
||||||
|
|
||||||
|
assert {
|
||||||
|
ok = not not true,
|
||||||
|
desc = "double negatives are positive",
|
||||||
};
|
};
|
@ -601,11 +601,18 @@ pub struct FailDef {
|
|||||||
pub message: Box<Expression>,
|
pub message: Box<Expression>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct NotDef {
|
||||||
|
pub pos: Position,
|
||||||
|
pub expr: Box<Expression>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Encodes a ucg expression. Expressions compute a value from.
|
/// Encodes a ucg expression. Expressions compute a value from.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
// Base Expression
|
// Base Expression
|
||||||
Simple(Value),
|
Simple(Value),
|
||||||
|
Not(NotDef),
|
||||||
|
|
||||||
// Binary expressions
|
// Binary expressions
|
||||||
Binary(BinaryOpDef),
|
Binary(BinaryOpDef),
|
||||||
@ -646,6 +653,7 @@ impl Expression {
|
|||||||
&Expression::Include(ref def) => &def.pos,
|
&Expression::Include(ref def) => &def.pos,
|
||||||
&Expression::Import(ref def) => &def.pos,
|
&Expression::Import(ref def) => &def.pos,
|
||||||
&Expression::Fail(ref def) => &def.pos,
|
&Expression::Fail(ref def) => &def.pos,
|
||||||
|
&Expression::Not(ref def) => &def.pos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -695,6 +703,9 @@ impl fmt::Display for Expression {
|
|||||||
&Expression::Fail(_) => {
|
&Expression::Fail(_) => {
|
||||||
write!(w, "<Fail>")?;
|
write!(w, "<Fail>")?;
|
||||||
}
|
}
|
||||||
|
&Expression::Not(ref def) => {
|
||||||
|
write!(w, "!{}", def.expr)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,9 @@ impl<'a> AstWalker<'a> {
|
|||||||
Expression::Import(_) | Expression::Include(_) | Expression::Fail(_) => {
|
Expression::Import(_) | Expression::Include(_) | Expression::Fail(_) => {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
|
Expression::Not(ref mut def) => {
|
||||||
|
self.walk_expression(def.expr.as_mut());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1786,7 +1786,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
} else {
|
} else {
|
||||||
Err(Box::new(error::BuildError::new(
|
Err(Box::new(error::BuildError::new(
|
||||||
format!(
|
format!(
|
||||||
"Expected string form message but got {}",
|
"Expected string for message but got {}",
|
||||||
def.message.as_ref()
|
def.message.as_ref()
|
||||||
),
|
),
|
||||||
error::ErrorType::TypeFail,
|
error::ErrorType::TypeFail,
|
||||||
@ -1794,6 +1794,21 @@ impl<'a> FileBuilder<'a> {
|
|||||||
)))
|
)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
&Expression::Not(ref def) => {
|
||||||
|
let val = self.eval_expr(&def.expr, scope)?;
|
||||||
|
return if let Val::Boolean(b) = val.as_ref() {
|
||||||
|
Ok(Rc::new(Val::Boolean(!b)))
|
||||||
|
} else {
|
||||||
|
Err(Box::new(error::BuildError::new(
|
||||||
|
format!(
|
||||||
|
"Expected boolean for expression but got {}",
|
||||||
|
def.expr.as_ref()
|
||||||
|
),
|
||||||
|
error::ErrorType::TypeFail,
|
||||||
|
def.expr.pos().clone(),
|
||||||
|
)))
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,6 +667,19 @@ make_fn!(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
make_fn!(
|
||||||
|
not_expression<SliceIter<Token>, Expression>,
|
||||||
|
do_each!(
|
||||||
|
pos => pos,
|
||||||
|
_ => word!("not"),
|
||||||
|
expr => must!(wrap_err!(expression, "Expected failure message")),
|
||||||
|
(Expression::Not(NotDef{
|
||||||
|
pos: pos,
|
||||||
|
expr: Box::new(expr),
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
|
fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
|
||||||
let _input = input.clone();
|
let _input = input.clone();
|
||||||
either!(
|
either!(
|
||||||
@ -685,6 +698,7 @@ make_fn!(
|
|||||||
trace_parse!(func_op_expression),
|
trace_parse!(func_op_expression),
|
||||||
trace_parse!(macro_expression),
|
trace_parse!(macro_expression),
|
||||||
trace_parse!(import_expression),
|
trace_parse!(import_expression),
|
||||||
|
trace_parse!(not_expression),
|
||||||
trace_parse!(fail_expression),
|
trace_parse!(fail_expression),
|
||||||
trace_parse!(module_expression),
|
trace_parse!(module_expression),
|
||||||
trace_parse!(select_expression),
|
trace_parse!(select_expression),
|
||||||
|
@ -278,6 +278,10 @@ make_fn!(istok<OffsetStrIter, Token>,
|
|||||||
do_text_token_tok!(TokenType::BAREWORD, "is", WS)
|
do_text_token_tok!(TokenType::BAREWORD, "is", WS)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
make_fn!(nottok<OffsetStrIter, Token>,
|
||||||
|
do_text_token_tok!(TokenType::BAREWORD, "not", WS)
|
||||||
|
);
|
||||||
|
|
||||||
make_fn!(failtok<OffsetStrIter, Token>,
|
make_fn!(failtok<OffsetStrIter, Token>,
|
||||||
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
||||||
);
|
);
|
||||||
@ -417,6 +421,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
|||||||
booleantok,
|
booleantok,
|
||||||
intok,
|
intok,
|
||||||
istok,
|
istok,
|
||||||
|
nottok,
|
||||||
lettok,
|
lettok,
|
||||||
outtok,
|
outtok,
|
||||||
selecttok,
|
selecttok,
|
||||||
|
@ -30,7 +30,7 @@ let asserts = module{
|
|||||||
// descriptive message to use in output.
|
// descriptive message to use in output.
|
||||||
desc=mod.default_description,
|
desc=mod.default_description,
|
||||||
} => {
|
} => {
|
||||||
let ok = mod.test != true;
|
let ok = not mod.test;
|
||||||
|
|
||||||
let desc = "@" % (mod.desc);
|
let desc = "@" % (mod.desc);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user