Implement return statements
This commit is contained in:
parent
3ae7456758
commit
a3a2df552d
@ -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();
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
0
src/abstract_tree/return.rs
Normal file
0
src/abstract_tree/return.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
52
tree-sitter-dust/corpus/blocks.txt
Normal file
52
tree-sitter-dust/corpus/blocks.txt
Normal 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)))))))
|
@ -2,7 +2,7 @@
|
||||
Anonymous Function
|
||||
================================================================================
|
||||
|
||||
() -> <str> { "Hiya" }
|
||||
() <str> { "Hiya" }
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -323,7 +323,7 @@ module.exports = grammar({
|
||||
|
||||
return: $ =>
|
||||
prec.right(
|
||||
seq('return', $.expression),
|
||||
seq('return', $.statement),
|
||||
),
|
||||
|
||||
type_definition: $ =>
|
||||
|
@ -1022,7 +1022,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "expression"
|
||||
"name": "statement"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -449,7 +449,7 @@
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "expression",
|
||||
"type": "statement",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user