Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions docs/language/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,37 @@ elif condition {
```

![](../assets/ifelif.png){width="200"}

## Ternary Expressions

Embed conditional logic directly inside expressions.

### Syntax

```goboscript
if (<condition>) <true_value> else <false_value>
```

### Examples

```goboscript
say if (score > 100) "winner" else "loser";
```

Ternaries can be nested — an `else` branch can itself be a ternary:

```goboscript
say if (condition_A) "A_true"
else if (condition_B) "B_true"
else "false";
```

When used as a condition, a ternary must be wrapped in parentheses:

```goboscript
say if (if (condition_A) true else false) "yes" else "no";
```

### Compilation

Ternaries are desugared at compile time into `if`/`else` branches. Each branch receives a copy of the surrounding statement with the ternary substituted for the appropriate value.
6 changes: 6 additions & 0 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ pub enum Expr {
property: SmolStr,
span: Span,
},
Ternary {
condition: Box<Expr>,
tvalue: Box<Expr>,
fvalue: Box<Expr>,
},
}

impl Expr {
Expand All @@ -79,6 +84,7 @@ impl Expr {
Self::BinOp { span, .. } => span.clone(),
Self::StructLiteral { span, .. } => span.clone(),
Self::Property { span, .. } => span.clone(),
Self::Ternary { condition, .. } => condition.span(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/codegen/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ pub fn build_impl<T: Write + Seek>(
block_count: 0,
});
}
visitor::ternary::visit_project(&mut project);
{
let mut fs = fs.borrow_mut();
visitor::pass0::visit_project(
Expand Down
1 change: 1 addition & 0 deletions src/codegen/sb3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@ impl Sb3 {
property,
span,
} => self.property(s, d, this_id, parent_id, object, property, span),
Expr::Ternary { .. } => unreachable!(),
}
}
}
Expand Down
197 changes: 104 additions & 93 deletions src/parser/grammar.lalrpop

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ pub mod pass1;
pub mod pass2;
pub mod pass3;
pub mod pass4;
pub mod ternary;
mod transformations;
4 changes: 4 additions & 0 deletions src/visitor/pass0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{
diagnostic::SpriteDiagnostics,
misc::SmolStr,
vfs::VFS,
visitor::ternary::extract_ternary_from_stmts,
};

struct V<'a> {
Expand Down Expand Up @@ -58,6 +59,7 @@ fn visit_sprite(
.proc_locals
.insert(proc.name.clone(), Default::default());
let proc_definition = sprite.proc_definitions.get_mut(&proc.name).unwrap();
extract_ternary_from_stmts(proc_definition);
visit_stmts(
proc_definition,
&mut V {
Expand Down Expand Up @@ -86,6 +88,7 @@ fn visit_sprite(
);
}
let func_definition = sprite.func_definitions.get_mut(&func.name).unwrap();
extract_ternary_from_stmts(func_definition);
visit_stmts(
func_definition,
&mut V {
Expand All @@ -96,6 +99,7 @@ fn visit_sprite(
);
}
for event in &mut sprite.events {
extract_ternary_from_stmts(&mut event.body);
visit_stmts(
&mut event.body,
&mut V {
Expand Down
1 change: 1 addition & 0 deletions src/visitor/pass1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ fn visit_expr(expr: &mut Expr, before: &mut Vec<Stmt>, s: &mut S) {
visit_expr(object, before, s);
None
}
Expr::Ternary { .. } => unreachable!(),
};
if let Some(replace) = replace {
*expr = replace;
Expand Down
1 change: 1 addition & 0 deletions src/visitor/pass2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ fn visit_expr(expr: &mut Expr, s: S, d: D) {
Expr::Property { object, .. } => {
visit_expr(object, s, d);
}
Expr::Ternary { .. } => unreachable!(),
}
transformations::apply(expr, |expr| transformations::enum_field_access(expr, s, d));
transformations::apply(expr, transformations::minus);
Expand Down
1 change: 1 addition & 0 deletions src/visitor/pass3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,5 +242,6 @@ fn visit_expr(expr: &Expr, s: &mut S) {
} => {
visit_expr(object, s);
}
Expr::Ternary { .. } => unreachable!(),
}
}
Loading
Loading