aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-03-03 02:30:46 +0100
committerMel <einebeere@gmail.com>2022-03-03 02:30:46 +0100
commitf5bb7bbd8824a20c991587d5a774644aa98241d9 (patch)
treec8729e0e1a04f2c924b5351f57fb9b2ec18d4633 /src
parent8f7e3d1d2cd43d30ccc16799fcf69058ccc5a717 (diff)
downloadrabbithole-f5bb7bbd8824a20c991587d5a774644aa98241d9.tar.zst
rabbithole-f5bb7bbd8824a20c991587d5a774644aa98241d9.zip
Allow returns without valueHEADmain
Diffstat (limited to 'src')
-rw-r--r--src/interpret/operator.rs2
-rw-r--r--src/interpret/walker.rs10
-rw-r--r--src/parse/ast/statement.rs10
-rw-r--r--src/parse/parser.rs11
4 files changed, 23 insertions, 10 deletions
diff --git a/src/interpret/operator.rs b/src/interpret/operator.rs
index 057f942..9a68a7f 100644
--- a/src/interpret/operator.rs
+++ b/src/interpret/operator.rs
@@ -280,7 +280,7 @@ impl<'t> ValueOperator<'t> {
Err(WalkerError {
kind: WalkerErrorKind::Return(returned_value),
..
- }) => Ok(returned_value),
+ }) => Ok(returned_value.unwrap_or_else(|| Value::void(self.types))),
Err(x) => Err(CallError::InsideFunction(x)),
}
}
diff --git a/src/interpret/walker.rs b/src/interpret/walker.rs
index 7c86780..07e127d 100644
--- a/src/interpret/walker.rs
+++ b/src/interpret/walker.rs
@@ -62,12 +62,16 @@ impl Walker {
println!("{}", result);
None
}
- // FIXME: Returns are always expected to have a return even though `return;` is valid.
StatementKind::Return(node) => {
+ let returned = match node {
+ Some(e) => Some(self.walk_expression(e)?),
+ None => None,
+ };
+
// If there's a function running above us it will catch this error.
return Err(WalkerError::new(
statement.at,
- WalkerErrorKind::Return(self.walk_expression(node)?),
+ WalkerErrorKind::Return(returned),
));
}
StatementKind::Break(node) => {
@@ -381,5 +385,5 @@ pub enum WalkerErrorKind {
LoopBreak(Option<Value>),
// Same as with the loop control errors, but for functions.
#[error("Return statements are only valid inside functions.")]
- Return(Value),
+ Return(Option<Value>),
}
diff --git a/src/parse/ast/statement.rs b/src/parse/ast/statement.rs
index 7ed91dc..899190b 100644
--- a/src/parse/ast/statement.rs
+++ b/src/parse/ast/statement.rs
@@ -16,7 +16,7 @@ pub enum StatementKind {
Print(Expression),
Break(Option<Expression>),
Continue,
- Return(Expression),
+ Return(Option<Expression>),
}
impl Display for Statement {
@@ -39,8 +39,12 @@ impl Statement {
expression.nested_fmt(f, depth + 1)?;
}
StatementKind::Return(expression) => {
- writeln!(f, "{}Return:", pad)?;
- expression.nested_fmt(f, depth + 1)?;
+ if let Some(returned) = expression {
+ writeln!(f, "{}Return:", pad)?;
+ returned.nested_fmt(f, depth + 1)?;
+ } else {
+ writeln!(f, "{}Return", pad)?;
+ }
}
StatementKind::Break(expression) => {
if let Some(returned_on_break) = expression {
diff --git a/src/parse/parser.rs b/src/parse/parser.rs
index f19dcf1..a9baf7a 100644
--- a/src/parse/parser.rs
+++ b/src/parse/parser.rs
@@ -51,11 +51,16 @@ impl<T: Iterator<Item = Token>> Parser<T> {
fn return_statement(&mut self) -> Result<Statement, ParserError> {
let return_token = consume!(self, KeywordReturn)?;
- let expression = self.expression()?;
- consume!(self, SemiColon)?;
+ let returned = if consume_if!(self, SemiColon).is_none() {
+ let expression = self.expression()?;
+ consume!(self, SemiColon)?;
+ Some(expression)
+ } else {
+ None
+ };
Ok(Statement {
at: return_token.location,
- kind: StatementKind::Return(expression),
+ kind: StatementKind::Return(returned),
})
}