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 {
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)?;
statements.push(statement);
}
}
@ -59,13 +60,25 @@ impl AbstractTree for Block {
.enumerate()
.find_map_first(|(index, statement)| {
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)
} else if index == statements.len() - 1 {
let _ = final_result.write().unwrap().as_mut().map(|_| result);
} else if is_last_statement {
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 {
None
}
@ -75,6 +88,10 @@ impl AbstractTree for Block {
let mut prev_result = None;
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));
}

View File

View File

@ -15,6 +15,7 @@ pub enum Statement {
Match(Match),
While(Box<While>),
Block(Box<Block>),
Return(Box<Statement>),
For(Box<For>),
IndexAssignment(Box<IndexAssignment>),
}
@ -50,9 +51,14 @@ impl AbstractTree for Statement {
"match" => Ok(Statement::Match(Match::from_syntax_node(
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 {
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(),
location: child.start_position(),
relevant_source: source[child.byte_range()].to_string(),
@ -70,6 +76,7 @@ impl AbstractTree for Statement {
Statement::Block(block) => block.run(source, context),
Statement::For(r#for) => r#for.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::For(r#for) => r#for.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
================================================================================
() -> <str> { "Hiya" }
() <str> { "Hiya" }
--------------------------------------------------------------------------------

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff