Skip to content

Commit

Permalink
Early return statements
Browse files Browse the repository at this point in the history
  • Loading branch information
sagebind committed Feb 3, 2024
1 parent ed17132 commit 8486a1c
Show file tree
Hide file tree
Showing 14 changed files with 208 additions and 113 deletions.
11 changes: 4 additions & 7 deletions runtime/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::{
prelude::*,
scope::Scope,
string::RipString,
table,
throw,
};
use riptide_syntax::source::SourceFile;
use std::convert::TryInto;
Expand All @@ -21,7 +23,6 @@ pub(crate) fn load_module() -> Result<Value, Exception> {
"load" => Value::ForeignFn(load.into()),
"nil" => Value::ForeignFn(nil.into()),
"nth" => Value::ForeignFn(nth.into()),
"pass" => Value::ForeignFn(pass.into()),
"throw" => Value::ForeignFn(throw.into()),
"try" => Value::ForeignFn(try_fn.into()),
"typeof" => Value::ForeignFn(type_of.into()),
Expand Down Expand Up @@ -61,7 +62,7 @@ async fn type_of(_: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {

/// Parse a string as code, returning it as an executable closure.
async fn load(fiber: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {
let script: RipString = match args.get(0).and_then(Value::as_string) {
let script: RipString = match args.first().and_then(Value::as_string) {
Some(s) => s.clone(),
None => throw!("first argument must be a string"),
};
Expand All @@ -73,7 +74,7 @@ async fn load(fiber: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {
}

async fn nth(_: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {
let list = match args.get(0).and_then(Value::as_list) {
let list = match args.first().and_then(Value::as_list) {
Some(s) => s.to_vec(),
None => throw!("first argument must be a list"),
};
Expand All @@ -91,10 +92,6 @@ async fn nil(_: &mut Fiber, _: Vec<Value>) -> Result<Value, Exception> {
Ok(Value::Nil)
}

async fn pass(_fiber: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {
Ok(args.first().cloned().unwrap_or(Value::Nil))
}

/// Throw an exception.
async fn throw(_: &mut Fiber, args: Vec<Value>) -> Result<Value, Exception> {
match args.first() {
Expand Down
29 changes: 29 additions & 0 deletions runtime/src/controlflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Helpers for navigating control flow within the interpreter.
//!
//! This is not exposed in the runtime API, as manipulating control flow is a
//! privileged operation.
use crate::{Exception, Value};

/// Control flow is handled in the interpreter entirely using return values.
pub(crate) type ControlFlow<T> = std::ops::ControlFlow<BreakAction, T>;

/// When performing an early exit of normal control flow, this is the action being
/// performed.
pub(crate) enum BreakAction {
/// Break out of the closest function boundary with the given return value.
/// This bubbles up through the stack until the nearest function invocation
/// is reached.
Return(Value),

/// Throw an exception. This is bubbled up through the stack until caught.
Throw(Exception),
}

macro_rules! throw_cf {
($($arg:tt)*) => {
return ::std::ops::ControlFlow::Break(BreakAction::Throw($crate::Exception::from(format!($($arg)*))))
};
}

pub(crate) use throw_cf;
Loading

0 comments on commit 8486a1c

Please sign in to comment.