Fix tests and parser

This commit is contained in:
Jeff 2024-03-17 10:19:22 -04:00
parent 062a3b606c
commit 199e1c9184
4 changed files with 31 additions and 41 deletions

View File

@ -14,6 +14,10 @@ impl Block {
pub fn new(statements: Vec<WithPosition<Statement>>) -> Self { pub fn new(statements: Vec<WithPosition<Statement>>) -> Self {
Self { statements } Self { statements }
} }
pub fn last_statement(&self) -> &WithPosition<Statement> {
self.statements.last().unwrap()
}
} }
impl AbstractTree for Block { impl AbstractTree for Block {

View File

@ -8,15 +8,15 @@ use super::{AbstractTree, Action, Block, Expression, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub struct IfElse { pub struct IfElse {
if_expression: WithPosition<Expression>, if_expression: WithPosition<Expression>,
if_block: WithPosition<Block>, if_block: Block,
else_block: Option<WithPosition<Block>>, else_block: Option<Block>,
} }
impl IfElse { impl IfElse {
pub fn new( pub fn new(
if_expression: WithPosition<Expression>, if_expression: WithPosition<Expression>,
if_block: WithPosition<Block>, if_block: Block,
else_block: Option<WithPosition<Block>>, else_block: Option<Block>,
) -> Self { ) -> Self {
Self { Self {
if_expression, if_expression,
@ -28,20 +28,20 @@ impl IfElse {
impl AbstractTree for IfElse { impl AbstractTree for IfElse {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
self.if_block.node.expected_type(_context) self.if_block.expected_type(_context)
} }
fn validate(&self, context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context) -> Result<(), ValidationError> {
if let Type::Boolean = self.if_expression.node.expected_type(context)? { if let Type::Boolean = self.if_expression.node.expected_type(context)? {
if let Some(else_block) = &self.else_block { if let Some(else_block) = &self.else_block {
let expected = self.if_block.node.expected_type(context)?; let expected = self.if_block.expected_type(context)?;
let actual = else_block.node.expected_type(context)?; let actual = else_block.expected_type(context)?;
expected expected
.check(&actual) .check(&actual)
.map_err(|conflict| ValidationError::TypeCheck { .map_err(|conflict| ValidationError::TypeCheck {
conflict, conflict,
actual_position: self.if_block.position, actual_position: self.if_block.last_statement().position,
expected_position: self.if_expression.position, expected_position: self.if_expression.position,
})?; })?;
} }
@ -61,9 +61,9 @@ impl AbstractTree for IfElse {
.as_boolean()?; .as_boolean()?;
if if_boolean { if if_boolean {
self.if_block.node.run(_context) self.if_block.run(_context)
} else if let Some(else_statement) = self.else_block { } else if let Some(else_statement) = self.else_block {
else_statement.node.run(_context) else_statement.run(_context)
} else { } else {
Ok(Action::None) Ok(Action::None)
} }
@ -87,8 +87,7 @@ mod tests {
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string()) ValueNode::String("foo".to_string())
)) ))
.with_position((0, 0))]) .with_position((0, 0))]),
.with_position((0, 0)),
None None
) )
.run(&Context::new()), .run(&Context::new()),
@ -104,15 +103,11 @@ mod tests {
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string()) ValueNode::String("foo".to_string())
)) ))
.with_position((0, 0))]) .with_position((0, 0))]),
.with_position((0, 0)), Some(Block::new(vec![Statement::Expression(Expression::Value(
Some(
Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("bar".to_string()) ValueNode::String("bar".to_string())
)) ))
.with_position((0, 0))]) .with_position((0, 0))]))
.with_position((0, 0))
)
) )
.run(&Context::new()), .run(&Context::new()),
Ok(Action::Return(Value::string("bar".to_string()))) Ok(Action::Return(Value::string("bar".to_string())))

View File

@ -121,10 +121,6 @@ pub fn parser<'src>() -> DustParser<'src> {
) )
.map(|statements| Block::new(statements)); .map(|statements| Block::new(statements));
let positioned_block = block
.clone()
.map_with(|block, state| block.with_position(state.span()));
let positioned_expression = recursive(|positioned_expression| { let positioned_expression = recursive(|positioned_expression| {
let identifier_expression = identifier.clone().map_with(|identifier, state| { let identifier_expression = identifier.clone().map_with(|identifier, state| {
Expression::Identifier(identifier).with_position(state.span()) Expression::Identifier(identifier).with_position(state.span())
@ -336,10 +332,10 @@ pub fn parser<'src>() -> DustParser<'src> {
)); ));
choice(( choice((
function,
function_call,
range, range,
logic_math_and_index, logic_math_and_index,
function,
function_call,
identifier_expression, identifier_expression,
list, list,
map, map,
@ -397,10 +393,10 @@ pub fn parser<'src>() -> DustParser<'src> {
let if_else = just(Token::Keyword("if")) let if_else = just(Token::Keyword("if"))
.ignore_then(positioned_expression.clone()) .ignore_then(positioned_expression.clone())
.then(positioned_block.clone()) .then(block.clone())
.then( .then(
just(Token::Keyword("else")) just(Token::Keyword("else"))
.ignore_then(positioned_block.clone()) .ignore_then(block.clone())
.or_not(), .or_not(),
) )
.map_with(|((if_expression, if_block), else_block), state| { .map_with(|((if_expression, if_block), else_block), state| {
@ -574,8 +570,7 @@ mod tests {
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string()) ValueNode::String("foo".to_string())
),) ),)
.with_position((10, 15))]) .with_position((10, 15))]),
.with_position((8, 17)),
None None
),) ),)
); );
@ -590,15 +585,11 @@ mod tests {
Block::new(vec![Statement::Expression(Expression::Value( Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("foo".to_string()) ValueNode::String("foo".to_string())
),) ),)
.with_position((9, 14))]) .with_position((9, 14))]),
.with_position((8, 17)), Some(Block::new(vec![Statement::Expression(Expression::Value(
Some(
Block::new(vec![Statement::Expression(Expression::Value(
ValueNode::String("bar".to_string()) ValueNode::String("bar".to_string())
),) ),)
.with_position((24, 29))]) .with_position((24, 29))]))
.with_position((22, 31))
)
),) ),)
) )
} }

View File

@ -62,7 +62,7 @@ fn function_context_does_not_capture_values() {
), ),
Err(vec![Error::Validation { Err(vec![Error::Validation {
error: ValidationError::VariableNotFound(Identifier::new("x")), error: ValidationError::VariableNotFound(Identifier::new("x")),
position: (0, 0).into() position: (32, 66).into()
}]) }])
); );