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,
|
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.
|
/// Encodes a ucg expression. Expressions compute a value from.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
@ -617,6 +623,9 @@ pub enum Expression {
|
|||||||
Select(SelectDef),
|
Select(SelectDef),
|
||||||
FuncOp(FuncOpDef),
|
FuncOp(FuncOpDef),
|
||||||
Module(ModuleDef),
|
Module(ModuleDef),
|
||||||
|
|
||||||
|
// Declarative failure expressions
|
||||||
|
Fail(FailDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
@ -636,6 +645,7 @@ impl Expression {
|
|||||||
&Expression::FuncOp(ref def) => def.pos(),
|
&Expression::FuncOp(ref def) => def.pos(),
|
||||||
&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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -682,6 +692,9 @@ impl fmt::Display for Expression {
|
|||||||
&Expression::Import(_) => {
|
&Expression::Import(_) => {
|
||||||
write!(w, "<Include>")?;
|
write!(w, "<Include>")?;
|
||||||
}
|
}
|
||||||
|
&Expression::Fail(_) => {
|
||||||
|
write!(w, "<Fail>")?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ impl<'a> AstWalker<'a> {
|
|||||||
Expression::Simple(ref mut val) => {
|
Expression::Simple(ref mut val) => {
|
||||||
self.visit_value(val);
|
self.visit_value(val);
|
||||||
}
|
}
|
||||||
Expression::Import(_) | Expression::Include(_) => {
|
Expression::Import(_) | Expression::Include(_) | Expression::Fail(_) => {
|
||||||
//noop
|
//noop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,3 +101,21 @@ fn test_format() {
|
|||||||
fn test_type_checks() {
|
fn test_type_checks() {
|
||||||
assert_build(include_str!("../../integration_tests/types_test.ucg"));
|
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::FuncOp(ref def) => self.eval_func_op(def, scope),
|
||||||
&Expression::Include(ref def) => self.eval_include(def),
|
&Expression::Include(ref def) => self.eval_include(def),
|
||||||
&Expression::Import(ref def) => self.eval_import(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
|
// Parsing Errors
|
||||||
ParseError,
|
ParseError,
|
||||||
AssertError,
|
AssertError,
|
||||||
|
// User Defined Declarative Errors
|
||||||
|
UserDefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for ErrorType {
|
impl fmt::Display for ErrorType {
|
||||||
@ -49,6 +51,7 @@ impl fmt::Display for ErrorType {
|
|||||||
&ErrorType::ReservedWordError => "ReservedWordError",
|
&ErrorType::ReservedWordError => "ReservedWordError",
|
||||||
&ErrorType::ParseError => "ParseError",
|
&ErrorType::ParseError => "ParseError",
|
||||||
&ErrorType::AssertError => "AssertError",
|
&ErrorType::AssertError => "AssertError",
|
||||||
|
&ErrorType::UserDefined => "UserDefined",
|
||||||
};
|
};
|
||||||
w.write_str(name)
|
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> {
|
fn unprefixed_expression(input: SliceIter<Token>) -> ParseResult<Expression> {
|
||||||
let _input = input.clone();
|
let _input = input.clone();
|
||||||
either!(
|
either!(
|
||||||
@ -668,6 +689,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!(fail_expression),
|
||||||
trace_parse!(module_expression),
|
trace_parse!(module_expression),
|
||||||
trace_parse!(select_expression),
|
trace_parse!(select_expression),
|
||||||
trace_parse!(grouped_expression),
|
trace_parse!(grouped_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!(failtok<OffsetStrIter, Token>,
|
||||||
|
do_text_token_tok!(TokenType::BAREWORD, "fail", WS)
|
||||||
|
);
|
||||||
|
|
||||||
make_fn!(macrotok<OffsetStrIter, Token>,
|
make_fn!(macrotok<OffsetStrIter, Token>,
|
||||||
do_text_token_tok!(TokenType::BAREWORD, "macro", WS)
|
do_text_token_tok!(TokenType::BAREWORD, "macro", WS)
|
||||||
);
|
);
|
||||||
@ -417,6 +421,7 @@ fn token<'a>(input: OffsetStrIter<'a>) -> Result<OffsetStrIter<'a>, Token> {
|
|||||||
outtok,
|
outtok,
|
||||||
selecttok,
|
selecttok,
|
||||||
asserttok,
|
asserttok,
|
||||||
|
failtok,
|
||||||
macrotok,
|
macrotok,
|
||||||
moduletok,
|
moduletok,
|
||||||
importtok,
|
importtok,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user