Implement return statements

This commit is contained in:
Jeff 2023-12-31 14:04:10 -05:00
parent 3ae7456758
commit a3a2df552d
10 changed files with 11987 additions and 11984 deletions

View File

@ -37,8 +37,9 @@ impl AbstractTree for Block {
for index in 1..node.child_count() - 1 { for index in 1..node.child_count() - 1 {
let child_node = node.child(index).unwrap(); let child_node = node.child(index).unwrap();
if child_node.is_named() { if child_node.kind() == "statement" {
let statement = Statement::from_syntax_node(source, child_node, context)?; let statement = Statement::from_syntax_node(source, child_node, context)?;
statements.push(statement); statements.push(statement);
} }
} }
@ -59,13 +60,25 @@ impl AbstractTree for Block {
.enumerate() .enumerate()
.find_map_first(|(index, statement)| { .find_map_first(|(index, statement)| {
let result = statement.run(source, context); let result = statement.run(source, context);
let is_last_statement = index == statements.len() - 1;
let is_return_statement = if let Statement::Return(_) = statement {
true
} else {
false
};
if result.is_err() { if is_return_statement || result.is_err() {
Some(result) Some(result)
} else if index == statements.len() - 1 { } else if is_last_statement {
let _ = final_result.write().unwrap().as_mut().map(|_| result); let get_write_lock = final_result.write();
None match get_write_lock {
Ok(mut final_result) => {
*final_result = result;
None
}
Err(error) => Some(Err(error.into())),
}
} else { } else {
None None
} }
@ -75,6 +88,10 @@ impl AbstractTree for Block {
let mut prev_result = None; let mut prev_result = None;
for statement in &self.statements { for statement in &self.statements {
if let Statement::Return(inner_statement) = statement {
return inner_statement.run(source, context);
}
prev_result = Some(statement.run(source, context)); prev_result = Some(statement.run(source, context));
} }

View File

View File

@ -15,6 +15,7 @@ pub enum Statement {
Match(Match), Match(Match),
While(Box<While>), While(Box<While>),
Block(Box<Block>), Block(Box<Block>),
Return(Box<Statement>),
For(Box<For>), For(Box<For>),
IndexAssignment(Box<IndexAssignment>), IndexAssignment(Box<IndexAssignment>),
} }
@ -50,9 +51,14 @@ impl AbstractTree for Statement {
"match" => Ok(Statement::Match(Match::from_syntax_node( "match" => Ok(Statement::Match(Match::from_syntax_node(
source, child, context, source, child, context,
)?)), )?)),
"return" => {
let statement_node = child.child(1).unwrap();
Ok(Statement::Return(Box::new(Statement::from_syntax_node(source, statement_node, context)?)))
},
_ => Err(Error::UnexpectedSyntaxNode { _ => Err(Error::UnexpectedSyntaxNode {
expected: expected:
"assignment, expression, block, return, if...else, while, for, index_assignment or match".to_string(), "assignment, index assignment, expression, block, return, if...else, while, for or match".to_string(),
actual: child.kind().to_string(), actual: child.kind().to_string(),
location: child.start_position(), location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(), relevant_source: source[child.byte_range()].to_string(),
@ -70,6 +76,7 @@ impl AbstractTree for Statement {
Statement::Block(block) => block.run(source, context), Statement::Block(block) => block.run(source, context),
Statement::For(r#for) => r#for.run(source, context), Statement::For(r#for) => r#for.run(source, context),
Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context), Statement::IndexAssignment(index_assignment) => index_assignment.run(source, context),
Statement::Return(statement) => statement.run(source, context),
} }
} }
@ -83,6 +90,7 @@ impl AbstractTree for Statement {
Statement::Block(block) => block.expected_type(context), Statement::Block(block) => block.expected_type(context),
Statement::For(r#for) => r#for.expected_type(context), Statement::For(r#for) => r#for.expected_type(context),
Statement::IndexAssignment(index_assignment) => index_assignment.expected_type(context), Statement::IndexAssignment(index_assignment) => index_assignment.expected_type(context),
Statement::Return(statement) => statement.expected_type(context),
} }
} }
} }

View File

@ -442,3 +442,38 @@ mod type_definition {
})); }));
} }
} }
mod blocks {
use dust_lang::*;
#[test]
fn simple() {
assert_eq!(interpret("{ 1 }"), Ok(Value::Integer(1)));
}
#[test]
fn nested() {
assert_eq!(interpret("{ 1 { 1 + 1 } }"), Ok(Value::Integer(2)));
}
#[test]
fn with_return() {
assert_eq!(interpret("{ return 1; 1 + 1; }"), Ok(Value::Integer(1)));
}
#[test]
fn async_with_return() {
assert_eq!(
interpret(
"
async {
return 1
1 + 1
3
}
"
),
Ok(Value::Integer(1))
);
}
}

View File

@ -0,0 +1,52 @@
================================================================================
Simple Block
================================================================================
{
output(123)
}
--------------------------------------------------------------------------------
(root
(statement
(block
(statement
(expression
(function_call
(function_expression
(identifier
(built_in_function)))
(expression
(value
(integer)))))))))
================================================================================
Block with Return
================================================================================
{
1
return 4
5
}
--------------------------------------------------------------------------------
(root
(statement
(block
(statement
(expression
(value
(integer))))
(statement
(return
(statement
(expression
(value
(integer))))))
(statement
(expression
(value
(integer)))))))

View File

@ -2,7 +2,7 @@
Anonymous Function Anonymous Function
================================================================================ ================================================================================
() -> <str> { "Hiya" } () <str> { "Hiya" }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -323,7 +323,7 @@ module.exports = grammar({
return: $ => return: $ =>
prec.right( prec.right(
seq('return', $.expression), seq('return', $.statement),
), ),
type_definition: $ => type_definition: $ =>

View File

@ -1022,7 +1022,7 @@
}, },
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "expression" "name": "statement"
} }
] ]
} }

View File

@ -449,7 +449,7 @@
"required": true, "required": true,
"types": [ "types": [
{ {
"type": "expression", "type": "statement",
"named": true "named": true
} }
] ]

File diff suppressed because it is too large Load Diff