mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
parent
eaa3e84179
commit
6d5d4c79de
@ -595,6 +595,12 @@ pub struct IsDef {
|
||||
pub typ: Token,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct FailDef {
|
||||
pub pos: Position,
|
||||
pub message: Box<Expression>,
|
||||
}
|
||||
|
||||
/// Encodes a ucg expression. Expressions compute a value from.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Expression {
|
||||
@ -617,6 +623,9 @@ pub enum Expression {
|
||||
Select(SelectDef),
|
||||
FuncOp(FuncOpDef),
|
||||
Module(ModuleDef),
|
||||
|
||||
// Declarative failure expressions
|
||||
Fail(FailDef),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
@ -636,6 +645,7 @@ impl Expression {
|
||||
&Expression::FuncOp(ref def) => def.pos(),
|
||||
&Expression::Include(ref def) => &def.pos,
|
||||
&Expression::Import(ref def) => &def.pos,
|
||||
&Expression::Fail(ref def) => &def.pos,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -682,6 +692,9 @@ impl fmt::Display for Expression {
|
||||
&Expression::Import(_) => {
|
||||
write!(w, "<Include>")?;
|
||||
}
|
||||
&Expression::Fail(_) => {
|
||||
write!(w, "<Fail>")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ impl<'a> AstWalker<'a> {
|
||||
Expression::Simple(ref mut val) => {
|
||||
self.visit_value(val);
|
||||
}
|
||||
Expression::Import(_) | Expression::Include(_) => {
|
||||
Expression::Import(_) | Expression::Include(_) | Expression::Fail(_) => {
|
||||
//noop
|
||||
}
|
||||
}
|
||||
|
@ -101,3 +101,21 @@ fn test_format() {
|
||||
fn test_type_checks() {
|
||||
assert_build(include_str!("../../integration_tests/types_test.ucg"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "UserDefined")]
|
||||
fn test_declarative_failures_are_user_defined() {
|
||||
assert_build("fail \"I am a failure!\";");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "Caused By:\n\tI am a failure!")]
|
||||
fn test_declarative_failures_are_caused_by_msg() {
|
||||
assert_build("fail \"I am a failure!\";");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "1 is a failure!")]
|
||||
fn test_declarative_failures_can_with_format_expr() {
|
||||
assert_build("fail \"@ is a failure!\" % (1);");
|
||||
}
|
||||
|
@ -1766,6 +1766,25 @@ impl<'a> FileBuilder<'a> {
|
||||
&Expression::FuncOp(ref def) => self.eval_func_op(def, scope),
|
||||
&Expression::Include(ref def) => self.eval_include(def),
|
||||
&Expression::Import(ref def) => self.eval_import(def),
|
||||
&Expression::Fail(ref def) => {
|
||||
let err = self.eval_expr(&def.message, scope)?;
|
||||
return if let Val::Str(ref s) = err.as_ref() {
|
||||
Err(Box::new(error::BuildError::new(
|
||||
s.clone(),
|
||||
error::ErrorType::UserDefined,
|
||||
def.pos.clone(),
|
||||
)))
|
||||
} else {
|
||||
Err(Box::new(error::BuildError::new(
|
||||
format!(
|
||||
"Expected string form message but got {}",
|
||||
def.message.as_ref()
|
||||
),
|
||||
error::ErrorType::TypeFail,
|
||||
def.message.pos().clone(),
|
||||
)))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ pub enum ErrorType {
|
||||
// Parsing Errors
|
||||
ParseError,
|
||||
AssertError,
|
||||
// User Defined Declarative Errors
|
||||
UserDefined,
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorType {
|
||||
@ -49,6 +51,7 @@ impl fmt::Display for ErrorType {
|
||||
&ErrorType::ReservedWordError => "ReservedWordError",
|
||||
&ErrorType::ParseError => "ParseError",
|
||||
&ErrorType::AssertError => "AssertError",
|
||||
&ErrorType::UserDefined => "UserDefined",
|
||||
};
|
||||
w.write_str(name)
|
||||
}
|
||||
|
@ -650,6 +650,27 @@ make_fn!(
|
||||
)
|
||||
);
|
||||
|
||||
make_fn!(
|
||||
string_expression<SliceIter<Token>, Expression>,
|
||||
do_each!(
|
||||
val => trace_parse!(quoted_value),
|
||||
(value_to_expression(val))
|
||||
)
|
||||
);
|
||||
|
||||
make_fn!(
|
||||
fail_expression<SliceIter<Token>, Expression>,
|
||||
do_each!(
|
||||
pos => pos,
|
||||
_ => word!("fail"),
|
||||
msg => must!(wrap_err!(either!(format_expression, string_expression), "Expected failure message")),
|
||||
(Expression::Fail(FailDef{
|
||||
pos: pos,
|
||||
message: Box::new(msg),
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
||||
fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
|
||||
let _input = input.clone();
|
||||
either!(
|
||||
@ -668,6 +689,7 @@ make_fn!(
|
||||
trace_parse!(func_op_expression),
|
||||
trace_parse!(macro_expression),
|
||||
trace_parse!(import_expression),
|
||||
trace_parse!(fail_expression),
|
||||
trace_parse!(module_expression),
|
||||
trace_parse!(select_expression),
|
||||
trace_parse!(grouped_expression),
|
||||
|
@ -278,6 +278,10 @@ make_fn!(istok<OffsetStrIter, Token>,
|
||||
do_text_token_tok!(TokenType::BAREWORD, "is", WS)
|
||||
);
|
||||
|
||||
make_fn!(failtok<OffsetStrIter, Token>,
|
||||
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
||||
);
|
||||
|
||||
make_fn!(macrotok<OffsetStrIter, Token>,
|
||||
do_text_token_tok!(TokenType::BAREWORD, "macro", WS)
|
||||
);
|
||||
@ -417,6 +421,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
||||
outtok,
|
||||
selecttok,
|
||||
asserttok,
|
||||
failtok,
|
||||
macrotok,
|
||||
moduletok,
|
||||
importtok,
|
||||
|
Loading…
x
Reference in New Issue
Block a user